import { useEffect, useMemo, useState, useRef } from 'react';
import { inBrowser } from '../utils';
import { cancelRaf, raf } from '../utils/raf';
var SECOND = 1000;
var MINUTE = 60 * SECOND;
var HOUR = 60 * MINUTE;
var DAY = 24 * HOUR;

function parseTime(time) {
  var days = Math.floor(time / DAY);
  var hours = Math.floor(time % DAY / HOUR);
  var minutes = Math.floor(time % HOUR / MINUTE);
  var seconds = Math.floor(time % MINUTE / SECOND);
  var milliseconds = Math.floor(time % SECOND);
  return {
    total: time,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds,
    milliseconds: milliseconds
  };
}

function isSameSecond(time1, time2) {
  return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
}

export default function useCountDown(options) {
  var rafId = useRef(0);
  var endTime = useRef(0);
  var counting = useRef(false);

  var _useState = useState(function () {
    return options.time;
  }),
      remain = _useState[0],
      updateRemain = _useState[1];

  var remainRef = useRef(0);
  var current = useMemo(function () {
    return parseTime(remain);
  }, [remain]);
  remainRef.current = remain;

  var pause = function pause() {
    counting.current = false;
    cancelRaf(rafId.current);
  };

  var getCurrentRemain = function getCurrentRemain() {
    return Math.max(endTime.current - Date.now(), 0);
  };

  var setRemain = function setRemain(value) {
    remainRef.current = value;
    updateRemain(value);
    options.onChange == null ? void 0 : options.onChange(current);

    if (value === 0) {
      pause();
      options.onFinish == null ? void 0 : options.onFinish();
    }
  };

  var microTick = function microTick() {
    rafId.current = raf(function () {
      // in case of call reset immediately after finish
      if (counting.current) {
        setRemain(getCurrentRemain());

        if (remainRef.current > 0) {
          microTick();
        }
      }
    });
  };

  var macroTick = function macroTick() {
    rafId.current = raf(function () {
      // in case of call reset immediately after finish
      if (counting.current) {
        var remainRemain = getCurrentRemain();

        if (!isSameSecond(remainRemain, remainRef.current) || remainRemain === 0) {
          setRemain(remainRemain);
        }

        if (remainRef.current > 0) {
          macroTick();
        }
      }
    });
  };

  var tick = function tick() {
    // should not start counting in server
    // see: https://github.com/youzan/vant/issues/7807
    if (!inBrowser) {
      return;
    }

    if (options.millisecond) {
      microTick();
    } else {
      macroTick();
    }
  };

  var start = function start() {
    if (!counting.current) {
      endTime.current = Date.now() + remainRef.current;
      counting.current = true;
      tick();
    }
  };

  var reset = function reset(totalTime) {
    if (totalTime === void 0) {
      totalTime = options.time;
    }

    pause();
    remainRef.current = totalTime;
    updateRemain(totalTime);
  };

  useEffect(function () {
    if (options.autostart) {
      start();
    }
  }, []);
  return {
    start: start,
    pause: pause,
    reset: reset,
    current: current
  };
}