<template>
  <div class="dv-time-control">
    <div ref="controlLeft" class="dv-time-control-left">
      <div class="dv-time-control-left-button" @click.stop="playOrPause">
        <div class="dv-time-control-left-button-icon-close" v-if="isPlaying">▐▐</div>
        <div class="dv-time-control-left-button-icon-open" v-else></div>
      </div>
    </div>
    <div class="dv-time-control-right"
         @click.stop="onClickTimeBar"
         ref="controlRight"
         @mousemove="showTips"
         @mouseleave="isShowHoverTip = false">
      <ul class="dv-time-control-time-group-list">
        <li class="dv-time-control-time-group-item" v-for="(timeGroup, index) in timeGroups" :key="index">
          <div class="dv-time-control-time-group-item-time-spans" v-if="timeUnit === 'hour'">
            <div class="dv-time-control-time-group-item-time-span" v-for="groupTimeSpanIndex in groupTimeSpanCount" :key="groupTimeSpanIndex">
              <div class="dv-time-control-time-group-item-time-span-times">
                <time-group-item-time-span-time :timeSpanIndex="timeSpanIndex"
                                                :timeGroup="timeGroup"
                                                :groupTimeSpanIndex="groupTimeSpanIndex"
                                                v-for="timeSpanIndex in timeSpan"
                                                :key="timeSpanIndex"></time-group-item-time-span-time>
              </div>
              <div class="dv-time-control-time-group-item-time-span-value">{{numberToTime(groupTimeSpanIndex)}}</div>
            </div>
          </div>
          <div class="dv-time-control-time-group-item-date">
            {{timeGroup.day}} {{timeGroup.week | weekToChinese}}
          </div>
        </li>
      </ul>

      <div class="dv-time-control-current-bubble-content" :style="{left: timePercent * 100 + '%'}">
        <div class="current-bubble">
          {{currentContent}}
        </div>
      </div>
      <div class="dv-time-control-hover-bubble-content" :style="{left: hoverTipLeft * 100 + '%'}" v-if="isShowHoverTip">
        <div class="hover-bubble">
          {{hoverContent}}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import dayjs from 'dayjs';
import TimeGroupItemTimeSpanTime from "./TimeGroupItemTimeSpanTime";

export default {
  name: "DvTimeControl",
  components: {TimeGroupItemTimeSpanTime},
  provide () {
    return {
      timeControl: this
    }
  },
  props: {
    playInterval: {
      type: Number,
      default: 1000
    },
    groupCount: {
      type: Number,
      default: 7
    },
    timeUnit: {
      type: String,
      default: 'hour'
    },
    currentTimeHandle: {
      type: Function,
      default (currentTime) {
        const hours = currentTime.hour();
        const minutes = currentTime.minute();

        switch (this.timeUnit) {
          case 'hour':
            if (minutes >= 30) {
              return currentTime.minute(0).second(0).millisecond(0);
            }
            return currentTime.subtract(1, this.timeUnit).minute(0).second(0).millisecond(0);
          case 'day':
            if (hours === 0) {
              return currentTime.subtract(1, 'day').hour(0).minute(0).second(0).millisecond(0);
            }
            return currentTime.hour(0).minute(0).second(0).millisecond(0);
        }
      }
    }
  },
  filters: {
    // 星期转为中文
    weekToChinese (value) {
      switch (value) {
        case 'Monday':
          return '周一';
        case 'Tuesday':
          return '周二';
        case 'Wednesday':
          return '周三';
        case 'Thursday':
          return '周四';
        case 'Friday':
          return '周五';
        case 'Saturday':
          return '周六';
        case 'Sunday':
          return '周日';
        default:
          break;
      }
    }
  },
  data () {
    return {
      isPlaying: false,
      time: null,
      currentTime: null,
      timeGroups: [],
      hoverTipLeft: 0,
      hoverContent: null,
      isShowHoverTip: false, // 是否显示hover的事件
    };
  },
  watch: {
    timeUnit () {
      this.initialize();
    },
  },
  computed: {
    groupTimeLength() {
      return this.timeUnit === 'hour' ? 24 : 1;
    },
    timeFormat () {
      return this.timeUnit === 'hour' ? 'YYYY-MM-DD HH:00:00' : 'YYYY-MM-DD 00:00:00'
    },
    groupTimeSpanCount() {
      return this.groupTimeLength / this.timeSpan;
    },
    timeSpan () {
      return this.timeUnit === 'hour' ? 3 : 1;
    },
    currentContent() {
      return this.time?.format(this.tipFormat);
    },
    totalTimes() {
      return this.groupTimeLength * this.groupCount;
    },
    timePercent() {
      return this.time?.diff(this.timeGroups[0].date, this.timeUnit) / this.totalTimes;
    },
    currentTimePercent() {
      return this.currentTime.diff(this.timeGroups[0].date, this.timeUnit) / this.totalTimes;
    },
    tipFormat() {
      if (this.timeUnit === 'day') {
        return 'MM/DD';
      }
      return 'HH:00';
    }
  },
  methods: {
    numberToTime(value) {
      return value * this.timeSpan;
    },
    showTips (event) {
      this.isShowHoverTip = true;
      let left = this.$refs.controlRight.getBoundingClientRect().left;
      let allWidth = this.$refs.controlRight.getBoundingClientRect().width;
      let width = event.x - left;
      let percent = width / allWidth;
      this.hoverContent = this.timeGroups[0].date.add(parseInt(percent * this.groupTimeLength * this.groupCount), this.timeUnit).format(this.tipFormat);
      this.hoverTipLeft =  percent;
    },
    isTimeActive(timeGroup, groupTimeSpanIndex, timeSpanIndex) {
      const time = timeGroup.date.add((groupTimeSpanIndex - 1) * this.timeSpan + timeSpanIndex, this.timeUnit);
      return time <= this.time;
    },
    pre() {
      const time = this.time.subtract(1, this.timeUnit);

      if (time.isBefore(this.timeGroups[0].date)) {
        return;
      }
      this.setTime(time);
    },
    next() {
      const time = this.time.add(1, this.timeUnit);

      if (time.isAfter(this.currentTime)) {
        return;
      }
      this.setTime(time);
    },
    playOrPause() {
      if (this.isPlaying) {
        this.pause();
      }
      else {
        this.start();
      }
    },
    onClickTimeBar(e) {
      this.pause();
      let left = this.$refs.controlRight.getBoundingClientRect().left;
      let width = e.x - left;

      let allWidth = this.$refs.controlRight.getBoundingClientRect().width;
      const percent = width / allWidth;

      if (percent <= this.currentTimePercent) {
        this.setTime(this.timeGroups[0].date.add(parseInt(percent * this.totalTimes), this.timeUnit));
      }
      else {
        this.setTime(this.currentTime);
      }
    },
    setToStartTime() {
      const startTime = this.timeGroups[0].date;
      this.setTime(startTime);
    },
    start() {
      this.isPlaying = true;
      if (this.time.format(this.timeFormat) === this.currentTime.format(this.timeFormat)) {
        this.setToStartTime();
      }
      this.timer = setInterval(() => {
        this.walk();
      }, this.playInterval);
    },
    pause() {
      clearInterval(this.timer);
      this.isPlaying = false;
      this.timer = null;
    },
    setTime(time) {
      this.time = this.timeUnit === 'day' ? time.hour(12) : time;
      this.$emit('updateTime', time.format(this.timeFormat));
    },
    walk () {
      if (this.time.format(this.timeFormat) === this.currentTime.format(this.timeFormat)) {
        this.pause();
      }
      else {
        this.setTime(this.time.add(1, this.timeUnit));
      }
    },
    initialize() {
      this.updateBar();

      // 设置30分切换事件
      setInterval(() => {
        const date = new Date();

        if (date.getMinutes() === 30 && date.getSeconds() === 0) {
          this.updateBar();
        }
      }, 1000);
    },
    getCurrentTime() {
      return this.currentTimeHandle(dayjs());
    },
    updateBar() {
      this.currentTime = this.getCurrentTime();

      if (!this.isPlaying) {
        this.setTime(this.currentTime);
      }
      this.timeGroups = [];

      for(let i = this.groupCount - 1; i >= 0; i--) {
        let date = this.currentTime.hour(0).subtract(i, 'day');
        let day = date.format('MM/DD');
        let week = date.format('dddd');
        const timeGroup = {
          date,
          day,
          week
        };
        this.timeGroups.push(timeGroup);
      }
    }
  },
  mounted() {
    this.initialize();

    document.addEventListener('keydown', (e) => {
      let key = window.event.keyCode;
      // 时间移动==》
      if (key === 39) {
        this.next();
      }
      // 时间移动《==
      if (key === 37) {
        this.pre();
      }
    });
  }
}
</script>
