import PropTypes from "prop-types";
import React from "react";
import $calc from "../../utils/common";
import styleObj from "./index.module.scss";

export default class CalcCountDown extends React.Component {
  //#region 属性 & 构造函数

  // 属性类型校验
  static propTypes = {
    lv: PropTypes.number,
    customClass: PropTypes.string,

    beforeStartText: PropTypes.string,
    afterStartText: PropTypes.string,
    // 倒计时时间间隔, 单位s
    interval: PropTypes.number,
    // 是否自动启动倒计时
    isAutoRunFirst: PropTypes.bool,
    // 是否执行启动事件当自动启动倒计时的时候
    isExeStartEventWhenAutoRunFirst: PropTypes.bool,
    // 启动后执行的事件
    onStartEvent: PropTypes.func,
    // 每帧需要执行的事件
    // 假设显示器刷新频次为60HZ, 则一帧执行时间为1/60*1000 = 16.7ms
    onIntervalEvent: PropTypes.func,
    onFinishEvent: PropTypes.func,
  };

  // 属性默认值
  static defaultProps = {
    lv: 7,
    customClass: "custom-calc-count-down",

    beforeStartText: "Send Code",
    afterStartText: "Resend in {interval}",
    interval: 180,
    isAutoRunFirst: false,
    isExeStartEventWhenAutoRunFirst: false,
    onStartEvent: () => {
      console.log(`onStartEvent`);
    },
    onIntervalEvent: (subTime) => {
      console.log(`onIntervalEvent`, subTime);
    },
    onFinishEvent: () => {
      console.log(`onFinishEvent`);
    },
  };

  constructor(props) {
    super(props);
    this.state = {
      interval: this.props.interval,
      isCounting: false,
    };
  }

  #data = {
    rafID: null,
    startTime: null,
    stopTime: null,
    subTime: null,
  };

  //#endregion

  //#region 属性

  // 显示文本
  get showingText() {
    const _self = this;
    const { beforeStartText, afterStartText } = _self.props;
    const { interval, isCounting } = _self.state;

    let text = "";
    if (!isCounting) {
      text = beforeStartText;
    } else {
      text = afterStartText.replace("{interval}", interval);
    }

    return text;
  }

  //#endregion

  //#region hooks

  render() {
    const _self = this;
    const { lv, customClass } = _self.props;
    const { isCounting } = _self.state;

    return (
      <div className={`${styleObj["calc-count-down-scoped"]}`}>
        <div className={`calc-count-down ${customClass}`}>
          <div
            className={`label-btn ${isCounting ? "isCounting" : ""}`}
            onClick={(e) => {
              _self.#startCountDownEvent(true);
            }}
          >
            {_self.showingText}
          </div>
        </div>
      </div>
    );
  }

  componentDidMount() {
    const _self = this;
    // 任务初始化
    _self.initTask(() => {});
    // console.log(`componentDidMount`);
  }

  shouldComponentUpdate(nextProps, nextState) {
    const _self = this;
    const removeProps = ["children"];
    const nextPropsClone = $calc.tool.deepClone(nextProps, removeProps);
    const curPropsClone = $calc.tool.deepClone(_self.props, removeProps);

    const nextStateClone = $calc.tool.deepClone(nextState, removeProps);
    const curnextStateClone = $calc.tool.deepClone(_self.state, removeProps);

    const needRender =
      JSON.stringify(nextPropsClone) != JSON.stringify(curPropsClone) ||
      JSON.stringify(nextStateClone) != JSON.stringify(curnextStateClone);
    // console.log("calc-count-down shouldComponentUpdate...", needRender);
    if (needRender) {
      return true;
    }

    return false;
  }

  componentDidUpdate(prevProps, prevState) {}

  componentWillUnmount() {}

  //#endregion

  //#region methods

  //任务初始化
  //callBack: 回调函数
  initTask(callBack) {
    const _self = this;
    // // 1>重置时间间隔
    // _self.#resetInterval(callBack);
    const { isAutoRunFirst, isExeStartEventWhenAutoRunFirst = false } =
      _self.props;
    // console.log(
    //   `initTask-isAutoRunFirst`,
    //   isAutoRunFirst,
    //   `initTask-isExeStartEventWhenAutoRunFirst`,
    //   isExeStartEventWhenAutoRunFirst
    // );
    isAutoRunFirst &&
      _self.#startCountDownEvent(isExeStartEventWhenAutoRunFirst);
    callBack && callBack();
  }

  //重置时间间隔
  //callBack: 回调函数
  #resetInterval(callBack) {
    const _self = this;
    const { interval } = _self.props;
    _self.setState(
      {
        interval,
      },
      () => {
        callBack && callBack();
      }
    );
  }

  // 启动倒计时事件
  // isExeStartEventWhenAutoRunFirst: 是否执行启动事件当自动启动倒计时的时候
  #startCountDownEvent(isExeStartEvent = true) {
    const _self = this;
    // console.log(`startCountDownEvent-isExeStartEvent`, isExeStartEvent);
    _self.#start(isExeStartEvent);
  }

  // 启动倒计时
  // isExeStartEvent: 是否执行启动事件, 默认true
  #start(isExeStartEvent = true) {
    const _self = this;
    // console.log(`start-isExeStartEvent`, isExeStartEvent);
    const { isCounting } = _self.state;
    const { interval, onStartEvent } = _self.props;

    // 若已经启动, 则返回
    if (isCounting) {
      return false;
    }

    _self.setState(
      {
        isCounting: true,
      },
      () => {}
    );
    _self.#data.startTime = performance.now();
    // const that = this;
    _self.#data.rafID = requestAnimationFrame((timestamp) => {
      _self.#step(timestamp);
    });
    // 执行启动事件
    isExeStartEvent && onStartEvent && onStartEvent();
  }
  // 每帧需要执行的动作
  #step(timestamp) {
    const _self = this;
    // console.log(timestamp);
    const { interval, onIntervalEvent, onFinishEvent } = _self.props;
    const { startTime } = _self.#data;
    _self.#data.subTime = timestamp - startTime;
    // 设置state.interval
    _self.#formatInterval(_self.#data.subTime);
    // 执行间隔事件
    onIntervalEvent && onIntervalEvent(_self.#data.subTime);

    // 倒计时和时间到, 停止计数
    if (Math.floor(_self.#data.subTime / 1000) >= interval) {
      _self.#finish();
      return true;
    }

    // 继续执行下一帧动作
    _self.#data.rafID = requestAnimationFrame((timestamp) => {
      _self.#step(timestamp);
    });
  }
  // 格式化显示的间隔值
  #formatInterval(subTime) {
    const _self = this;
    const { interval } = _self.props;
    subTime = $calc.tool.isNullOrEmpty(subTime) ? 0 : subTime;
    _self.setState(
      {
        interval: interval - Math.floor(subTime / 1000),
      },
      () => {}
    );
  }
  // 执行完毕
  #finish() {
    const _self = this;
    const { interval, onFinishEvent } = _self.props;
    _self.#pause();
    // 重置属性
    _self.#data.rafID = null;
    _self.#data.startTime = null;
    _self.#data.stopTime = null;
    _self.#data.subTime = null;
    // 重置间隔时间
    _self.#resetInterval();
    // 执行完成事件
    onFinishEvent && onFinishEvent();
  }
  // 暂停
  #pause() {
    const _self = this;
    const { isCounting } = _self.state;
    const { rafID } = _self.#data;
    // 若已经停止计数, 则pass
    if (!isCounting) {
      return;
    }

    _self.setState(
      {
        isCounting: false,
      },
      () => {}
    );
    _self.#data.stopTime = performance.now();
    rafID && cancelAnimationFrame(rafID);
  }
  // 继续
  #continue() {
    const _self = this;
    const { isCounting } = _self.state;
    let { startTime, stopTime } = _self.#data;
    // 若已经在计数, 则pass
    if (isCounting) {
      return;
    }

    _self.setState(
      {
        isCounting: true,
      },
      () => {}
    );

    _self.#data.startTime = startTime + performance.now() - stopTime;
    _self.#data.rafID = requestAnimationFrame((timestamp) => {
      _self.#step(timestamp);
    });
  }

  //#endregion
}