import { TimeUtils } from "@imengyu/imengyu-utils";
import { computed, ref } from "vue";

interface CountDownComposeOptions {
  /**
   * 倒计时时长，单位毫秒
   * @default 0
   */
  time: number,
  /**
   * 是否开启毫秒级渲染
   * @default false
   */
  millisecond?: boolean,
  /**
   * 倒计时改变时触发的回调函数
   */
  onChange?: (current: CurrentTime) => void,
  /**
   * 倒计时结束时触发的回调函数
   */
  onFinish?: () => void,
}
export interface CurrentTime {
  /**
   * 剩余总时间（单位毫秒）
   */
  total: number,
  /**
   * 剩余天数
   */
  days: number,
  /**
   * 	剩余小时
   */
  hours: number,
  /**
   * 剩余分钟
   */
  minutes: number,
  /**
   * 剩余秒数
   */
  seconds: number,
  /**
   * 剩余毫秒
   */
  milliseconds: number,
}

/**
 * 提供倒计时管理能力的 HOOK。
 * @param options 参数
 * @returns 返回一个对象，可以用于控制倒计时启停。
 */
export function useCountDown(options: CountDownComposeOptions) {
  const now = ref(options.time);

  const current = computed(() => {

    const {
      days, hours, minutes,
      seconds, milliseconds
    } = TimeUtils.splitMillSeconds(now.value);

    return {
      total: now.value,
      days,
      hours,
      minutes,
      seconds,
      milliseconds,
    };
  });

  const timer = ref(0);

  const checkCallback = (v: number) => {
    if (v <= 0) {
      //小于0，结束
      stop();
      now.value = 0;
      options.onFinish && options.onFinish();
    }
    options.onChange && options.onChange(current.value);
  };

  /**
   * 开始倒计时
   */
  function start() {
    if (timer.value <= 0) {
      const subTime = options.millisecond ? 40 : 1000;
      timer.value = setInterval(() => {
        const nowValue = now.value - subTime;
        checkCallback(nowValue);
        now.value = nowValue;
      }, subTime) as unknown as number;
    }
  }
  /**
   * 暂停倒计时
   */
  function stop() {
    if (timer.value > 0) {
      clearInterval(timer.value);
      timer.value = 0;
    }
  }
  /**
   * 重置倒计时，支持传入新的倒计时时长
   */
  function reset(time?: number) {
    now.value = (time || options.time);
  }

  return {
    /**
     * 当前剩余的时间
     */
    current,
    now,
    start,
    stop,
    reset,
  };
}