<template>
  <div ref="calerRef" class="caler">
    <div class="caler-wrapper" :class="[wrapperClass]">
      <div v-if="arrowUpOrDown" class="caler-top">
        <button :disabled="prevMonthBtn" class="caler-top-left" @click="onChangeMonth(-1)">
          <span :class="{ disabled: prevMonthBtn }" />
        </button>
        <div class="caler-top-dateTxt">
          {{ parseTime(new Date(currentYear, currentMonth - 1), '{y}年{m}月') }}
        </div>
        <button :disabled="nextMonthBtn" class="caler-top-right" @click="onChangeMonth(1)">
          <span :class="{ disabled: nextMonthBtn }" />
        </button>
      </div>
      <div class="caler-week">
        <div v-for="item in weekList" :key="item" class="caler-week-item">{{ item }}</div>
      </div>
      <div class="caler-info">
        <div
          v-for="item in arrowUpOrDown ? renderDateList : currentWeekList"
          :key="item.time"
          :class="renderClass(item)"
          :data-time="item.time"
          @click="onClickDate(item)"
        >
          <div class="caler-info-item__text">
            <span>{{ item.value }}</span>
            <i v-if="item.dot" class="dot" />
          </div>
        </div>
      </div>
    </div>

    <div class="caler-arrow" :class="arrowUpOrDown ? 'up' : 'down'" @click="triggerEvent" />
  </div>
</template>
<script>
import { parseTime } from '@/service/utils.service';
import * as dTools from '../utils';

const UPDATE_DOWN = 'update-down';
const SELECT_DATE = 'select-time';
// const todayDate = new Date('2023/01/29'); // 今日日期，实际项目中推荐从接口拿服务器日期用
const todayDate = new Date(); // 今日日期，实际项目中推荐从接口拿服务器日期用
const todayZeroDate = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate()); // 今日零点的日期，用于后续转换时间戳后日期大小的比较
export default {
  props: {
    choseDateList: {
      type: Array,
      default: () => []
    },
    countDay: {
      type: Number,
      default: 30
    }
  },
  data() {
    return {
      arrowUpOrDown: false,
      wrapperClass: '',

      currentTime: parseTime(todayZeroDate, '{y}-{m}-{d}'),
      weekList: ['日', '一', '二', '三', '四', '五', '六'],
      currentYear: todayZeroDate.getFullYear(),
      currentMonth: todayZeroDate.getMonth() + 1,
      renderDateList: [],
      currentWeekList: []
    };
  },
  computed: {
    currentMonthTime() {
      return dTools.getCurrentMonth(todayZeroDate.getFullYear(), todayZeroDate.getMonth());
    },
    countDayTime() {
      return +new Date(+todayZeroDate - 86400000 * (this.countDay - 1));
    },
    prevMonthBtn() {
      const start = this.countDayTime;
      if (parseTime(start, '{y}-{m}') === parseTime(+todayZeroDate, '{y}-{m}')) {
        return true;
      }
      const resultTime = dTools.getCurrentMonth(this.currentYear, this.currentMonth - 1);
      return resultTime - start < 0;
    },
    nextMonthBtn() {
      return (
        dTools.getCurrentMonth(this.currentYear, this.currentMonth - 1) >= this.currentMonthTime
      );
    }
  },
  watch: {
    choseDateList() {
      this.renderCakendar();
    },
    arrowUpOrDown() {
      this.getCurrentHeight();
    }
  },
  created() {
    this.renderCakendar();
  },
  mounted() {
    this.getCurrentHeight();
  },
  methods: {
    getCurrentHeight() {
      const upDown = this.arrowUpOrDown;
      const timer = setTimeout(() => {
        clearTimeout(timer);
        const height = this.$refs.calerRef.offsetHeight;
        this.$emit(UPDATE_DOWN, { height, upDown });
      }, 240);
    },
    refresh() {
      this.currentTime = parseTime(todayZeroDate, '{y}-{m}-{d}');
      this.currentYear = todayZeroDate.getFullYear();
      this.currentMonth = todayZeroDate.getMonth() + 1;
      this.renderCakendar();
    },
    parseTime,
    triggerEvent() {
      this.arrowUpOrDown = !this.arrowUpOrDown;
      if (this.arrowUpOrDown) {
        this.wrapperClass = 'caler-down-wrapper';
      } else {
        this.wrapperClass = 'caler-up-wrapper';
      }
      if (!this.currentTime) {
        this.currentTime = parseTime(todayZeroDate, '{y}-{m}-{d}');
        this.currentYear = todayZeroDate.getFullYear();
        this.currentMonth = todayZeroDate.getMonth() + 1;
        this.renderCakendar();
      }
    },

    onChangeYear(num) {
      this.currentYear = this.currentYear + num;
      this.renderCakendar();
    },

    onChangeMonth(num) {
      this.currentTime = parseTime(todayZeroDate, '{y}-{m}-{d}');
      if (this.currentMonth + num <= 0) {
        this.currentYear = this.currentYear - 1;
        this.currentMonth = 12 - (this.currentMonth + num);
      } else if (this.currentMonth + num >= 13) {
        this.currentYear = this.currentYear + 1;
        this.currentMonth = this.currentMonth + num - 12;
      } else {
        this.currentMonth = this.currentMonth + num;
      }
      this.renderCakendar();
    },
    renderClass(item) {
      return {
        'caler-info-item': true,
        current: item.current,
        disabled: item.disabled
      };
    },
    // 点击选中日期的事件
    onClickDate(item) {
      if (item.disabled) return;
      if (!item.dot) {
        if (dTools.getDotDate(item.time) < this.countDayTime) {
          this.$toast('只保留30天之内的记录~');
        } else {
          this.$toast('这一天没有浏览记录~');
        }
        return;
      }
      if (item.current) return;
      this.$emit(SELECT_DATE, item.time);
      this.currentTime = item.time;
      this.renderCakendar();
    },

    getPrevMonthDays() {
      const { currentYear, currentMonth } = this;
      const firstDayOrWeek = dTools.getFirstDayOrWeek(currentYear, currentMonth); // 获取本月1号对应周几
      const prevMonthLastNums = dTools.getDateByMonthOrDays(currentYear, currentMonth - 1); // 获取上个月所有天数
      return prevMonthLastNums.slice(firstDayOrWeek === 0 ? -7 : -firstDayOrWeek).map(value => {
        const time = parseTime(new Date(currentYear, currentMonth - 2, value), '{y}-{m}-{d}');
        // const dot = choseDateList.includes(time);
        // const current = currentTime === time;
        return { time, value, current: false, disabled: true, type: 'prev', dot: false };
      });
    },

    getCurrentMonthDays() {
      const { currentYear, currentMonth, choseDateList, currentTime } = this;
      const currentMonthNums = dTools.getDateByMonthOrDays(currentYear, currentMonth);
      return currentMonthNums.map(value => {
        const itemDate = new Date(currentYear, currentMonth - 1, value);
        const time = parseTime(itemDate, '{y}-{m}-{d}');
        const dot = choseDateList.includes(time);
        // const current = +itemDate === +todayZeroDate;
        const current = currentTime === time;
        return { time, value, current, disabled: false, type: 'current', dot };
      });
    },
    // 初始化日历
    renderCakendar() {
      const { currentYear, currentMonth } = this;
      const prevMonthDays = this.getPrevMonthDays();
      const currentMonthDays = this.getCurrentMonthDays();
      const nextMonthNums = dTools.getDateByMonthOrDays(currentYear, currentMonth + 1);
      const nextMonthDays = nextMonthNums
        .slice(0, 6 * 7 - prevMonthDays.length - currentMonthDays.length)
        .map(value => {
          const time = parseTime(new Date(currentYear, currentMonth, value), '{y}-{m}-{d}');
          // const dot = choseDateList.includes(time);
          // const current = currentTime === time;
          return { time, value, current: false, disabled: true, type: 'next', dot: false };
        });
      const renderDateList = [...prevMonthDays, ...currentMonthDays, ...nextMonthDays];
      this.renderCurrentWeeks(renderDateList);
      this.$set(this, 'renderDateList', renderDateList);
    },
    renderCurrentWeeks(renderDateList) {
      const currentIndex = renderDateList.findIndex(item => item.current); // 获取当前选中的日期下标
      if (currentIndex !== -1) {
        const currentItem = renderDateList[currentIndex]; // 获取当前选中item
        const nowDate = new Date(currentItem.time);
        const nowWeekNum = dTools.getFirstDayOrWeek(
          nowDate.getFullYear(),
          nowDate.getMonth() + 1,
          nowDate.getDate()
        );
        this.currentWeekList = renderDateList.slice(
          currentIndex - nowWeekNum,
          currentIndex + (7 - nowWeekNum)
        );
        return;
      }
      this.currentTime = null;
      this.currentWeekList = [];
    }
  }
};
</script>

<style lang="less" scoped>
.caler {
  .text-size(14);
  padding: 0 12px 10px;
  background-color: #fff;
  position: relative;
  border-radius: 0px 0px 4px 4px;
  border: 1px solid @gray-1;
  border-top: none;
  z-index: 1;
  &-wrapper {
    height: 68px;
    overflow: hidden;
  }
  &-down-wrapper {
    animation: myslideDown 0.2s linear forwards;
  }
  &-up-wrapper {
    animation: myslideUp 0.2s linear forwards;
  }

  &-arrow {
    width: 60px;
    height: 14px;
    background-color: @white;
    background-repeat: no-repeat;
    background-size: 18px 8px;
    background-position: center center;
    border-radius: 7px;
    border: 1px solid #f4f4f4;
    position: absolute;
    bottom: -7px;
    left: 50%;
    margin-left: -30px;
    &.up {
      background-image: url(~@/assets/images/browse/up.png);
    }
    &.down {
      background-image: url(~@/assets/images/browse/down.png);
    }
  }

  &-top {
    .text-size(16);
    color: @black;
    height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 10px;
    &-dateTxt {
      font-weight: 500;
    }
    &-left,
    &-right {
      height: 100%;
      width: 70px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: transparent;
      border: none;
      span {
        border: 5px solid transparent;
      }
    }
    &-left {
      span {
        border-right-color: @black;
        border-right-width: 7px;

        &.disabled {
          border-right-color: @gray-4;
        }
      }
    }
    &-right {
      span {
        border-left-color: @black;
        border-left-width: 7px;
        &.disabled {
          border-left-color: @gray-4;
        }
      }
    }
  }

  &-week {
    color: @gray-4;
    display: flex;
    align-items: center;
    &-item {
      flex: 1;
      text-align: center;
      height: 33px;
      line-height: 33px;
    }
  }

  &-info {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    &-item {
      color: @black;
      height: 34px;
      width: 14.28571%;
      display: flex;
      align-items: center;
      justify-content: center;
      &__text {
        width: 34px;
        height: 34px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        .dot {
          display: block;
          position: absolute;
          bottom: 3px;
          left: 50%;
          transform: translateX(-50%);
          width: 4px;
          height: 4px;
          background-color: #ea4209;
          border-radius: 50%;
        }
      }
      &.disabled {
        color: @gray-4;
      }
      &.current {
        .caler-info-item__text {
          color: @white;
          background-color: #ea4209;
        }
        .dot {
          background-color: @white;
        }
      }
    }
  }
}
@keyframes myslideDown {
  0% {
    height: 68px;
  }
  99% {
    height: 304px;
  }
  100% {
    height: max-content;
  }
}
@keyframes myslideUp {
  0% {
    height: max-content;
  }
  1% {
    height: 304px;
  }
  100% {
    height: 68px;
  }
}
</style>
