import { useMemo, useEffect, useState, useRef } from "react";
import { inBrowser } from "../utils";
import { cancelRaf, raf } from "../utils/raf";
const SECOND = 1e3;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
function parseTime(time) {
  const days = Math.floor(time / DAY);
  const hours = Math.floor(time % DAY / HOUR);
  const minutes = Math.floor(time % HOUR / MINUTE);
  const seconds = Math.floor(time % MINUTE / SECOND);
  const milliseconds = Math.floor(time % SECOND);
  return {
    total: time,
    days,
    hours,
    minutes,
    seconds,
    milliseconds
  };
}
function isSameSecond(time1, time2) {
  return Math.floor(time1 / 1e3) === Math.floor(time2 / 1e3);
}
function useCountDown(options) {
  const [remain, setRemain] = useState(options.time);
  const remainRef = useRef(remain);
  const rafId = useRef();
  const endTime = useRef();
  const counting = useRef();
  const current = useMemo(() => parseTime(remain), [remain]);
  const pause = () => {
    counting.current = false;
    cancelRaf(rafId.current);
  };
  const getCurrentRemain = () => Math.max(endTime.current - Date.now(), 0);
  const handleRemain = (value) => {
    var _a, _b;
    setRemain(value);
    remainRef.current = value;
    (_a = options.onChange) == null ? void 0 : _a.call(options, parseTime(value));
    if (value === 0) {
      pause();
      (_b = options.onFinish) == null ? void 0 : _b.call(options);
    }
  };
  const microTick = () => {
    rafId.current = raf(() => {
      if (counting.current) {
        handleRemain(getCurrentRemain());
        if (remainRef.current > 0) {
          microTick();
        }
      }
    });
  };
  const macroTick = () => {
    rafId.current = raf(() => {
      if (counting.current) {
        const remainRemain = getCurrentRemain();
        if (!isSameSecond(remainRemain, remainRef.current) || remainRemain === 0) {
          handleRemain(remainRemain);
        }
        if (remainRef.current > 0) {
          macroTick();
        }
      }
    });
  };
  const tick = () => {
    if (!inBrowser) {
      return;
    }
    if (options.millisecond) {
      microTick();
    } else {
      macroTick();
    }
  };
  const start = () => {
    if (!counting.current) {
      endTime.current = Date.now() + remainRef.current;
      counting.current = true;
      tick();
    }
  };
  const reset = (totalTime = options.time) => {
    pause();
    setRemain(totalTime);
    remainRef.current = totalTime;
  };
  useEffect(() => {
    return () => {
      pause();
    };
  }, []);
  return {
    start,
    pause,
    reset,
    current
  };
}
export {
  useCountDown
};
