<template>
  <ul :class="pickerMode ? 'picker-mode' : ''">
    <!-- Previous arrow -->
    <li v-if="currentPage > 0">
      <a @click="goTo(currentPage - 1)">&lt; prev</a>
    </li>

    <!-- First Page -->
    <li v-if="firstPage !== null">
      <a @click="goTo(0)">{{ 1 }}</a>
    </li>

    <!-- Before elipse (if needed) -->
    <li v-if="beforeElipse">
      <a @click="goTo(pages[0] - 1)">...</a>
    </li>

    <!-- Pages -->
    <li
      v-for="pg in pages"
      :key="pg"
    >
      <template v-if="currentPage === pg">
        <span>{{ pg + 1 }}</span>
      </template>
      <template v-else>
        <a @click="goTo(pg)">{{ pg + 1 }}</a>
      </template>
    </li>

    <!-- After elipse -->
    <li v-if="afterElipse">
      <a @click="goTo(pages[pages.length-1] + 1)">...</a>
    </li>

    <!-- Last Page -->
    <li v-if="lastPage !== null">
      <a @click="goTo(lastPage)">{{ lastPage+1 }}</a>
    </li>

    <!-- Next link -->
    <li v-if="currentPage < pagesSize-1">
      <a @click="goTo(currentPage + 1)">next ></a>
    </li>
  </ul>
</template>
<script>

export default {
  props: {
    total: {
      required: true,
      type: Number
    },
    limit: {
      required: true,
      type: Number
    },
    offset: {
      required: true,
      type: Number
    },
    groupSize: {
      type: Number,
      default: 10
    },
    pickerMode: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    /**
     * total number of pages (before truncation)
     * @return {number}
     */
    pagesSize() {
      return Math.ceil(this.total / this.limit);
    },

    /**
     * current page based on offset
     * @return {number}
     */
    currentPage() {
      return Math.floor(this.offset / this.limit);
    },

    /**
     * half the groupSize (rounded down)
     * @return {number}
     */
    halfGroupSize() {
      return Math.floor(this.groupSize / 2);
    },

    /**
     * early check to see if truncation is needed
     * @return {Boolean}
     */
    hasElipses() {
      return this.pagesSize > this.groupSize + 2;
    },

    /**
     * array of linked pages after truncation
     * @return {number[]}
     */
    pages() {
      const out = [],
        start = Math.max(this.currentPage - this.halfGroupSize, 0),
        end = Math.min(start + this.groupSize, this.pagesSize - 1);

      for (let x = start; x <= end; x++) {
        out.push(x);
      }
      return out;
    },

    /**
     * the ... appearing between the first page and the pages array
     * @return {string} - ''|...
     */
    beforeElipse() {
      return this.hasElipses && this.pages[0] > 1 ? '...' : '';
    },

    /**
     * the ... appearing between the last page of the pages array and the last page
     * @return {string} - ''|...
     */
    afterElipse() {
      return this.hasElipses
          && this.pages[this.pages.length - 1] < this.pagesSize - 1
        ? '...'
        : '';
    },

    /**
     * first page null if contained in pages array
     * @return {number|null}
     */
    firstPage() {
      return this.pages[0] > 0 ? 0 : null;
    },

    /**
     * last page null if contained in pages array
     * @return {number|null}
     */
    lastPage() {
      return this.pages[this.pages.length - 1] >= this.pagesSize - 1
        ? null
        : this.pagesSize - 1;
    }
  },
  methods: {
    /**
     * Emits to parent that offset should change
     * this will trigger rerender and "page" (offset * limit) will update
     * @param {number} page - page to go to
     */
    goTo(page = 1) {
      this.$emit('setOffset', page * this.limit);
    }
  }
};
</script>
<style lang="scss" scoped>
  @import 'Styles/fonts.scss';

  ul {
    font-size: 1.25em;
    list-style-type: none;
    margin: 1em auto 3em;
    padding: 0;
    text-align: center;

    &.picker-mode {
      font-size: $standard-font-size;
      margin: 1em auto;
    }
  }
  li {
    display: inline;
  }
  a,
  span {
    display: inline-block;
    margin: 0 0.3em;
    padding: 0.2em;
  }
  a {
    cursor: pointer;

    &:hover {
      text-decoration: underline;
    }
  }
  span {
    font-weight: bold;
  }
</style>
