<script setup>
import { ref, watch } from 'vue'
import MDIcon from '../MDIcon/MDIcon.vue'

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({
      year: new Date().getFullYear(),
      month: new Date().getMonth() + 1,
      day: new Date().getDate(),
      dayOfWeek: new Date().getDay(),
    }),
  },
})

const emit = defineEmits(['update:modelValue'])

const daysJa = ['日', '月', '火', '水', '木', '金', '土']

// 選択されている年を定義する
const selectYear = ref(props.modelValue.year)
// 選択されている月を定義する
const selectMonth = ref(props.modelValue.month)
// 選択されている日を定義する
const selectDay = ref(props.modelValue.day)
// 選択されている曜日を定義する
const selectDayOfWeek = ref(daysJa[props.modelValue.dayOfWeek])

// 前月の日配列を生成する
const backMonthDayArr = ref([])
// 選択されている年月のカレンダーを生成する
const selectMonthDayArr = ref([])

const animation = ref(false)

// カレンダーを選択した場合、再計算する
function recalculateDays() {
  animation.value = true
  // 前月の日配列をリセットする
  backMonthDayArr.value = []
  // 月初の曜日を取得
  const startDayOfWeek = new Date(selectYear.value, selectMonth.value - 1).getDay()
  // 前月の月末日を取得する
  const backMonthEndDay = new Date(selectYear.value, selectMonth.value - 1, 0).getDate()
  for (let i = 0; i < backMonthEndDay; i++) {
    backMonthDayArr.value.push({ day: i + 1 })
  }
  if (startDayOfWeek === 0) {
    backMonthDayArr.value = []
  } else {
    backMonthDayArr.value = backMonthDayArr.value.slice(-startDayOfWeek)
  }

  // 選択されている年月のカレンダーをリセットする
  selectMonthDayArr.value = []
  // 今月末日を取得
  const endDay = new Date(selectYear.value, selectMonth.value, 0).getDate()
  for (let i = 0; i < endDay; i++) {
    // 日付ごとの曜日ナンバーを取得する
    const targetDayOfWeek = new Date(selectYear.value, selectMonth.value - 1, i + 1).getDay()
    selectMonthDayArr.value.push({
      year: selectYear.value,
      month: selectMonth.value,
      day: i + 1,
      dayOfWeek: targetDayOfWeek,
    })
  }
  setTimeout(function removeAnimation() {
    animation.value = false
  }, 300)
}

recalculateDays()

watch(selectYear, () => recalculateDays())
watch(selectMonth, () => recalculateDays())

// 日付をクリックした場合
const clickDate = (dateObject) => {
  // 選択されている年をセットする
  selectYear.value = dateObject.year
  // 選択されている月をセットする
  selectMonth.value = dateObject.month
  // 選択されている日をセットする
  selectDay.value = dateObject.day
  // 選択されている曜日をセットする
  selectDayOfWeek.value = daysJa[dateObject.dayOfWeek]
  emit('update:modelValue', {
    year: selectYear.value,
    month: selectMonth.value,
    day: selectDay.value,
    dayOfWeek: selectDayOfWeek.value,
  })
}

// 前年選択ボタンをクリック
const selectBackYear = () => {
  selectYear.value = selectYear.value - 1
}
// 翌年選択ボタンをクリック
const selectNextYear = () => {
  selectYear.value = selectYear.value + 1
}
// 前月選択ボタンをクリック
const selectBackMonth = () => {
  selectMonth.value = selectMonth.value - 1
  if (selectMonth.value < 1) {
    selectMonth.value = 12
    selectYear.value = selectYear.value - 1
  }
}
// 翌月選択ボタンをクリック
const selectNextMonth = () => {
  selectMonth.value = selectMonth.value + 1
  if (selectMonth.value > 12) {
    selectMonth.value = 1
    selectYear.value = selectYear.value + 1
  }
}
</script>

<template>
  <!-- 外枠 -->
  <div class="_box">
    <!-- ヘッダー -->
    <div class="_header _primary">
      <div>
        <!-- 対象の年 -->
        <div class="_target_year">{{ modelValue.year }}</div>
        <!-- 対象の月/日/曜日 -->
        <div class="_target_date">
          {{ modelValue.month }}月{{ modelValue.day }}日（{{ selectDayOfWeek }}）
        </div>
      </div>
    </div>

    <!-- カレンダーエリア -->

    <!-- 選択された年/月/日/のコンテナ -->
    <div class="_select_date_container">
      <!-- 選択された年月の共通コンテナ -->
      <div class="_select_common_container">
        <!-- 月左矢印 -->
        <MDIcon name="chevron_left" class="_arrow_left" @click="selectBackYear" />
        <!-- 選択された年 -->
        <div class="_select_year_month_text_common">{{ selectYear }}</div>
        <!-- 月右矢印 -->
        <MDIcon name="chevron_right" class="_arrow_right" @click="selectNextYear" />
      </div>

      <!-- 選択された年月の共通コンテナ -->
      <div class="_select_common_container _month_position">
        <!-- 月左矢印 -->
        <MDIcon name="chevron_left" class="_arrow_left" @click="selectBackMonth" />
        <!-- 選択された月 -->
        <div class="_select_year_month_text_common">{{ selectMonth }}月</div>
        <!-- 月右矢印 -->
        <MDIcon name="chevron_right" class="_arrow_right" @click="selectNextMonth" />
      </div>
    </div>

    <!-- 曜日タイトルコンテナ -->
    <div class="_day_of_week_container">
      <div class="_dow_title_common">日</div>
      <div class="_dow_title_common">月</div>
      <div class="_dow_title_common">火</div>
      <div class="_dow_title_common">水</div>
      <div class="_dow_title_common">木</div>
      <div class="_dow_title_common">金</div>
      <div class="_dow_title_common">土</div>
    </div>

    <!-- 日/表示エリア -->
    <!-- 日コンテナ -->
    <div class="_day_container" :class="{ _animation: animation }">
      <!-- 前月の日配列 -->
      <div v-for="b in backMonthDayArr" :key="b.day" class="_hide_day">
        {{ b.day }}
      </div>

      <!-- 対象日 -->
      <div
        v-for="item in selectMonthDayArr"
        :key="`${item.year}-${item.month}-${item.day}`"
        class="_target_day"
        :class="{
          [`_primary`]:
            modelValue.year === item.year &&
            modelValue.month === item.month &&
            modelValue.day === item.day,
        }"
        @click="clickDate(item)"
      >
        {{ item.day }}
      </div>
    </div>
  </div>
</template>

<style lang="sass" scoped>
/* メインカラー */
._primary
  background: var(--q-primary, #3c4d58)
  color: #ffffff
// 外枠
._box
  position: relative
  z-index: 10000
  height: 280px
  width: 195px
  box-shadow: 0 0 8px -2px gray
  background: #ffffff

// ヘッダー
._header
  height: 50px
  font-weight: 600
  padding: 0 15px
  display: flex
  align-items: center

// 対象の年
._target_year
  font-size: 12px
  opacity: 0.7

// 対象の月/日/曜日
._target_date
  font-size: 14px

// 選択された年/月/日/のコンテナ
._select_date_container
  display: flex
  height: 40px
  padding: 0px 15px

// 選択された年月の共通コンテナ
._select_common_container
  width: 75px
  display: flex
  align-items: center
  justify-content: center
  position: relative
  opacity: 0.7
._month_position
  margin-left: auto
._select_year_month_text_common
  font-size: 12px

// 左矢印
._arrow_left
  position: absolute
  font-size: 16px
  left: 0
  border-radius: 25px
  cursor: pointer
  transition: 0.3s
._arrow_left:hover
  background: #DDDDDD
._arrow_left:active
  background: #cccccc

// 右矢印
._arrow_right
  position: absolute
  font-size: 16px
  right: 0
  border-radius: 25px
  cursor: pointer
  transition: 0.3s
._arrow_right:hover
  background: #DDDDDD
._arrow_right:active
  background: #cccccc

// 曜日タイトルコンテナ
._day_of_week_container
  width: fit-content
  font-size: 10px
  opacity: 0.7
  display: grid
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr
  gap: 5.5px
  margin: 5px auto
._dow_title_common
  width: 20px
  text-align: center

// 日コンテナ
._day_container
  width: fit-content
  font-size: 10px
  display: grid
  grid-template-columns: 25px 25px 25px 25px 25px 25px 25px
  gap: 0px
  margin: 0 auto
._testTest
  background: yellow

// 対象日
._target_day
  height: 25px
  width: 25px
  display: flex
  justify-content: center
  align-items: center
  border-radius: 25px
  cursor: pointer
  transition: 0.3s
._target_day:hover
  background: #DDDDDD
._target_day:active
  background: #cccccc

// 選択した日付の表示
._target_day._primary:hover
  background: var(--q-primary, #3c4d58)
  opacity: .7
._target_day._primary:active
  background: var(--q-primary, #3c4d58)
  opacity: .5

// 非表示の日付（前月/翌月）
._hide_day
  opacity: 0
  cursor: default

// カレンダーの日付更新時のアニメーション
._animation
  animation: changeShow .3s 1 ease-in-out

@keyframes changeShow
  0%
    opacity: 1
  50%
    opacity: 0
  100%
    opacity: 1
</style>
