<script setup lang="ts">
import { ref, computed, onMounted, PropType } from 'vue'
import { SizeTypes } from '../../types'

const props = defineProps({
  /**
   * 値
   * @example 1
   */
  modelValue: { type: Number, default: 1 },
  /**
   * パターン
   * @example 1
   */
  pattern: { type: Number, default: 1 },
  /**
   * ボタンの最大値
   * @example 10
   */
  max: { type: Number, default: 1 },
  /**
   * ページに表示するボタンの最大値
   * @example 5
   */
  maxPages: { type: Number, default: 1 },
  /**
   * サイズ
   * @example 'S' | 'L'
   */
  size: { type: String as PropType<SizeTypes>, default: 'L' },
})

const emit = defineEmits<{
  (e: 'update:modelValue', val: number): void
}>()

const model = computed({
  get: () => props.modelValue,
  set: (value) => {
    emit('update:modelValue', value)
  },
})

// 全てのボタン数配列を定義する
const isBtnAllNumArray = ref<number[]>([])

// 表示するボタン数配列を定義する
const isBtnDispNumArray = ref<number[]>([])

onMounted(() => {
  // ボタンの最大値が未設定の場合、全てのボタン数配列に1を追加する
  if (!props.max) {
    isBtnAllNumArray.value.push(1)
    return
  }

  // 全てのボタン数配列にprops.max分の数字を追加する
  for (let i = 1; i < props.max + 1; i++) {
    isBtnAllNumArray.value.push(i)
  }

  // 全てのボタン数配列へページに表示するボタンの最大値分フィルターをかけて、表示するボタン数配列へ代入する
  isBtnDispNumArray.value = isBtnAllNumArray.value.filter((num) => num <= props.maxPages)
})

// pattern1
// 番号ボタンをクリックする
const clickBtnNum = (selectNum: number) => {
  // 選択された数字をmodelへ代入する
  model.value = selectNum

  // 配列の中央を定義する
  const centerIndex = Math.round(isBtnDispNumArray.value.length / 2 - 1)

  // 選択されたボタン数より上のループ処理回数を定義する
  let upperCounter = 0
  // 選択されたボタン数より下のループ処理回数を定義する
  let underCounter = 0
  if (props.maxPages % 2 === 0) {
    upperCounter = props.maxPages - centerIndex
    underCounter = props.maxPages - centerIndex - 1
  } else {
    upperCounter = props.maxPages - centerIndex
    underCounter = props.maxPages - centerIndex
  }

  // 選択されたボタン数より上の数字配列を生成する
  const upperNumArr = ref<number[]>([])
  for (let i = 1; i < upperCounter; i++) {
    if (selectNum + i <= props.max) {
      upperNumArr.value.push(selectNum + i)
    } else {
      underCounter++
    }
  }

  // 選択されたボタン数より下の数字配列を生成する
  const underNumArr = ref<number[]>([])
  for (let i = 1; i < underCounter; i++) {
    underNumArr.value.unshift(selectNum - i)
  }

  // 選択されたボタンのみ配列に格納する
  const selectNumArr = ref<number[]>([selectNum])

  // 選択されたボタンの値を元に、新いボタン配列を生成する
  const newBtnDispNumArray = ref<number[]>([
    ...underNumArr.value,
    ...selectNumArr.value,
    ...upperNumArr.value,
  ])

  if (newBtnDispNumArray.value[0] <= 0) {
    // 新いボタン配列のindex0の値が0を含む低い数字になった場合props.maxPages分フィルターをかけて変数へ代入する
    isBtnDispNumArray.value = isBtnAllNumArray.value.filter((num) => num <= props.maxPages)
  } else {
    // 新いボタン配列を変数へ代入する
    isBtnDispNumArray.value = newBtnDispNumArray.value
  }
}

// 左ボタンをクリック
const clickArrowLeft = (pattern: number) => {
  if (model.value === 1) return
  model.value--

  // pattern1の場合
  // ボタンの最大値がページに表示するボタンの最大値より大きい場合
  if (pattern === 1 && props.max > props.maxPages) {
    // 表示されているボタン配列の中央の値を定義する
    const centerIndex = Math.round(isBtnDispNumArray.value.length / 2 - 1)
    const centerNum = isBtnDispNumArray.value[centerIndex]

    // 表示されるスタート位置の数字を定義する
    const startNum = isBtnDispNumArray.value.slice(-1)[0] - props.maxPages

    // 表示されるエンド位置の数字を定義する
    const endNum = isBtnDispNumArray.value.slice(-1)[0] - 1

    // 現在地が中央値を超えて、エンド位置以下の場合
    if (model.value === centerNum && startNum > 0) {
      isBtnDispNumArray.value = isBtnAllNumArray.value.filter(
        (num) => num >= startNum && num <= endNum
      )
    }
  }
}

// 右ボタンをクリック
const clickArrowRight = (pattern: number) => {
  if (model.value === props.max) return
  model.value++

  // pattern1の場合
  // ボタンの最大値がページに表示するボタンの最大値より大きい場合
  if (pattern === 1 && props.max > props.maxPages) {
    // 表示されているボタン配列の中央の値を定義する
    const centerIndex = Math.round(isBtnDispNumArray.value.length / 2 - 1)
    const centerNum = isBtnDispNumArray.value[centerIndex]

    // 表示されるスタート位置の数字を定義する
    const startNum = isBtnDispNumArray.value[1]

    // 表示されるエンド位置の数字を定義する
    const endNum = isBtnDispNumArray.value.slice(-1)[0] + 1

    // 現在地が中央値を超えて、エンド位置以下の場合
    if (model.value >= centerNum && endNum < props.max) {
      isBtnDispNumArray.value = isBtnAllNumArray.value.filter(
        (num) => num >= startNum && num <= endNum
      )
    }
    // エンド位置とボタンの最大値が同じ場合
    if (endNum === props.max) {
      isBtnDispNumArray.value = isBtnAllNumArray.value.filter(
        (num) => num >= props.max - props.maxPages + 1 && num <= props.max
      )
    }
  }
}
</script>

<template>
  <div class="_box">
    <div
      class="_arrow_container_common"
      :class="{
        _arrow_container_disabled_common: model === 1,
        _arrow_container_common_size_s: props.size === 's' || props.size === 'S',
      }"
      @click="clickArrowLeft(props.pattern)"
    >
      <div
        class="_arrow_left"
        :class="{
          _arrow_left_size_s: props.size === 's' || props.size === 'S',
        }"
      />
    </div>

    <!-- pattern1 -->
    <div
      v-show="props.pattern === 1"
      v-for="btnNum in isBtnDispNumArray"
      :key="btnNum"
      class="_pattern_1_num_btn"
      :class="{
        _pattern_1_num_btn_active: btnNum === model,
        _pattern_1_num_btn_passive: btnNum !== model,
        _pattern_1_num_btn_size_s: props.size === 's' || props.size === 'S',
      }"
      @click="clickBtnNum(btnNum)"
    >
      {{ btnNum }}
    </div>

    <!-- pattern2 -->
    <div
      v-show="props.pattern === 2"
      class="_pattern_2_num_container"
      :class="{
        _pattern_2_num_container_size_s: props.size === 's' || props.size === 'S',
      }"
    >
      {{ model }} / {{ props.max }}
    </div>

    <div
      class="_arrow_container_common"
      :class="{ _arrow_container_disabled_common: model === props.max }"
      @click="clickArrowRight(props.pattern)"
    >
      <div
        class="_arrow_right"
        :class="{
          _arrow_right_size_s: props.size === 's' || props.size === 'S',
        }"
      />
    </div>
  </div>
</template>

<style lang="sass" scoped>
._box
  display: flex
  align-items: center
  width: fit-content
  font-family: 'Roboto', sans-serif

._pattern_1_num_btn
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
  user-select: none
  height: 40px
  width: 40px
  border-radius: 50%
  display: flex
  justify-content: center
  align-items: center
  cursor: pointer
._pattern_1_num_btn_active
  background: var(--c-primary)
  color: #fff
  font-weight: bold
._pattern_1_num_btn_passive
  background: #fff
  color: var(--c-primary)

._pattern_1_num_btn_size_s
  font-size: 14px
  height: 35px
  width: 35px

._arrow_container_common
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
  width: 40px
  height: 40px
  display: flex
  justify-content: center
  align-items: center
  border-radius: 50%
  cursor: pointer
._arrow_container_disabled_common
  cursor: not-allowed
  opacity: 0.7

._arrow_container_common_size_s
  width: 35px
  height: 35px

._arrow_left
  height: 18px
  width: 18px
  transform: rotate(45deg)
  border-left: solid 5px var(--c-primary)
  border-bottom: solid 5px var(--c-primary)

._arrow_left_size_s
  height: 13px
  width: 13px

._pattern_2_num_container
  user-select: none
  font-size: 20px
  font-weight: bold
  min-width: 87px
  text-align: center
  color: var(--c-primary)

._pattern_2_num_container_size_s
  font-size: 18px

._arrow_right
  height: 18px
  width: 18px
  transform: rotate(45deg)
  border-top: solid 5px var(--c-primary)
  border-right: solid 5px var(--c-primary)

._arrow_right_size_s
  height: 13px
  width: 13px
</style>
