<template>
  <div v-if="pageCount > 1" class="pagination">
    <div class="pagination-content">
      <!-- 总数 -->
      <span class="pagination-info">共 <em>{{ modelValue.total }}</em> 条</span>
      <ul>
        <!-- 上一页 -->
        <li :class="{ disabled: modelValue.page <= 1 }">
          <el-icon v-if="modelValue.page <= 1"><ArrowLeft/></el-icon>
          <nuxt-link v-else :to="getPageUrl(modelValue.page - 1)">
            <el-icon><ArrowLeft/></el-icon>
          </nuxt-link>
        </li>
        <!-- 前置分页 -->
        <li
          v-for="pageIndex in prevPages"
          :key="pageIndex"
          :class="{ selected: pageIndex === modelValue.page }"
        >
          <nuxt-link :to="getPageUrl(pageIndex)">{{ pageIndex }}</nuxt-link>
        </li>
        <!-- 前置翻页器：存在中间页码 || 完全展示了后置页码 -->
        <li v-if="centerPages.length > 0 || afterPages.length === limitPageCount" class="page-control">
          <nuxt-link :to="getPageUrl(modelValue.page-limitPageCount < 1 ? 1 : modelValue.page-limitPageCount)">
            <span>...</span>
            <el-icon><DArrowLeft /></el-icon>
          </nuxt-link>
        </li>
        <!-- 中间分页 -->
        <li
          v-for="pageIndex in centerPages"
          :key="pageIndex"
          :class="{ selected: pageIndex === modelValue.page }"
        >
          <nuxt-link :to="getPageUrl(pageIndex)">{{ pageIndex }}</nuxt-link>
        </li>
        <!-- 后置翻页器：存在中间页码 || 完全展示了前面的页码但总页数要大于前方展示的页码数 -->
        <li v-if="centerPages.length > 0 || (prevPages.length === limitPageCount && pageCount > limitPageCount)" class="page-control">
          <nuxt-link :to="getPageUrl(modelValue.page+limitPageCount > pageCount ? pageCount : modelValue.page+limitPageCount)">
            <span>...</span>
            <el-icon><DArrowRight /></el-icon>
          </nuxt-link>
        </li>
        <!-- 后置分页 -->
        <li
          v-for="pageIndex in afterPages"
          :key="pageIndex"
          :class="{ selected: pageIndex === modelValue.page }"
        >
          <nuxt-link :to="getPageUrl(pageIndex)">{{ pageIndex }}</nuxt-link>
        </li>
        <!-- 下一页 -->
        <li :class="{ disabled: modelValue.page >= pageCount }">
          <el-icon v-if="modelValue.page >= pageCount"><ArrowRight /></el-icon>
          <nuxt-link v-else :to="getPageUrl(modelValue.page + 1)">
            <el-icon><ArrowRight/></el-icon>
          </nuxt-link>
        </li>
      </ul>
      <!-- 跳转 -->
      <div class="pagination-info pagination-jump">
        前往
        <el-input-number
          v-model="targetPage"
          :controls="false"
          :max="pageCount"
          @keydown.enter="jump"
        />
        页
      </div>
    </div>
  </div>
</template>

<script>
import { ArrowLeft, DArrowLeft, ArrowRight, DArrowRight } from '@element-plus/icons-vue'

export default {
  name: 'Pagination',
  components: { ArrowLeft, DArrowLeft, ArrowRight, DArrowRight },
  emits: ['update:modelValue', 'page-change'],
  props: {
    // 分页值，e.g: { page: 1, capacity: 10, total: 100 }
    modelValue: {
      type: Object,
      required: true,
      default: function () {
        return {}
      }
    },
    // 获取页码链接函数
    getPageUrl: {
      type: Function,
      default: function (page) {
        return `?page=${page}`
      }
    },
    // 最多一次性展示多少个页码
    limitPageCount: {
      type: Number,
      default: 5
    }
  },
  data () {
    return {
      targetPage: 1,
    }
  },
  computed: {
    // 最大同时展示的页码数量，其中4 = 首页 + 页面控制按钮 + 尾页 + 页面控制按钮
    maxPageCount () {
      return this.limitPageCount + 4
    },
    // 总页数
    pageCount () {
      return Math.ceil(this.modelValue.total / this.modelValue.capacity)
    },
    // 中间数
    limitPageCountHalf () {
      return Math.floor(this.limitPageCount / 2)
    },
    // 前置分页
    prevPages () {
      // 总页不超过maxPageCount，全部展示
      if (this.pageCount <= this.maxPageCount) {
        return new Array(this.pageCount)
          .fill(0)
          .map((item, index) => index + 1)
      }
      // 当前页码在头部（即当前页码 <= limitPageCount）
      if (this.modelValue.page < this.limitPageCount) {
        return new Array(this.limitPageCount)
          .fill(0)
          .map((item, index) => index + 1)
      }
      return [1]
    },
    // 中间分页，展示5条
    centerPages () {
      if (this.pageCount <= this.maxPageCount) {
        return []
      }
      // 当前页码不在头和尾部（即当前页码 > limitPageCount && 当前页码 < pageCount - limitPageCount）
      if (this.modelValue.page >= this.limitPageCount && this.modelValue.page <= this.pageCount - this.limitPageCount + 1) {
        const pages = []
        for (let i = 0; i < this.limitPageCount; i++) {
          // 中间页面
          if (i === this.limitPageCountHalf) {
            pages.push(this.modelValue.page)
            continue
          }
          // 左右两侧页码
          pages.push(this.modelValue.page - this.limitPageCountHalf + i)
        }
        return pages
      }
      return []
    },
    // 后置分页
    afterPages () {
      if (this.pageCount <= this.maxPageCount) {
        return []
      }
      // 当前页码在尾部（当前页码 >= pageCount - limitPageCount + 1）
      if (this.modelValue.page > this.pageCount - this.limitPageCount + 1) {
        return new Array(this.limitPageCount)
          .fill(0)
          .map((item, index) => {
            return this.pageCount - this.limitPageCount + index + 1
          })
      }
      return [this.pageCount]
    }
  },
  watch: {
    // 监听分页数据发生变化，刷新目标页码
    'modelValue.page': {
      immediate: true,
      handler (newValue) {
        if (this.targetPage !== newValue) {
          this.targetPage = newValue
          this.$router.replace(this.getPageUrl(newValue))
        }
      }
    }
  },
  methods: {
    // 跳转指定页
    jump () {
      if (this.targetPage < 1) {
        this.targetPage = 1
      }
      this.$router.push(this.getPageUrl(this.targetPage))
    }
  }
}
</script>

<style scoped lang="scss">
.pagination {
  --page-item-size: 35px;
  width: 100%;
  text-align: center;
  .pagination-content {
    width: 800px;
    overflow: hidden;
    margin: 0 auto;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  // 页码列表
  ul {
    display: flex;
    margin: 0 30px;
    li {
      width: var(--page-item-size);
      height: var(--page-item-size);
      background: var(--background-color);
      margin-right: 3px;
      display: flex;
      justify-content: center;
      align-items: center;
      a {
        display: block;
        width: 100%;
        height: 100%;
        line-height: var(--page-item-size);
        text-align: center;
        color: #333;
        &:hover {
          color: var(--primary-color);
        }
        .el-icon {
          position: relative;
          top: 2px;
        }
      }
      // 选中状态
      &.selected {
        a {
          color: var(--color-white);
          background: var(--primary-color);
          &:hover {
            color: var(--color-white);
          }
        }
      }
      // 禁用状态
      &.disabled {
        color: var(--color-gray);
        cursor: not-allowed;
      }
      // 页面控制
      &.page-control {
        a {
          display: flex;
          justify-content: center;
          align-items: center;
        }
        .el-icon {
          display: none;
          position: relative;
          top: 0;
        }
        &:hover {
          span {
            display: none;
          }
          .el-icon {
            display: block;
          }
        }
      }
    }
  }
  // 附加信息
  .pagination-info {
    color: var(--color-gray);
    em {
      color: var(--font-color);
      font-style: normal;
    }
  }
  // 跳转
  .pagination-jump {
    display: flex;
    align-items: center;
    .el-input-number {
      width: 70px;
      text-align: center;
      margin: 0 10px;
    }
  }
}
</style>
