<template>
  <div :class="{'fbg-datetime-box ': true}">
    <div class="fbg-datetime-ym">
      <span class="fbg-datetime-ym-left" v-show="showLeftButton">
        <i class="fbg-icon-d-arrow-left" @click="handlePreYear"/>
        <i class="fbg-icon-arrow-left" @click="handlePreMonth"/>
      </span>
      <span>{{date.year}}年{{date.month}}月</span>
      <span class="fbg-datetime-ym-right" v-show="showRightButton">
        <i class="fbg-icon-arrow-right" @click="handleNextMonth"/>
        <i class="fbg-icon-d-arrow-right" @click="handleNextYear"/>
      </span>
    </div>
    <div class="fbg-datetime-day">
      <ul class="fbg-datetime-day-box">
        <li class="fbg-datetime-day-item">日</li>
        <li class="fbg-datetime-day-item">一</li>
        <li class="fbg-datetime-day-item">二</li>
        <li class="fbg-datetime-day-item">三</li>
        <li class="fbg-datetime-day-item">四</li>
        <li class="fbg-datetime-day-item">五</li>
        <li class="fbg-datetime-day-item">六</li>
      </ul>
      <ul v-for="(item, index) in data" :key="index" class="fbg-datetime-day-box">
        <li v-for="(child) in item" :key="child.month + child.day" @click="handleChooseDateTime(child)" :class="{'fbg-datetime-day-item': true, 'fbg-datetime-day-other': !child.status}">
          <div :key="child.month + child.day" @mouseover="handleHover(child)" :class="{
            'fbg-datetime-day-item-disabled': (child.disabled || (isRange && chooseDate.length === 1 && child.chooseDisabled ) ),
            'fbg-datetime-day-item-box': child.status,
            'fbg-datetime-day-item-range': isInRange(child),
            'fbg-datetime-day-item-range-start': isSameDate(child.stampTime, startTime.stampTime),
            'fbg-datetime-day-item-range-end': isSameDate(child.stampTime, endTime.stampTime),
            'active': isSameDate(child.stampTime, date.todayStampTime)
          }">
            <div :class="{'fbg-datetime-day-item-main': child.status, 'active':  isActive(child), 'disabled': child.chooseDisabled && (isSameDate(child.stampTime, endTime.stampTime)||isSameDate(child.stampTime, startTime.stampTime))}">
              {{child.day}}
            </div>
          </div>
          </li>
        </ul>
      </div>
      <div>
        <time-picker ref="timeRef" v-if="isDateTime" :value="timeValue" @change="handleTimeChange" @onClick="handleTimePickClick"/>
      </div>
  </div>
</template>
<script>
import extendData from '../common/datetimeExtend.js';
import TimePicker from '../timePicker';
import util from '../../utils';

export default {
  extends: extendData,
  components: {
    TimePicker
  },
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    comType: {
      type: String,
      default: 'start'
    },

    value: {
      type: [Date, Number, Array, String],
      default() {
        return new Date();
      }
    },
    type: {
      type: String,
      default: 'date'
    },
    pickerOptions: {
      type: Object,
      default() {
        return {};
      }
    },
    format: {
      type: String,
      default() {
        return util.getDefaultDateType(this.type);
      } 
    },
    valueFormat: {
      type: String,
      default() {
        return util.getDefaultDateType(this.type);
      }
    },
    dateRangeChooseDisabled() {},
    selectDate: {
      type: Array,
      default() {
        return [];
      }
    },
    defaultValue: {
      type: Date,
      default() {
        return null;
      }
    },
    showLeftButton: {
      type: Boolean,
      default: true,
    },
    showRightButton: {
      type: Boolean,
      default: true,
    },
    chooseDate: {
      type:  Array,
      default() {
        return [];
      }
    }
  },
  data() {
    const date = this.initDate();
    const timeValue = this.initTime();
    return {
      data: [],
      showDate: new Date(),
      selectedDate: null,
      startTime: {},
      endTime: {},
      timeValue,
      date
    };
  },
  computed: {
    isDateTime() {
      return this.type === 'datetime' || this.type === 'datetimerange';
    }
  },
  watch: {
    visible: {
      handler(value) {
        if (value === false) {
          this.$refs.timeRef && (this.$refs.timeRef.isShow = false);
        }
      }
    },
    selectDate: {
      immediate: true,
      deep: true,
      handler(arr) {
        this.chooseRange(arr);
      }
    },
    chooseDate: {
      immediate: true,
      deep: true,
      handler(arr) {
        this.updateChooseDisabledStatus(arr);
        this.chooseRange(arr);
      }
    },
    defaultValue: {
      immediate: true,
      handler(value) {
        if (value) {
          this.showDate = value;
        } else if (this.value) {
          this.showDate = this.value;
        }
      }
    },
    showDate: {
      immediate: true,
      handler(date) {
        this.initShowDate(date);
        this.$emit('changeShowDate', date);
      }
    },
    value: {
      immediate: true,
      handler(value) {
        if (this.isRange) {
          if (value.length === 2) {
            const v1 = this.valueToDateTime(value[0], this.valueFormat);
            const v2 = this.valueToDateTime(value[1], this.valueFormat);
            const startDateObj = this.getDateObj(v1); 
            const endDateObj = this.getDateObj(v2);
            let startDate = null;
            let endDate = null;
            if (this.isDateTime) {
              startDate = this.getDateTimeInfo(startDateObj);
              endDate = this.getDateTimeInfo(endDateObj);
            } else {
              startDate = this.getDateInfo(startDateObj);
              endDate = this.getDateInfo(endDateObj);
            }
            if (this.comType === 'start') {
              this.timeValue = this.getTimeObj(startDateObj);
            } else if (this.comType === 'end') {
              this.timeValue = this.getTimeObj(endDateObj);
            }
            this.$set(this.selectDate, 0, startDate);
            this.$set(this.selectDate, 1, endDate);
            this.$set(this.chooseDate, 0, startDate);
            this.$set(this.chooseDate, 1, endDate);
          }
        } else {
          if (value !== '') {
            const v = this.valueToDateTime(value, this.valueFormat);
            const date = this.getDateObj(v);
            this.date.chooseStampTime = date.getTime();
            this.timeValue = this.getTimeObj(date);
          } else {
            const dateInfo = this.getDateTimeInfo(new Date())
            this.mergeInfoToDate(dateInfo);
            this.timeValue = this.initTime();
          }
        }
      }
    }
  },
  methods: {
    initTime() {
      return {
        hour: 0,
        minute: 0,
        second: 0
      };
    },
    initDate() {
      return {
        year: '',
        month: '',
        day: '',
        todayStampTime: new Date(),
        chooseStampTime: 0
      };
    },
    getTimeObj(date) {
      const data = this.getDateTimeInfo(date);
      return {
        hour: data.hour,
        minute: data.minute,
        second: data.second
      }
    },
    updateValue(data) {
      this.$emit('change', data);
    },
    initShowDate(date) {
      const dateInfo = this.getDateTimeInfo(date);
      this.mergeInfoToDate(dateInfo);
      this.data = this.createdDaysData(date);
    },
    isInRange(item) {
      return item.status&&(item.stampTime>=this.startTime.stampTime&&item.stampTime<=this.endTime.stampTime||this.isSameDate(item.stampTime, this.startTime.stampTime)||this.isSameDate(item.stampTime, this.endTime.stampTime))
    },
    isActive(item) {
      if (this.isRange) {
        return this.isSameDate(item.stampTime,this.startTime.stampTime) || this.isSameDate(item.stampTime, this.endTime.stampTime);
      } else {
        return this.isSameDate(item.stampTime, this.date.chooseStampTime);
      }
    },
    mergeInfoToDate(dateInfo) {
      return Object.assign(this.date, {year: dateInfo.year, month: dateInfo.month});
    },
    // 选择时间范围
    chooseRange(arr) {
      if (arr.length >= 2) {
        if (arr[0].stampTime > arr[1].stampTime) {
          this.startTime = arr[1];
          this.endTime = arr[0];
        } else {
          this.startTime = arr[0];
          this.endTime = arr[1];
        }
      } else if (arr.length === 1) {
        this.startTime = arr[0];
        this.endTime = {};
      } else {
        this.startTime = {};
        this.endTime = {};     
      }
    },
    updateChooseDisabledStatus(arr) {
      if (arr.length === 1 && typeof this.pickerOptions.disabledChooseDateRange === 'function') {
        this.data && this.data.forEach(item => {
          item.forEach(child => {
            child.chooseDisabled = this.pickerOptions.disabledChooseDateRange(new Date(child.stampTime), new Date(arr[0].stampTime));
          });
        });
      }
    },
    // 选择时间范围
    chooseDateRange(data) {
      if (!data.status || data.disabled || (data.chooseDisabled && this.chooseDate.length === 1)) {
        return false;
      }
      if (!data.status) {
        return false;
      }
      if (this.chooseDate.length === 2) {
        this.selectDate.splice(0, this.selectDate.length);
        this.chooseDate.splice(0, this.chooseDate.length);
      }
      this.selectDate.push(data);
      this.chooseDate.push(data); 
    },
    handleTimePickClick() {
      this.$emit('onClick');
    },
    // 选择时间
    handleChooseDateTime(data) {
      if (data.disabled) {
        return false;
      }
      switch(this.type) {
        case 'date': 
          this.updateValue(data);
          break;
        case 'datetime':
          const date = this.getDate(data.year, data.month, data.day);
          const params = this.getDateTimeInfo(date);
          this.updateValue(params);
          break;
        case 'daterange':
        case 'datetimerange':
          if (data.chooseDisabled) {
            return false;
          }
          const rangeDate = this.getDate(data.year, data.month, data.day);
          const rangeParams = this.getDateTimeInfo(rangeDate);
          rangeParams.status = data.status;
          this.chooseDateRange(rangeParams);
          break;
      }
    },
    handleTimeChange(item) {
      this.timeValue = item;
      this.$emit('timeChange', item);
    },
    // 浮动选择时间效果
    handleHover(data) {
      if (this.selectDate.length > 0 && this.chooseDate.length === 1) {
        this.$set(this.selectDate, 1, data);
      }
    },
    handlePreYear() {
      const date = this.getDateByYear(this.showDate, -1);
      this.showDate = date;
    },
    handleNextYear() {
      const date = this.getDateByYear(this.showDate, 1);
      this.showDate = date;
    },
    handlePreMonth() {
      const date = this.getDateByMonth(this.showDate, -1);
      this.showDate = date;
    },
    handleNextMonth() {
      const date = this.getDateByMonth(this.showDate, 1);
      this.showDate = date;
    }
  }
}
</script>
<style lang="scss" scoped>
.fbg {
  &-datetime {
    &-box {
      display: inline-block;
      padding: 10px;
      vertical-align: top;
    }
    &-ym {
      text-align: center;
      &-left {
        float: left;
        cursor: pointer;
      }
      &-right {
        float: right;
        cursor: pointer;
      }
    }
    &-day {
      &-box {
        display: table;
      }
      &-item {
        display: table-cell;
        height: 30px;
        width: 35px;
        text-align: center;
        line-height: 30px;
        cursor: pointer;
        &-disabled {
          cursor: not-allowed;
        }
        &:first-child {
          .fbg-datetime-day-item-box {
             border-top-left-radius: 15px;
             border-bottom-left-radius: 15px;
          }
        }
       &:last-child {
          .fbg-datetime-day-item-box {
            border-top-right-radius: 15px;
            border-bottom-right-radius: 15px;
          }
        }
        &-box {
          height: 26px;
          width: 35px;
          line-height: 30px;
        }
        &-box.active {
          color: $themeColor;
        }
        &-range {
          background-color: $themeTintColor;
          &-start {
             border-top-left-radius: 15px;
             border-bottom-left-radius: 15px;
          }
          &-end {
            width: 30px;
             border-top-right-radius: 15px;
             border-bottom-right-radius: 15px;
          }
        }
        &-main {
          height: 26px;
          width: 26px;
          line-height: 26px;
          transition: all 0.4s;
          border-radius: 13px;
          &:hover {
            color: #fff;
            background-color: $themeColor;
          }
        }
        &-main.active {
          color: #fff;
          background-color: $themeColor;
        }
        &-main.disabled {
          color: #fff;
          background-color: #ccc!important;
        }
      }
      &-other {
        color: #999;
      }
    }
  }
}
</style>