<template>
  <div
    :class="[
      { 'is-disabled': isDisabled },
      'pagination-container btn-group'
    ]"
  >
    <TfButton
      :disabled="value === 1 || isDisabled"
      data-test="select previous page"
      type="secondary"
      size="text-icon"
      icon="angle-left"
      @mousedown="$event.preventDefault()"
      @click="$emit('input', value - 1)"
    />
    <TfButton
      v-for="page in pages"
      :key="page"
      :class="{ active: page === value }"
      :data-test="`select page ${page}`"
      :disabled="page === value || isDisabled"
      size="text"
      type="secondary"
      @mousedown="$event.preventDefault()"
      @click="$emit('input', page)"
      v-text="page"
    />
    <TfButton
      :disabled="value === totalPages || isDisabled"
      data-test="select next page"
      type="secondary"
      size="text-icon"
      icon="angle-right"
      @mousedown="$event.preventDefault()"
      @click="$emit('input', value + 1)"
    />
  </div>
</template>
<script>
  /**
   * TfPagination is a component used to render a button for each of the pages of the totalPages that is passed down.
   * It uses the v-model/:value from the parent and $emits the model changes to the parent.
   *
   * @vuedoc
   * @exports TfPagination
   * @category Components
   */
  export default {
    name: 'TfPagination',
    props: {
      isDisabled: {
        type: Boolean,
        default: false,
      },
      totalPages: {
        type: Number,
        required: true,
      },
      value: {
        type: Number,
        required: true,
      },
      truncatedPageRange: {
        type: Number,
        default: 0,
        validator: (value) => Boolean(value % 2 || value === 0),
      },
    },
    computed: {
      /**
       * Returns an array or page numbers based on the total pages.
       *
       * @returns {Array}
       */
      pages() {
        const pages = [...Array(this.totalPages).keys()].map((i) => i + 1);

        if (!this.truncatedPageRange || this.totalPages <= this.truncatedPageRange) {
          return pages;
        }
        const activePage = this.value;

        // Half Range is the amount of pages on either side of the current page
        const halfRange = Math.floor(this.truncatedPageRange / 2);

        /**
         * truncated pages should always be half the desired range on the right and left of the active page if there are enough pages on either side.
         * if one side cannot show up to desired pages, display more pages on the other side i.e. range = 5 pages, active page = 2, can only
         * show 1 page to the left so show 3 more pages to the right to fulfill the 5 page range desired (1 [2] 3 4 5)
         */

        // Find the end of the page range
        let end = activePage + halfRange;

        // store excess indices in remainder if end exceeds total pages
        const remainder = Math.max(end - this.totalPages, 0);

        // Find the starting index of page range, which is the active page minus halfRange, minus the remainder if any, minus 1 (0 index)
        let start = activePage - halfRange - remainder - 1;

        // If start is negative we know it should just start at 0 and the end will be the length of the range.
        if (start < 0) {
          start = 0;
          end = this.truncatedPageRange;
        }

        return pages.slice(start, end);
      },
    },
  };
</script>

<style lang="scss" scoped>
  @import 'src/assets/styles/variables';

  .tf-button.tf-button--secondary {
    padding: 6px 10px;
    line-height: 14px;
    border-radius: 2px;

    &:not(.is-disabled) {
      color: $tf-dark-blue;
    }

    &.active {
      cursor: default;

      .pagination-container:not(.is-disabled) & {
        color: $tf-blue;
        background: $tf-light-blue;
      }
    }

    &:focus {
      outline: -webkit-focus-ring-color auto 1px;
    }

    + .tf-button {
      margin-left: 4px;
    }
  }
</style>
