<template>
  <div
    class="hn-countdown"
    :class="[
      'hn-countdown--' + type,
      'hn-countdown--' + size,
    ]">
    <slot :countDownData="countDownData">
      <div
        v-if="showPrefix"
        class="hn-countdown__prefix">
        {{ prefix }}
      </div>
      <div
        v-if="tplIndexOfDays !== -1"
        class="hn-countdown__item">
        <div class="hn-countdown-num hn-countdown-num--day">
          {{ countDownData.d }}
        </div>
        <div class="hn-countdown-tpl hn-countdown-tpl--day">
          {{ getDot(tplIndexOfDays, tplIndexOfHours) }}
        </div>
      </div>
      <div
        v-if="tplIndexOfHours !== -1"
        class="hn-countdown__item">
        <div class="hn-countdown-num hn-countdown-num--hour">
          {{ countDownData.h }}
        </div>
        <div class="hn-countdown-tpl hn-countdown-tpl--hour">
          {{ getDot(tplIndexOfHours, tplIndexOfMinutes) }}
        </div>
      </div>
      <div
        v-if="tplIndexOfMinutes !== -1"
        class="hn-countdown__item">
        <div class="hn-countdown-num hn-countdown-num--minute">
          {{ countDownData.m }}
        </div>
        <div class="hn-countdown-tpl hn-countdown-tpl--minute">
          {{ getDot(tplIndexOfMinutes, tplIndexOfSeconds) }}
        </div>
      </div>
      <div
        v-if="tplIndexOfSeconds !== -1"
        class="hn-countdown__item">
        <div class="hn-countdown-num hn-countdown-num--second">
          {{ countDownData.s }}
        </div>
        <div class="hn-countdown-tpl hn-countdown-tpl--second">
          {{ getDot(tplIndexOfSeconds, -1) }}
        </div>
      </div>
    </slot>
  </div>
</template>

<script>
  import parseMS from 'heiner-ui/src/utils/parse-ms';

  export default {
    name: 'HnCountdown',
    components: {},
    props: {
      size: {
        type: String,
        default: 'medium'
      },
      type: {
        type: String,
        default: 'default'
      },
      totalTime: {
        type: [Number, String],
        default: 0,
        validator: v => v >= 0
      },
      endTime: [Number, String],
      // 倒计时的间隔,单位为"毫秒"
      interval: {
        type: Number,
        default: 1000,
        validator: v => v >= 0
      },
      tpl: {
        type: String,
        default: '{h}:{m}:{s}'
      },
      stopAtThatTime: {
        type: Boolean,
        default: true
      },
      showPrefix: {
        type: Boolean,
        default: false
      },
      timingPrefix: {
        type: String,
        default: '-'
      },
      timeoutPrefix: {
        type: String,
        default: '+'
      }
    },
    data() {
      return {
        leftTime: 0,
        timer: null
      };
    },

    computed: {
      timeUnits() {
        return this.tpl.match(/[^\{\}]+(?=\})/g);
      },
      countDownData() {
        let ms = this.leftTime;
        if (this.stopAtThatTime && ms <= 0) {
          ms = 0;
          this.$emit('finish');
          this.clearInterval();
        }
        ms = Math.ceil(ms / 1000) * 1000;
        return parseMS(ms, this.timeUnits);
      },
      tplIndexOfDays() {
        return this.tpl.indexOf('d');
      },
      tplIndexOfHours() {
        return this.tpl.indexOf('h');
      },
      tplIndexOfMinutes() {
        return this.tpl.indexOf('m');
      },
      tplIndexOfSeconds() {
        return this.tpl.indexOf('s');
      },
      isTimeOut() {
        return this.leftTime <= 0;
      },
      prefix() {
        return this.isTimeOut ? this.timeoutPrefix : this.timingPrefix;
      }
    },

    created() {
      this.initLeftTime();
    },

    mounted() {
      this.start();
    },

    beforeDestroy() {
      this.clearInterval();
    },

    methods: {
      getTimeStamp(timeStr) {
        if (!timeStr) return Date.now();
        let t = timeStr;
        t = t > 0 ? +t : t.toString().replace(/\-/g, '/');
        return new Date(t).getTime();
      },

      clearInterval() {
        clearInterval(this.timer);
        this.timer = null;
      },

      initLeftTime() {
        const curr = Date.now();
        const _end = this.getTimeStamp(this.endTime || curr);
        const endTime = _end + (this.totalTime * 1000);
        this.leftTime = endTime - curr;
      },

      start() {
        if (this.timer) return;
        const endTime = this.leftTime + Date.now();
        // 避免触发 countDownData 计算
        if (this.stopAtThatTime && this.isTimeOut) return;
        this.timer = setInterval(() => {
          this.leftTime = endTime - Date.now();
        }, this.interval);
      },

      pause() {
        if (!this.timer) return;
        this.clearInterval();
      },

      getDot(prevTagIndex, nextTagIndex = -1) {
        if (nextTagIndex === -1) {
          return this.tpl.slice(prevTagIndex + 2);
        }
        return this.tpl.slice(prevTagIndex + 2, nextTagIndex - 1);
      }

    }
  };
</script>
