import PropTypes from "prop-types";
import React from "react";
import $calc from "../../utils/common";
import styleObj from "./index.module.scss";

export default class CalcSlidingVerifier extends React.Component {
  //#region 属性 & 构造函数

  // 属性类型校验
  static propTypes = {
    lv: PropTypes.number,
    customClass: PropTypes.string,

    isPassing: PropTypes.bool,

    width: PropTypes.number,
    height: PropTypes.number,

    text: PropTypes.string,
    successText: PropTypes.string,
    handlerBg: PropTypes.string,
    textSize: PropTypes.string,
    textColor: PropTypes.string,

    background: PropTypes.string,
    progressBarBg: PropTypes.string,
    completedBg: PropTypes.string,

    circle: PropTypes.bool,
    radius: PropTypes.string,
    // 拖拽句柄是否完全填充验证器高度
    handlerFullFilling: PropTypes.bool,

    handlerIcon: PropTypes.string,
    successIcon: PropTypes.string,
    handlerIconColor: PropTypes.string,
    successIconColor: PropTypes.string,

    // hooks
    updateIsPassing: PropTypes.func,
    handlerMove: PropTypes.func,
    handlerVerifyFail: PropTypes.func,
    handlerVerifySuccess: PropTypes.func,
  };
  // 属性默认值
  static defaultProps = {
    lv: 7,
    customClass: "custom-calc-sliding-verifier",

    isPassing: false,

    width: 250,
    height: 40,

    text: "Swiping to right side for verifying",
    successText: "Verified successfully",
    handlerBg: "#ffffff",
    textSize: "14px",
    textColor: "#333333",

    background: "#eeeee",
    // progressBarBg: "#76c61d",
    // completedBg: "#76c61d",
    progressBarBg: "#3db25e",
    completedBg: "#3db25e",

    circle: false,
    radius: "4px",
    handlerFullFilling: true,

    handlerIcon: "calc-oa-verification",
    successIcon: "calc-oa-drag-done",
    handlerIconColor: "#666666",
    successIconColor: "#3db25e",

    updateIsPassing: (val) => {
      console.log(`updateIsPassing`, val);
    },
    handlerMove: () => {
      console.log(`handlerMove`);
    },
    handlerVerifyFail: () => {
      console.log(`handlerVerifyFail`);
    },
    handlerVerifySuccess: () => {
      console.log(`handlerVerifySuccess`);
    },
  };

  constructor(props) {
    super(props);
    this.state = {
      isMoving: false,
      x: 0,
      isOk: false,
    };
  }

  dragVerifyRef = React.createRef();
  progressBarRef = React.createRef();
  messageRef = React.createRef();
  handlerRef = React.createRef();

  get message() {
    const _self = this;
    return _self.props.isPassing ? _self.props.successText : _self.props.text;
  }

  get textStyle() {
    const _self = this;
    return {
      height: `${_self.props.height}px`,
      width: `${_self.props.width}px`,
      fontSize: _self.props.textSize,
    };
  }

  get dragVerifyStyle() {
    const _self = this;
    return {
      width: `${_self.props.width}px`,
      height: `${_self.props.height}px`,
      lineHeight: `${_self.props.height}px`,
      background: _self.props.background,
      borderRadius: _self.props.circle
        ? `${_self.props.height / 2}px`
        : _self.props.radius,
    };
  }

  get progressBarStyle() {
    const _self = this;
    return {
      background: _self.props.progressBarBg,
      height: `${_self.props.height}px`,
      borderRadius: _self.props.circle
        ? `${_self.props.height / 2}px 0 0 ${_self.props.height / 2}px`
        : _self.props.radius,
    };
  }

  get handlerStyle() {
    const _self = this;
    let height = _self.props.height || 0;
    let styleObj = {};

    if (_self.props.fullFilling && height >= 2) {
      styleObj = {
        width: `${_self.props.height}px`,
        height: `${_self.props.height}px`,
        background: _self.props.handlerBg,
      };
    } else {
      let margin = 2;
      height = height - margin - margin;
      styleObj = {
        width: `${height}px`,
        height: `${height}px`,
        background: _self.props.handlerBg,
        margin: `${margin}px`,
        borderRadius: `3px`,
      };
    }

    return styleObj;
  }

  get handlerIconStyle() {
    const _self = this;
    let styleObj = {};
    styleObj["color"] = _self.props.isPassing
      ? _self.props.successIconColor
      : _self.props.handlerIconColor;
    // console.log(
    //   `handlerIconStyle`,
    //   `isPassing:${_self.props.isPassing}`,
    //   styleObj
    // );
    return styleObj;
  }

  //#endregion

  //#region hooks

  render() {
    const _self = this;
    return (
      <div className={`${styleObj["calc-sliding-verifier-scoped"]}`}>
        <div
          ref={_self.dragVerifyRef}
          className={`calc-sliding-verifier ${_self.props.customClass}`}
          style={_self.dragVerifyStyle}
          onMouseMove={(e) => {
            _self.dragMoving(e);
          }}
          onMouseUp={(e) => {
            _self.dragFinish(e);
          }}
          onMouseLeave={(e) => {
            _self.dragFinish(e);
          }}
          onTouchMove={(e) => {
            // console.log(`onTouchMove`, e);
            _self.dragMoving(e);
          }}
          onTouchEnd={(e) => {
            // console.log(`onTouchEnd`, e);
            _self.dragFinish(e);
          }}
        >
          <div
            ref={_self.progressBarRef}
            className={`dv_progress_bar ${_self.state.isOk ? "goFirst2" : ""}`}
            style={_self.progressBarStyle}
          ></div>

          <div
            ref={_self.messageRef}
            className="dv_text"
            style={_self.textStyle}
          >
            {_self.message}
          </div>

          <div
            ref={_self.handlerRef}
            className={`dv_handler dv_handler_bg ${
              _self.state.isOk ? "goFirst" : ""
            }`}
            style={_self.handlerStyle}
            onMouseDown={(e) => {
              _self.dragStart(e);
            }}
            onTouchStart={(e) => {
              // console.log(`onTouchStart`, e);
              _self.dragStart(e);
            }}
          >
            <i
              className={`${_self.props.handlerIcon} handler-icon`}
              style={_self.handlerIconStyle}
            ></i>
          </div>
        </div>
      </div>
    );
  }

  componentDidMount() {
    const _self = this;
    // 1>任务初始化
    _self.initTask(() => {});
  }
  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-sliding-verifier shouldComponentUpdate...", needRender);
    if (needRender) {
      return true;
    }

    return false;
    // return true;
  }
  componentDidUpdate(prevProps, prevState) {
    // const _self = this;
    // console.log(`componentDidUpdate`, _self.props);
  }
  componentWillUnmount() {}

  //#endregion

  //#region methods

  /**
   * 任务初始化
   * @param {function} callBack 回调函数
   * @return {void}
   */
  initTask(callBack) {
    const _self = this;
    // 1>定义样式变量
    _self.definedStyleVariable();
    callBack && callBack();
  }
  /**
   * 定义样式变量
   * @return {void}
   */
  definedStyleVariable() {
    const _self = this;
    const dragEl = _self.dragVerifyRef.current;
    if (!dragEl) {
      return false;
    }
    dragEl.style.setProperty("--textColor", _self.props.textColor);
    dragEl.style.setProperty(
      "--width",
      `${Math.floor(_self.props.width / 2)}px`
    );
    dragEl.style.setProperty(
      "--pwidth",
      `${-Math.floor(_self.props.width / 2)}px`
    );
  }

  dragStart(e) {
    const _self = this;
    // console.log(`dragStart`, e.button);
    if (e.button && e.button != 0) {
      return false;
    }
    // console.log(`dragStart-isPassing`, _self.props.isPassing);
    if (!_self.props.isPassing) {
      _self.setState(
        {
          isMoving: true,
          x: e.pageX || e.touches[0].pageX,
        },
        () => {
          _self.props.handlerMove && _self.props.handlerMove();
          // console.log(`dragStart-state`, _self.state);
        }
      );
    } else {
      _self.props.handlerMove && _self.props.handlerMove();
    }
  }
  dragMoving(e) {
    const _self = this;
    // console.log(
    //   `dragMoving`,
    //   `isMoving:${_self.state.isMoving}`,
    //   `isPassing:${_self.props.isPassing}`
    // );
    // console.log(`dragMoving`, e);
    if (_self.state.isMoving && !_self.props.isPassing) {
      const _x = (e.pageX || e.touches[0].pageX) - _self.state.x;
      if (_x > 0 && _x <= _self.props.width - _self.props.height) {
        _self.handlerRef.current.style.left = _x + "px";
        if (_self.props.fullFilling) {
          _self.progressBarRef.current.style.width = `${
            _x + _self.props.height / 2
          }px`;
        } else {
          _self.progressBarRef.current.style.width = `${
            _x + _self.props.height
          }px`;
        }
      } else if (_x > _self.props.width - _self.props.height) {
        _self.handlerRef.current.style.left = `${
          _self.props.width - _self.props.height
        }px`;
        if (_self.props.fullFilling) {
          _self.progressBarRef.current.style.width = `${
            _self.props.width - _self.props.height / 2
          }px`;
        } else {
          _self.progressBarRef.current.style.width = `${_self.props.width}px`;
        }

        _self.passVerify();
      }
    }
  }
  dragFinish(e) {
    const _self = this;
    // console.log(`dragFinish`, e);
    // console.log(
    //   `dragFinish outer`,
    //   `isMoving:${_self.state.isMoving}`,
    //   `isPassing:${_self.props.isPassing}`
    // );
    if (_self.state.isMoving && !_self.props.isPassing) {
      const _x = (e.pageX || e.changedTouches[0].pageX) - _self.state.x;
      // console.log(
      //   `dragFinish inner`,
      //   `_x:${_x}`,
      //   `_self.props.width:${_self.props.width}`,
      //   `_self.props.height:${_self.props.height}`
      // );
      if (_x < _self.props.width - _self.props.height) {
        const that = this;
        _self.setState(
          {
            isOk: true,
          },
          () => {
            setTimeout(() => {
              that.handlerRef.current.style.left = "0";
              that.progressBarRef.current.style.width = "0";
              that.setState({
                isOk: false,
              });
            }, 500);
          }
        );
        _self.props.handlerVerifyFail && _self.props.handlerVerifyFail();
      } else {
        _self.handlerRef.current.style.left = `${
          _self.props.width - _self.props.height
        }px`;
        if (_self.props.fullFilling) {
          _self.progressBarRef.current.style.width = `${
            _self.props.width - _self.props.height / 2
          }px`;
        } else {
          _self.progressBarRef.current.style.width = `${_self.props.width}px`;
        }

        _self.passVerify();
      }
      _self.setState(
        {
          isMoving: false,
        },
        () => {}
      );
    }
  }
  passVerify() {
    const _self = this;
    // console.log(`passVerify`);
    _self.props.updateIsPassing && _self.props.updateIsPassing(true);

    _self.handlerRef.current.children[0].className = _self.props.successIcon;
    _self.progressBarRef.current.style.background = _self.props.completedBg;
    _self.messageRef.current.style["-webkit-text-fill-color"] = "unset";
    _self.messageRef.current.style.animation = "slidetounlock2 3s infinite";
    _self.messageRef.current.style.color = "#ffffff";
    _self.props.handlerVerifySuccess && _self.props.handlerVerifySuccess();

    _self.setState(
      {
        isMoving: false,
      },
      () => {}
    );
  }

  reset() {
    const _self = this;
    // const oriData = _self.$options.data();
    // for (const key in oriData) {
    //   if (Object.prototype.hasOwnProperty.call(oriData, key)) {
    //     this[key] = oriData[key];
    //   }
    // }
    // var handler = _self.$refs.handler;
    // var message = _self.$refs.message;
    // handler.style.left = "0";
    // _self.$refs.progressBar.style.width = "0";
    // handler.children[0].className = _self.handlerIcon;
    // message.style["-webkit-text-fill-color"] = "transparent";
    // message.style.animation = "slidetounlock 3s infinite";
    // message.style.color = _self.background;

    // console.log(`reset`);

    // 初始化验证器成功标志位
    _self.props.updateIsPassing && _self.props.updateIsPassing(false);
    // 设置状态
    _self.setState(
      {
        isMoving: false,
        x: 0,
        isOk: false,
      },
      () => {
        //
        // dragVerifyRef = React.createRef();
        // progressBarRef = React.createRef();
        // messageRef = React.createRef();
        // handlerRef = React.createRef();

        const { handlerIcon, handlerIconColor } = _self.props;

        const progressBar = _self.progressBarRef.current;
        const handler = _self.handlerRef.current;
        const message = _self.messageRef.current;

        progressBar.style.width = "0";
        handler.style.left = "0";
        handler.children[0].className = handlerIcon;
        handler.children[0].style.color = handlerIconColor;

        message.style["-webkit-text-fill-color"] = "transparent";
        message.style.animation = "slidetounlock 3s infinite";
        // message.style.color = _self.background;
      }
    );
  }

  //#endregion
}
