<script setup lang="ts">
import { useElementSize } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import { ref, computed } from 'vue'
import { isMobileView } from '~/composables/screen'
import { preventNonNumeric } from '~/utils/event-validators'

const { t } = useI18n()

const pages = defineProp<number>('pages', {
  required: true,
  validator: (value: number) => value > 0
})

const page = defineModel<number>('page', {
  required: true,
  validator: (value: number) => value > 0
})

const goTo = ref<number>()

const range = (start: number, end: number) => Array.from({ length: end - start + 1 }, (_, i) => i + start)

const renderPages = computed(() => {
  const start = range(2, 5)
  const end = range(pages.value - 4, pages.value - 1)

  const pagesArray = [1]

  if (page.value < 5) pagesArray.push(...start)
  if (page.value >= 5 && page.value <= pages.value - 4) {
    pagesArray.push(page.value - 1)
    pagesArray.push(page.value)
    pagesArray.push(page.value + 1)
  }
  if (page.value > pages.value - 4) pagesArray.push(...end)
  pagesArray.push(pages.value)

  return pagesArray.filter((page, index, pages) => pages.indexOf(page) === index)
})

const pagination = ref()
const { width } = useElementSize(pagination)
const isSmall = isMobileView(width)

const setPage = () => {
  if (goTo.value == null) return
  page.value = Math.min(pages.value, Math.max(1, goTo.value))
}
</script>

<template>
  <nav ref="pagination" :aria-label="t('vui.aria.pagination.nav')" :class="{ 'is-small': isSmall }"
    class="funkwhale pagination" role="navigation">
    <ul class="pages">
      <li>
        <fw-button @click="page -= 1" :disabled="page <= 1" :aria-label="t('vui.aria.pagination.gotoPrevious')"
          color="secondary" outline>
          <i class="bi bi-chevron-left" />
          <span v-if="!isSmall">{{ t('vui.pagination.previous') }}</span>
        </fw-button>
      </li>

      <template v-if="!isSmall">
        <template v-for="(i, index) in renderPages" :key="i">
          <li>
            <fw-button v-if="i <= pages && i > 0 && pages > 3" @click="page = i" color="secondary"
              :aria-label="page !== i ? t('vui.aria.pagination.gotoPage', i) : t('vui.aria.pagination.currentPage', page)"
              :outline="page !== i">
              {{ i }}
            </fw-button>
          </li>
          <li v-if="i + 1 < renderPages[index + 1]">…</li>
        </template>
      </template>
      <template v-else>
        <li>
          <fw-button @click="page = 1" color="secondary"
            :aria-label="page !== 1 ? t('vui.aria.pagination.gotoPage', page) : t('vui.aria.pagination.currentPage', page)"
            :outline="page !== 1">
            1
          </fw-button>
        </li>
        <li v-if="page === 1 || page === pages">…</li>
        <li v-else>
          <fw-button color="secondary" :aria-label="t('vui.aria.pagination.currentPage', page)" aria-current="true">
            {{ page }}
          </fw-button>
        </li>
        <li>
          <fw-button @click="page = pages" color="secondary"
            :aria-label="page !== pages ? t('vui.aria.pagination.gotoPage', page) : t('vui.aria.pagination.currentPage', page)"
            :outline="page !== pages">
            {{ pages }}
          </fw-button>
        </li>
      </template>

      <li>
        <fw-button @click="page += 1" :disabled="page >= pages" :aria-label="t('vui.aria.pagination.gotoNext')"
          color="secondary" outline>
          <span v-if="!isSmall">{{ t('vui.pagination.next') }}</span>
          <i class="bi bi-chevron-right" />
        </fw-button>
      </li>
    </ul>

    <div class="goto">
      {{ t('vui.go-to') }}
      <fw-input :placeholder="page.toString()" @keyup.enter="setPage" @keydown="preventNonNumeric"
        v-model.number="goTo" />
    </div>
  </nav>
</template>

<style lang="scss">
@import './style.scss'
</style>
