<template>
  <transition
    name="el-zoom-in-top"
    @after-leave="leavePanel">
    <div
      v-show="visible"
      class="el-time-range-picker el-picker-panel el-popper"
      :class="popperClass">
      <div class="el-time-range-picker__content">
        <div class="el-time-range-picker__cell">
          <div class="el-time-range-picker__header">{{ t('el.datepicker.startTime') }}</div>
          <div
            :class="{ 'has-seconds': showSeconds }"
            class="el-time-range-picker__body el-time-panel__content">
            <time-spinner
              ref="minSpinner"
              key="startTime"
              :show-seconds="showSeconds"
              :am-pm-mode="amPmMode"
              :disabled="disabledStart"
              @change="handleMinChange"
              :date="minDate">
            </time-spinner>
          </div>
        </div>
        <div class="el-time-range-picker__cell">
          <div class="el-time-range-picker__header">{{ t('el.datepicker.endTime') }}</div>
          <div
            :class="{ 'has-seconds': showSeconds }"
            class="el-time-range-picker__body el-time-panel__content">
            <time-spinner
              ref="maxSpinner"
              key="endTime"
              :show-seconds="showSeconds"
              :am-pm-mode="amPmMode"
              :disabled="disabledEnd"
              @change="handleMaxChange"
              :date="maxDate">
            </time-spinner>
          </div>
        </div>
      </div>
      <div class="el-time-panel__footer">
        <el-button
          size="mini"
          type="secondary"
          class="el-picker-panel__link-btn"
          @click="handleCancel">
          {{ t('el.datepicker.cancel') }}
        </el-button>
        <el-button
          size="mini"
          class="el-picker-panel__link-btn"
          :disabled="btnDisabled"
          @click="handleConfirm(false)">
          {{ t('el.datepicker.confirm') }}
        </el-button>
      </div>
    </div>
  </transition>
</template>

<script type="text/babel">
  import {
    parseDate,
    modifyDate,
    clearMilliseconds,
    timeWithinRange
  } from 'modesign-ui/src/utils/date-util';
  import Locale from 'modesign-ui/src/mixins/locale';
  import TimeSpinner from '../basic/time-spinner';
  import dayjs from 'dayjs';
  import ElButton from 'modesign-ui/packages/button';

  const MIN_TIME = parseDate('00:00:00', 'HH:mm:ss');
  const MAX_TIME = parseDate('23:59:59', 'HH:mm:ss');

  const minTimeOfDay = function(date) {
    return modifyDate(MIN_TIME, date.getFullYear(), date.getMonth(), date.getDate());
  };

  const maxTimeOfDay = function(date) {
    return modifyDate(MAX_TIME, date.getFullYear(), date.getMonth(), date.getDate());
  };

  // increase time by amount of milliseconds, but within the range of day
  const advanceTime = function(date, amount) {
    return new Date(Math.min(date.getTime() + amount, maxTimeOfDay(date).getTime()));
  };

  export default {
    mixins: [Locale],

    components: { TimeSpinner, ElButton },

    computed: {
      showSeconds() {
        return (this.format || '').indexOf('ss') !== -1;
      },

      offset() {
        return this.showSeconds ? 11 : 8;
      },

      spinner() {
        return this.selectionRange[0] < this.offset ? this.$refs.minSpinner : this.$refs.maxSpinner;
      },
      amPmMode() {
        if ((this.format || '').indexOf('A') !== -1) return 'A';
        if ((this.format || '').indexOf('a') !== -1) return 'a';
        return '';
      }
    },

    data() {
      return {
        popperClass: '',
        minDate: null,
        maxDate: null,
        value: [],
        oldValue: [new Date(), new Date()],
        defaultValue: null,
        format: 'HH:mm:ss',
        visible: false,
        btnDisabled: false,
        disabledStart: false,
        disabledEnd: false,
        confirmFlag: false,
        // selectionRange: [0, 2]
      };
    },

    watch: {
      value(value) {
        if (Array.isArray(value)) {
          this.minDate = new Date(value[0]);
          this.maxDate = new Date(value[1]);
        } else {
          if (Array.isArray(this.defaultValue)) {
            this.minDate = new Date(this.defaultValue[0]);
            this.maxDate = new Date(this.defaultValue[1]);
          } else if (this.defaultValue) {
            this.minDate = new Date(this.defaultValue);
            this.maxDate = advanceTime(new Date(this.defaultValue), 60 * 60 * 1000);
          } else {
            this.minDate = new Date();
            this.maxDate = advanceTime(new Date(), 60 * 60 * 1000);
          }
        }
      },
      visible(val) {
        if (val) {
          this.oldValue = this.value;
          this.$nextTick(() => this.$refs.minSpinner.emitSelectRange('hours'));
        }
      },
      secondPickDisabled(val) {
        if (Array.isArray(val) && val.length > 1) {
          const start = val[0]
          const end = val[1]
          const endHour = this.maxDate.getHours()
          const endMinute = this.maxDate.getMinutes()
          const endSeconds = this.maxDate.getSeconds()
          const startHour = this.minDate.getHours()
          const startMinute = this.minDate.getMinutes()
          const startSeconds = this.minDate.getSeconds()
          this.disabledStart = start
          this.disabledEnd = end
          const hours = []
          for (let i = 0; i < 24; i++) {
            if (start) {
              // 开始时间禁用，结束时间小时数>开始时间小时数
              hours[i] = i <= startHour
            }
            if (end) {
              // 结束时间禁用，开始时间小时数<=结束时间小时数
              hours[i] = i > endHour
            }
          }
          const minutes = []
          for (let i = 0; i < 60; i++) {
            if (startHour === endHour) {
              if (start) {
                // 开始时间禁用，结束时间分钟数>开始时间分钟数
                minutes[i] = i <= startMinute
              }
              if (end) {
                // 结束时间禁用，开始时间分钟数<=结束时间分钟数
                minutes[i] = i > endMinute
              }
            } else {
              minutes[i] = false
            }
          }
          const seconds = []
          for (let i = 0; i < 60; i++) {
            if (startHour === endHour && startMinute === endMinute) {
              if (start) {
                // 开始时间禁用，结束时间秒数>开始时间秒数
                seconds[i] = i <= startSeconds
              }
              if (end) {
                // 结束时间禁用，开始时间分钟数<=结束时间分钟数
                seconds[i] = i > endSeconds
              }
            } else {
              seconds[i] = false
            }
          }
          if (end) {
            this.$refs.minSpinner.disabledHours = hours
            this.$refs.minSpinner.disabledMinutes = minutes
            this.$refs.minSpinner.disabledSeconds = seconds
          }
          if (start) {
            this.$refs.maxSpinner.disabledHours = hours
            this.$refs.maxSpinner.disabledMinutes = minutes
            this.$refs.maxSpinner.disabledSeconds = seconds
          }
        } else {
          this.$refs.maxSpinner.disabledHours = null
          this.$refs.maxSpinner.disabledMinutes = null
          this.$refs.maxSpinner.disabledSeconds = null
          this.$refs.minSpinner.disabledHours = null
          this.$refs.minSpinner.disabledMinutes = null
          this.$refs.minSpinner.disabledSeconds = null
          this.disabledEnd = false
        }
      }
    },
    props: {
      // 禁用的小时数
      disabledHours: {
        type: Array,
        default: () => []
      },
      // 禁用的分钟数
      disabledMinutes: {
        type: Array,
        default: () => []
      },
      // 禁用的秒数
      disabledSeconds: {
        type: Array,
        default: () => []
      },
      secondPickDisabled: {
        type: Array,
        default: () => []
      }
    },
    methods: {
      handleClear() {
        this.$emit('pick', null);
      },

      handleCancel() {
        this.$emit('pick', this.oldValue);
      },
      /** 校验时间 **/
      checkTime(val) {
        const hours = val.getHours()
        const minutes = val.getMinutes()
        const seconds = val.getSeconds()
        return this.disabledHours.includes(hours) || this.disabledMinutes.includes(minutes) || this.disabledSeconds.includes(seconds);
      },
      handleMinChange(date) {
        if (this.secondPickDisabled && this.secondPickDisabled[0]) return
        if (this.checkTime(date)) {
          this.btnDisabled = true
          return
        } else {
          this.btnDisabled = false
        }
        this.minDate = clearMilliseconds(date);
        this.handleChange();
      },

      handleMaxChange(date) {
        if (this.secondPickDisabled && this.secondPickDisabled[1]) return
        if (this.checkTime(date)) {
          this.btnDisabled = true
          return
        } else {
          this.btnDisabled = false
        }
        this.maxDate = clearMilliseconds(date);
        this.handleChange();
      },

      handleChange() {
        if (this.isValidValue([this.minDate, this.maxDate])) {
          // this.$refs.minSpinner.selectableRange = [[minTimeOfDay(this.minDate), this.maxDate]];
          // this.$refs.maxSpinner.selectableRange = [[this.minDate, maxTimeOfDay(this.maxDate)]];
          const startHour = this.minDate.getHours()
          const startMinute = this.minDate.getMinutes()
          const startSeconds = this.minDate.getSeconds()
          const endHour = this.maxDate.getHours()
          const endMinute = this.maxDate.getMinutes()
          const endSeconds = this.maxDate.getSeconds()
          const minutes = []
          for (let i = 0; i < 60; i++) {
            if (startHour === endHour) {
              if (this.disabledStart) {
                // 开始时间禁用，结束时间分钟数>开始时间分钟数
                minutes[i] = i <= startMinute
              }
              if (this.disabledEnd) {
                // 结束时间禁用，开始时间分钟数<=结束时间分钟数
                minutes[i] = i > endMinute
              }
            } else {
              minutes[i] = false
            }
          }
          const seconds = []
          for (let i = 0; i < 60; i++) {
            if (startHour === endHour && startMinute === endMinute) {
              if (this.disabledStart) {
                // 开始时间禁用，结束时间秒数>开始时间秒数
                seconds[i] = i <= startSeconds
              }
              if (this.disabledEnd) {
                // 结束时间禁用，开始时间分钟数<=结束时间分钟数
                seconds[i] = i > endSeconds
              }
            } else {
              seconds[i] = false
            }
          }
          if (this.disabledEnd) {
            this.$refs.minSpinner.disabledMinutes = minutes
            this.$refs.minSpinner.disabledSeconds = seconds
          }
          if (this.disabledStart) {
            this.$refs.maxSpinner.disabledMinutes = minutes
            this.$refs.maxSpinner.disabledSeconds = seconds
          }
          this.$emit('pick', [this.minDate, this.maxDate], true);
        }
      },

      // setMinSelectionRange(start, end) {
      //   this.$emit('select-range', start, end, 'min');
      //   this.selectionRange = [start, end];
      // },
      //
      // setMaxSelectionRange(start, end) {
      //   this.$emit('select-range', start, end, 'max');
      //   this.selectionRange = [start + this.offset, end + this.offset];
      // },

      handleConfirm(visible = false) {
        // const minSelectableRange = this.$refs.minSpinner.selectableRange;
        // const maxSelectableRange = this.$refs.maxSpinner.selectableRange;
        //
        // this.minDate = limitTimeRange(this.minDate, minSelectableRange, this.format);
        // this.maxDate = limitTimeRange(this.maxDate, maxSelectableRange, this.format);
        this.confirmFlag = true;
        const time1 = +dayjs(this.minDate).format('HH:mm:ss').replace(/:/g, '')
        const time2 = +dayjs(this.maxDate).format('HH:mm:ss').replace(/:/g, '')
        // if (this.minDate.getTime() >= this.maxDate.getTime()) {
        if (time1 >= time2) {
          this.$emit('pick', [this.maxDate, this.minDate], visible);
        } else {
          this.$emit('pick', [this.minDate, this.maxDate], visible);
        }
      },

      adjustSpinners() {
        this.$refs.minSpinner.adjustSpinners();
        this.$refs.maxSpinner.adjustSpinners();
      },
      changeSelectionRange(step) {
        const list = this.showSeconds ? [0, 3, 6, 11, 14, 17] : [0, 3, 8, 11];
        const mapping = ['hours', 'minutes'].concat(this.showSeconds ? ['seconds'] : []);
        const index = list.indexOf(this.selectionRange[0]);
        const next = (index + step + list.length) % list.length;
        const half = list.length / 2;
        if (next < half) {
          this.$refs.minSpinner.emitSelectRange(mapping[next]);
        } else {
          this.$refs.maxSpinner.emitSelectRange(mapping[next - half]);
        }
      },

      isValidValue(date) {
        return Array.isArray(date) &&
          timeWithinRange(this.minDate, this.$refs.minSpinner.selectableRange) &&
          timeWithinRange(this.maxDate, this.$refs.maxSpinner.selectableRange);
      },

      handleKeydown(event) {
        const keyCode = event.keyCode;
        const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };

        // Left or Right
        if (keyCode === 37 || keyCode === 39) {
          const step = mapping[keyCode];
          this.changeSelectionRange(step);
          event.preventDefault();
          return;
        }

        // Up or Down
        if (keyCode === 38 || keyCode === 40) {
          const step = mapping[keyCode];
          this.spinner.scrollDown(step);
          event.preventDefault();
          return;
        }
      },
      leavePanel() {
        if (!this.confirmFlag) {
          this.$emit('pick', this.oldValue);
        }
        this.confirmFlag = false;
        this.$emit('dodestroy');
      }
    }
  };
</script>
