<template>
  <div :class="[`${prefixCls}`, `${prefixCls}-countdown`]">
    <div v-if="title || $slots.title" :class="`${prefixCls}-title`">
      <slot name="title">
        {{ title }}
      </slot>
    </div>
    <div :class="`${prefixCls}-content`">
      <div :class="`${prefixCls}-value`" :style="valueStyle">
        {{ displayValue }}
      </div>
    </div>
  </div>
</template>

<script>
import dayjs from 'dayjs';

const units = [
  ['Y', 1000 * 60 * 60 * 24 * 365], // years
  ['M', 1000 * 60 * 60 * 24 * 30], // months
  ['D', 1000 * 60 * 60 * 24], // days
  ['H', 1000 * 60 * 60], // hours
  ['m', 1000 * 60], // minutes
  ['s', 1000], // seconds
  ['S', 1], // million seconds
];

function getDateString(millisecond, format) {
  let leftMillisecond = millisecond;
  return units.reduce((current, [name, unit]) => {
    if (current.indexOf(name) !== -1) {
      const value = Math.floor(leftMillisecond / unit);
      leftMillisecond -= value * unit;
      return current.replace(new RegExp(`${name}+`, 'g'), (match) => {
        const len = match.length;
        return String(value).padStart(len, '0');
      });
    }
    return current;
  }, format);
}

export default {
  name: 'ElCountdown',
  props: {
    /**
     * @zh 倒计时的标题
     * @en Countdown title
     */
    title: String,
    /**
     * @zh 倒计时的值
     * @en Countdown value
     */
    value: {
      type: Number,
      default: () => Date.now() + 300000,
    },
    /**
     * @zh 用于修正初始化时间显示不正确
     * @en Used to correct the incorrect display of the initialization time
     */
    now: {
      type: Number,
      default: () => Date.now(),
    },
    /**
     * @zh 倒计时的展示格式 [dayjs](https://day.js.org/docs/en/display/format)
     * @en Countdown display format [dayjs](https://day.js.org/docs/en/display/format)
     */
    format: {
      type: String,
      default: 'HH:mm:ss',
    },
    /**
     * @zh 是否开始倒计时
     * @en Whether to start the countdown
     */
    start: {
      type: Boolean,
      default: true,
    },
    /**
     * @zh 自定义显示值的样式
     * @en Custom value style
     * @version 2.32.0
     */
    valueStyle: {
      type: Object
    },
  },
  data() {
    return {
      prefixCls: 'el-statistic',
      timer: 0,
      displayValue: null
    }
  },
  computed: {
    multiWatch() {
      const { value, now, format } = this;
      return {
        value,
        now,
        format
      }
    }
  },
  watch: {
    start(value) {
      if (value && !this.timer) {
        this.startTimer();
      }
    },
    multiWatch: {
      handler() {
        const _value = getDateString(
          Math.max(dayjs(this.value).diff(dayjs(this.now), 'millisecond'), 0),
          this.format
        );
        if (_value !== this.displayValue) {
          this.displayValue = _value;
        }
      },
      deep: true
    }
  },
  created() {
    this.displayValue = getDateString(
        Math.max(dayjs(this.value).diff(dayjs(this.now), 'millisecond'), 0),
        this.format
      )
  },
  beforeMount() {
    this.stopTimer();
  },
  mounted() {
    if (this.start) {
        this.startTimer();
      }
  },
  methods: {
    stopTimer() {
      if (this.timer) {
        window.clearInterval(this.timer);
        this.timer = 0;
      }
    },
    startTimer() {
      if (dayjs(this.value).valueOf() < Date.now()) {
        return;
      }

      this.timer = window.setInterval(() => {
        const _value = dayjs(this.value).diff(dayjs(), 'millisecond');
        if (_value <= 0) {
          this.stopTimer();
          this.$emit('finish');
        }
        this.$nextTick(()=>{
          this.displayValue = getDateString(Math.max(_value, 0), this.format);
        })
      }, 1000 / 10);
    }
  }
}
</script>