/**
 * 移动端扫码组件
 */
import { ScanOutlined } from "@ant-design/icons";
import { Button, message } from "antd";
import React from "react";
import { Renderer, RendererProps } from '../factory';
import { createObject, isMobile } from "../utils/helper";
import { Shell } from "../utils/shell";
import MSG from '../renderers/Lion/utils/msgsub';
import { IScopedContext, ScopedContext } from "../Scoped";
import { ApiObject } from "../types";
import Modal from "antd/lib/modal/Modal";
import Input from "antd/lib/input/Input";
import { tools } from "../utils/shell/tools";
import { eventStation, RuleTypes } from "../utils/shell/shell";
import { findDOMNode } from "react-dom";
import { RFIDTrigeerCodeEnum, windowRFIDTriger } from "../utils/RfidUtil";
import { KeyStepCommonFunction } from "../utils/keyStep";

declare const wx: any;
interface ScanCodeProps extends RendererProps {
  type: "scan-code",
  reload: string,
  api: ApiObject,
  scanTriggerMode: RFIDTrigeerCodeEnum,
  valueAttr?: string,
  actionLabel?: {
    codeLabel: string
  }
}
interface ScanCodeState {
  position: {
    x: number,
    y: number
  },
  visible: boolean,
  codeValue: string
}
class ScanCode extends React.Component<ScanCodeProps, ScanCodeState> {
  startX = 0;
  startY = 0;
  codeEvent: Function;//红外线扫码
  hash: string = '';
  constructor(props: ScanCodeProps) {
    super(props);
    this.state = {
      position: {
        x: (document.body.clientWidth - 280) / 2,
        y: 200
      },
      visible: false,
      codeValue: ''
    }
  }

  componentDidMount() {
    // if (this.props.scanTriggerMode)
    // windowRFIDTriger.addEventListener(this.props.scanTriggerMode, this.handleScanCode)
    // message.success('我注册了')
    windowRFIDTriger.addEventListener(this.props.scanTriggerMode || RFIDTrigeerCodeEnum.TRIGGERCLICK, this.handleScanCode)
    tools.isComWx && this.initData();
    this.hash = window.location.hash.slice(1);
    this.codeEvent = eventStation.subscription<{ code: string; href: string }>(RuleTypes.ShellCode, ({ code, href }) => {
      if (this.hash == href) {
        this.dealCode(code)
      }
    })
  }

  componentWillUnmount() {
    // if (this.props.scanTriggerMode)
    // windowRFIDTriger.removeEventListener(this.props.scanTriggerMode, this.handleScanCode)
    windowRFIDTriger.removeEventListener(this.props.scanTriggerMode || RFIDTrigeerCodeEnum.TRIGGERCLICK, this.handleScanCode)
    this.codeEvent?.();
  }

  initData = async () => {
    const { env } = this.props;
    const res = await env.fetcher({ url: '/api/v1/js/api/sdk', method: 'post' }, { jsSdkUrl: location.href.split('#')[0] })
    if (res.status == 0 && res.data != null) {
      const corpId = res.data.corpId
      if (corpId) {
        const sysConfig: any = res.data;
        const data = {
          debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
          appId: sysConfig.corpId, // 必填，企业微信的corpID，必须是本企业的corpID，不允许跨企业使用
          timestamp: sysConfig.timestamp, // 必填，生成签名的时间戳
          nonceStr: sysConfig.noncestr, // 必填，生成签名的随机串
          signature: sysConfig.signature,// 必填，签名，见 附录-JS-SDK使用权限签名算法
          jsApiList: ['scanQRCode', 'checkJsApi']
        }
        wx.config(data);
        wx.error(function (res: any) {
          message.warn(res?.errMsg || '鉴权失败')
        })
      }
    } else {
      message.error(res.msg)
    }
  }

  dealCode = async (codeValue: string) => {
    const { reload, valueAttr, env, api } = this.props;
    try {
      const data = { [valueAttr ?? 'scanValue']: codeValue }
      const ctx = createObject(this.props.data, data)
      const payload = await env.fetcher({ url: api.url, method: 'post', data: api.data }, ctx)
      if (payload.ok && payload.status == 20003) {
        await KeyStepCommonFunction(payload.data.scanAfterDo, data, env)
      }
      if (payload.status === 0 || payload.status == 20003) {
        const ctx = createObject(this.props.data, payload.data)
        reload && this.reloadTarget(reload, ctx);
        if (this.state.visible) {
          this.setState({ visible: false, codeValue: '' })
        }
        message.success(payload.msg)
      }
    } catch (error) {
      MSG._error('条码出错' + error);
    }
  }
  handleScanCode = async () => {
    if (Shell.hasShell()) {
      Shell.getScanCode().then(async res => {
        if (res.success) {
          this.dealCode(res.data.content)
        } else {
          MSG._info(res.msg)
        }
      })
    } else {
      if (tools.isComWx) {
        this.getWorkScanCode()
      } else {
        this.setState({ visible: true })
      }
    }
  }

  //使用企微的扫一扫
  getWorkScanCode = () => {
    wx.scanQRCode({
      desc: 'scanQRCode desc',
      needResult: 1, // 默认为0，扫描结果由企业微信处理，1则直接返回扫描结果，
      scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是条形码（一维码），默认二者都有
      success: (res: any) => {
        // 回调
        if (res.resultStr) {//当needResult为1时返回处理结果
          this.dealCode(res.resultStr)
        } else {
          message.error('无效码')
        }
      },
      error: (res: any) => {
        if (res.errMsg.indexOf('function_not_exist') > 0) {
          alert('版本过低请升级')
        } else {
          alert(res.errMsg)
        }
      },
      fail: (res: any) => {
        if (res.errMsg.indexOf('function_not_exist') > 0) {
          alert('版本过低请升级')
        } else {
          alert(res.errMsg)
        }
      }
    });
  }

  reloadTarget(target: string, data: any) { }

  //起始位置
  originX = 0;
  originY = 0;
  //拖动过程中的临时位置
  movingX = 0;
  movingY = 0;
  touchStart = (e: React.TouchEvent<HTMLDivElement>) => {
    e.persist()
    e.preventDefault()
    e.stopPropagation()
    e.persist()
    e.preventDefault()
    e.stopPropagation()
    if (e.touches.length > 0) {
      const touch = e.touches[0];
      this.originX = this.movingX = touch.clientX; // 记录触摸开始的横坐标
      this.originY = this.movingY = touch.clientY; // 记录触摸开始的纵坐标
    }
  }

  touchMove = (e: React.TouchEvent<HTMLDivElement>) => {
    e.persist()
    e.preventDefault()
    e.stopPropagation()
    if (e.changedTouches.length > 0) {
      const touch = e.changedTouches[0];
      const endX = touch.clientX; // 触摸结束的横坐标
      const endY = touch.clientY; // 触摸结束的纵坐标
      const moveX = endX - this.movingX; // 横向移动距离
      const moveY = endY - this.movingY; // 纵向移动距离
      if (moveX == 0 && moveY == 0) {
      } else {
        this.movingX = touch.clientX;
        this.movingY = touch.clientY;
        let nx = this.state.position.x + moveX;
        let ny = this.state.position.y - moveY;
        const dom = findDOMNode(this) as HTMLDivElement;
        if (nx <= 2) nx = 2;
        if (nx > dom.clientWidth - 280) nx = dom.clientWidth - 280;
        if (ny <= 2) ny = 2;
        if (ny > dom.clientHeight - 50) ny = dom.clientHeight - 50;
        this.setState({ position: { x: nx, y: ny } });
      }
    }
  }

  touchEnd = (e: React.TouchEvent<HTMLDivElement>) => {
    // e.persist()
    // e.preventDefault()
    // e.stopPropagation()
    // if (e.changedTouches.length > 0) {
    //   const touch = e.changedTouches[0];
    //   const endX = touch.clientX; // 触摸结束的横坐标
    //   const endY = touch.clientY; // 触摸结束的纵坐标
    //   // 如果拖动的距离很小，认为是一次单击事件
    //   const distance = Math.sqrt(
    //     (endX - this.originX) ** 2 + (endY - this.originY) ** 2
    //   );
    //   if (distance < 1) {
    //     // 在这里处理单击事件
    //     // this.handleScanCode()
    //   }
    // }
  }
  render() {
    const { render, classnames: cx, body, actionLabel } = this.props;
    const { position, visible, codeValue } = this.state;
    return (
      <div className={cx("Scan-code-container")}>
        {isMobile() &&
          <div className={cx("Scan-btn")}
            onTouchStart={this.touchStart}
            onTouchMove={this.touchMove}
            onTouchEnd={this.touchEnd}
            style={{ display: 'flex', position: 'absolute', left: position.x, bottom: position.y }}
          >
            <Button
              type="link"
              size="large"
              style={{ backgroundColor: '#3574ee', color: 'white', paddingLeft: 40, width: 176, height: 46, borderTopLeftRadius: 40, borderBottomLeftRadius: 40 }}
              onClick={(e) => {
                e.stopPropagation();
                this.handleScanCode()
              }} icon={<ScanOutlined />}
            >
              {actionLabel?.codeLabel || '点击扫码'}
            </Button>
            <div style={{ position: 'absolute', left: 175, zIndex: 1, width: 24, height: 46, backgroundColor: '#3574ee', borderTopRightRadius: 40, borderBottomRightRadius: 40 }}></div>
            <Button
              type="link"
              size="large"
              style={{ backgroundColor: 'rgba(0,0,0,0.26)', color: 'white', paddingLeft: 30, borderColor: 'transparent', width: 104, height: 46, borderTopRightRadius: 40, borderBottomRightRadius: 40 }}
              onClick={(e) => {
                e.stopPropagation();
                this.setState({ visible: true })
              }}
            >
              输入
            </Button>
          </div>
        }
        {render('scan-code', body)}
        {
          visible && <Modal className="scan-code-modal" visible={visible} closable={false}
            okText="确定" cancelText="取消" width={320} style={{ top: 200 }}
            maskClosable={false}
            onCancel={() => {
              this.setState({ visible: false, codeValue: '' })
            }}
            zIndex={1011}
            onOk={() => {
              if (codeValue) {
                this.dealCode(codeValue)
                this.setState({ visible: false })
              } else {
                message.warn('请输入条码内容!')
              }
            }}
            getContainer={this.props.env.getModalContainer}
          >
            <div className="code-input-container">
              <div className="title">请输入条码内容</div>
              <div className="input-box">
                <Input onChange={(e) => {
                  this.setState({ codeValue: e.target.value })
                }} autoFocus value={codeValue} />
              </div>
            </div>
          </Modal>
        }
      </div>
    )
  }
}

@Renderer({
  type: 'scan-code',
  isolateScope: true,
})
export class ScanCodeRenderer extends ScanCode {
  static contextType = ScopedContext;
  constructor(props: ScanCodeProps, context: IScopedContext) {
    super(props);
    const scoped = context;
    scoped.registerComponent(this);
  }

  reloadTarget(target: string, data: any) {
    const scoped = this.context as IScopedContext;
    scoped.reload(target, data);
  }
}