import React, { useEffect, useState, useRef } from 'react';
import { Form, Button, Input, Row, Col, Modal, Spin, message, Tabs } from 'antd';
import { UserOutlined, LockOutlined, SafetyCertificateOutlined } from '@ant-design/icons';
import './style.less';
import { changePass } from './service';
import logo from '@/images/login/logoPic.png';
import { refreshTokenApi, ZjfakeAccountLogin, ZjfakeFaceLogin } from '@/services/login';
import { history } from 'umi';
import cookie from 'react-cookies';
import moment from 'moment';
import FrameFaceLogin from '../faceLogin/FrameFaceLogin';
import LivingNotIE from './living.min.js';
import { _KJUR } from './jsrsasign-latest-all-min';
import { time } from 'echarts';

const layout = {
  labelCol: { span: 7 },
  wrapperCol: { span: 13 },
};

export interface RgbParams {
  type: string;
  image: string;
}

const Index: React.FC<{}> = () => {
  const [form] = Form.useForm();
  const [form2] = Form.useForm();
  const [imgUrl, setImgUrl] = useState<any>('');
  const [tmpToken, setTmpToken] = useState<any>('');
  const remainingTime = 3 //刷新token的剩余时间，单位小时
  const [changeForm] = Form.useForm();
  const [isModalVisible, setIsModalVisible] = useState<boolean>(false)
  const [spinning, setSping] = useState<boolean>(false);//加载遮罩
  const video = useRef();
  const whetherIE = useRef<boolean>(false);
  const mediaStreamTrack = useRef<any>();
  const { TabPane } = Tabs;
  const [submitLoading, setSubmitLoading] = useState<boolean>(false);
  const [faceLoginDisable, setFaceLoginDisable] = useState<boolean>(false);  
  const lv = useRef<LivingNotIE>();
  const [timerShow, setTimeShow] = useState<boolean>(false);
  const [itemShow, setItemShow] = useState<boolean>(false);
  const [action, setAction] = useState<number>(1);
  const [timer, setTimer] = useState<number>(10000);
  /**
   * 设置活体检测token
   */
  const setLiveDetectToken = () =>{
    let appKey= 'nkYy3g1yT0alE8pF6a1UTC4I'
    let appSecrect = 'L30zHpTyAtTlY7tTCpbzdxxKCQgwWIQL'
    // Header
    var header = {
      typ: "JWT", // 声明类型
      alg: "HS256" // 声明加密的算法 通常直接使用 HMAC SHA256
    };

    var payload = {
      iss: appKey,
      iat: moment().unix(),
      exp: moment()
        .add(29, "minutes")
        .unix()
    };
    var sHeader = JSON.stringify(header);
    var sPayload = JSON.stringify(payload);
    var sJWT = _KJUR.jws.JWS.sign("HS256", sHeader, sPayload, {
      utf8: appSecrect,
    });
    console.log(sJWT);
    return sJWT;
  };
  /**
   * 开始人脸识别（活体和比对）
   */
  const liveDetectStart = () => {
    liveDetectStop();
     let _lv = new LivingNotIE(null, {
      timer: 10000,
      action : [1,3,2],
      token: setLiveDetectToken(),
      proxy:'/living/api',
      getFacePicture:()=>{
        return getLiveDetectFile()
      },
      //开始活体检测，此时token已鉴权成功
      onDetectStart:()=>{
        setSubmitLoading(true);
      },
      //每轮检测开始
      onDetectActionStart:(action:number)=>{
        setAction(action);
        // this.drawCanvas()
      },
      //每轮检测计时
      onDetectActionProgress:(action:number,timer:number)=>{
        setTimer(timer);
      },
      //每轮检测结束
      onDetectActionFinish:(action:number,data:any)=>{
        // this.clearCanvas()
        setTimer(10000);
        console.log(data)
      },
      //活体检测完成
      onDetectFinish:(data:any)=>{
        if(data.code == 1){
          setAction(4);
          setTimeShow(false);
          //人脸比对
          hanleFaceSubmit(data.file.file, null);
        }else{
          message.error('活体检测失败');
          setSubmitLoading(false);
        }
        // data.code === 1? message.success('活体检测通过'):message.error('活体检测失败')
      }
    });
    //开始检测
    _lv.start();
    lv.current = _lv;
  }
  /**
   * 停止活体检测
   */
  const liveDetectStop = () => {
    lv.current && lv.current.stop();
  }
  /**
   * 给活体检测提供照片
   * @returns 活体照片
   */
  const getLiveDetectFile = () => {
    const canvas = document.createElement('canvas');
    canvas.setAttribute('width', '300');
    canvas.setAttribute('height', '200');
    const context = canvas.getContext('2d');
    context.drawImage(video.current, 0, 0, 300, 200);
    let _imgURI = canvas.toDataURL("image/jpeg",);
    console.log(_imgURI);
    let _file = base64ToBlob(_imgURI);
    return {
      file:_file//传给活体检测服务的文件
    }
  }
  const classColor = (action:any) => {
    let color = '';
    switch(action){
      case 1:
        color = '#409eff';
        break;
      case 2:
        color = '#5daf34';
        break;
      case 3:
        color = 'gold';
        break;
      case 4:
        color = 'grey';
        break;
    }
    return color;
  }
  const actionText = (action:number, timer:number) => {
    let text = '';
    switch(action){
      case 1:
        text = '对准摄像头眨眨眼（'+ timer + 's）';
        break;
      case 2:
        text = '对准摄像头张张嘴（'+ timer + 's）';
        break;
      case 3:
        text = '对准摄像头摇摇头（'+ timer + 's）';
        break;
      case 4:
        text = '请稍候，正在验证中...';
    }
    return text;
  }

  const genRandomString = (len: number) => {
    const text = 'abcdefghijklmnopqrstuvwxyz0123456789';
    const rdmIndex = (text: string | any[]) => (Math.random() * text.length) | 0;
    let rdmString = '';
    for (; rdmString.length < len; rdmString += text.charAt(rdmIndex(text)));
    return rdmString;
  };
  const changeCaptcha = () => {
    let tmpToken = genRandomString(16);
    let url = '/api/auth/captcha?token=' + tmpToken;
    setTmpToken(tmpToken);
    setImgUrl(url);
  };

  //登录刷新Token方法
  const refreshToken = async (data: any) => {
    const params = {
      grant_type: "refresh_token",
      refresh_token: data?.refreshToken?.value,
      client_id: REACT_APP_CLIENT_KEY,
      client_secret: REACT_APP_CLIENT_SECRET,
    }
    const header = {
      clientId: REACT_APP_CLIENT_KEY,
    }
    await refreshTokenApi(params, header).then(res => {
      if (res?.success == true) {
        sessionStorage.setItem('Authorization', res?.data?.value);
        // sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
        sessionStorage.setItem('scope', res?.data?.scope);
        history.push('/redirect');
      }
    })
  }

  const handleSubmit = async (values: any) => {
    await ZjfakeAccountLogin({ ...values, tmpToken }).then((res) => {
      if (res?.success) {
        if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
          refreshToken(res?.data)
        } else {
          sessionStorage.setItem('Authorization', res?.data?.value);
          // sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
          sessionStorage.setItem('scope', res?.data?.scope);
          history.push('/redirect');
        }
      }
      changeCaptcha();
    });
  };

  const onChange = (key: string) => {
    if (key == '2') {
      BrowserType();
      InitMedia();
    } else {
      if (allowedToFaceLogin()) {
        if (whetherIE.current) {
          releaseCamera('faceLoginFrame');
        } else {
          mediaStreamTrack.current?.stop();
        }
      }
    }
  };

  const releaseCamera = (id: string) => {
    const childFrameObj = document.getElementById(id);
    childFrameObj?.contentWindow?.postMessage('releaseCamera', '*');
  }

  const hanleFaceSubmit = async (multipartFiles: any, values: any) => {
    let userName = form2.getFieldValue('userName');
    if (whetherIE.current) {
      if (!multipartFiles) {
        const childFrameObj = document.getElementById('faceLoginFrame');
        childFrameObj.contentWindow.postMessage('capture', '*');
      } else {
        await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => {
          if (res?.success) {
            if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
              refreshToken(res?.data)
            } else {
              releaseCamera('faceLoginFrame');
              sessionStorage.setItem('Authorization', res?.data?.value);
              sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
              sessionStorage.setItem('scope', res?.data?.scope);
              history.push('/redirect');
            }
          }
        })
          .finally(
            () => { setSubmitLoading(false); }
          );
      }
    }
    else {
      if (!multipartFiles) {
        const canvas = document.createElement('canvas');
        canvas.setAttribute('width', '300');
        canvas.setAttribute('height', '200');
        document.body.appendChild(canvas);
        const context = canvas.getContext('2d');
        context.drawImage(video.current, 0, 0, 300, 200);
        canvas.toBlob(function (result: any) {
          hanleFaceSubmit(result, null);
        })
      } else {
        setSubmitLoading(true);
        await ZjfakeFaceLogin({ userName, multipartFiles }).then((res) => {
          if (res?.success) {
            if (moment(res?.data?.expiration).diff(moment(), 'hours') < remainingTime) {
              refreshToken(res?.data)
            } else {
              mediaStreamTrack.current?.stop();
              sessionStorage.setItem('Authorization', res?.data?.value);
              sessionStorage.setItem('refreshToken', res?.data?.refreshToken.value);
              sessionStorage.setItem('scope', res?.data?.scope);
              history.push('/redirect');
            }
          }
        })
          .finally(
            () => { setSubmitLoading(false); }
          );
      }
    }
  }

  const handleOk = () => { // 确定修改密码
    if (changeForm.getFieldValue("newPassword") !== changeForm.getFieldValue("newPassword1")) {
      message.warn('两次密码输入不一致，请重新输入')
    } else {
      changeForm.validateFields().then(res => {
        setSping(true);
        const date = {
          identityCard: changeForm.getFieldValue("identityCard"),
          oldPassword: changeForm.getFieldValue("oldPassword"),
          newPassword: changeForm.getFieldValue("newPassword"),
        };
        changePass({ ...date }).then(res => {
          if (res.success) {
            setSping(false);
            setIsModalVisible(false)
            message.success('修改密码成功');
            changeForm.resetFields()
          } else {
            setSping(false);
          }
        }).finally(() => {
          setSping(false);
        });;
      })
    }
  }
  //浏览器类型
  const BrowserType = () => {
    //取得浏览器的userAgent字符串
    var userAgent = navigator.userAgent;
    //判断是否IE<11
    var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1;
    //判断是否IE的Edge浏览器
    var isEdge = userAgent.indexOf("Edge") > -1 && !isIE;
    //判断是否IE11
    var isIE11 = userAgent.indexOf("Trident") > -1 && userAgent.indexOf("rv:11.0") > -1;
    if (isIE) {
      var reIE = new RegExp("MSIE(\\d+\\.\\d+);");
      reIE.test(userAgent);
      var fIEVersion = parseFloat(RegExp["$1"]);
      if (fIEVersion == 7) {
        return 7;
      } else if (fIEVersion == 8) {
        return 8;
      } else if (fIEVersion == 9) {
        return 9;
      } else if (fIEVersion == 10) {
        return 10;
      } else {
        //IE版本<=7
        return 6;
      }
    } else if (isEdge) {
      return 'edge';
    } else if (isIE11) {
      //IE11
      whetherIE.current = true;
      return 11;
    } else {
      //不是IE浏览器
      return -1;
    }
  }
  //初始化video
  const InitMedia = () => {
    if (!whetherIE.current) {
      InitUserMedia({ video: { width: 480, height: 320 } }, success, error);
    }
  };
  //访问用户媒体设备的兼容方法
  const InitUserMedia = (constraints: any, success: any, error: any) => {
    if (navigator.mediaDevices?.getUserMedia) {
      //最新的标准API
      navigator.mediaDevices?.getUserMedia(constraints).then(success).catch(error);
    } else if (navigator.webkitGetUserMedia) {
      //webkit核心浏览器
      navigator.webkitGetUserMedia(constraints, success, error);
    } else if (navigator.mozGetUserMedia) {
      //firfox浏览器
      navigator.mozGetUserMedia(constraints, success, error);
    } else if (navigator.getUserMedia) {
      //旧版API
      navigator.getUserMedia(constraints, success, error);
    }
  }
  //调用媒体设备成功回调方法
  const success = (stream: any) => {
    var result = stream.getVideoTracks().some(function (track: any) {
      return track.enabled && track.readyState === 'live';
    });
    if (result) {
      //兼容webkit核心浏览器
      const CompatibleURL = window.URL || window.webkitURL;
      //将视频流设置为video元素的源
      console.log(stream);
      //video.src = CompatibleURL.createObjectURL(stream);
      video.current.srcObject = stream;
      mediaStreamTrack.current = stream.getTracks()[0];
      video.current.play();
    }
  }
  //调用媒体设备失败回调方法    
  const error = (error: any) => {
    message.warn('无法获取到摄像头权限，请确认是否存在摄像头及是否授权使用摄像头');
    console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
  }

  //base64转blob
  const base64ToBlob = (base64: string) => {
    const parts = base64.split(";base64,");
    const contentType = parts[0].split(":")[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; i += 1) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
  };

  const IELiveDetectFinish2 = async(data:any) => {
    console.log(data);
    setAction(4);
    hanleFaceSubmit(data, null);
  }

  //IELiveDetectFinish
  const IELiveDetectFinish = async (data: any) => {
    if(data.code != 0){
      console.log(data);
      setAction(4);
      hanleFaceSubmit(data.file.file, null);
    }else{
      message.error('活体检测失败');
      setSubmitLoading(false);
    }
  }

  const UpdateDetectStatus = async(action:number, timer:number)=>{
    setSubmitLoading(true);
    setAction(action);
    setTimer(timer);
  }

  //是https或者是本地
  const httpsOrLocal = () => {
    let protocol = document.location.protocol;
    if (protocol == 'https:') {
      return true;
    } else {
      let host = window.location.hostname;
      if (host == '127.0.0.1' || host == 'localhost') {
        return true;
      }
    }
    return false;
  }

  //是否允许人脸登录
  const allowedToFaceLogin = () => {
    let browseType = BrowserType()
    if ((browseType == 11 || browseType == -1) && httpsOrLocal()) {
      return true;
    }
    return false;
  }


  useEffect(() => {
    cookie.remove('mall3_token');
    sessionStorage.clear();
    changeCaptcha();
    if (!allowedToFaceLogin()) {
      setFaceLoginDisable(true);
    }
  }, []);

  return (
    <Spin spinning={spinning}>
      <div className="login-box">
        <div className="top">
          <img src={logo} />
          <h3>中国联通智慧供应链平台 | 招标采购中心</h3>
          <Button className="change" danger style={{ borderColor: '#b30000', color: '#b30000' }} onClick={() => (setIsModalVisible(true), changeForm.resetFields())}>修改密码</Button>
        </div>
        <div className="main">
          <div className="text">
            <Tabs defaultActiveKey="1" onChange={onChange} size={'large'}>
              <TabPane tab="账号密码登录" key="1">
                <Form
                  name="basic"
                  className="form-box"
                  initialValues={{ remember: true }}
                  form={form}
                  onFinish={handleSubmit}
                // onFinishFailed={onFinishFailed}
                >
                  <Form.Item
                    label=""
                    name="userName"
                    rules={[{ required: true, message: '请输入用户名!' }]}
                  >
                    <Input
                      prefix={
                        <UserOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
                      }
                      placeholder="请输入用户名"
                    />
                  </Form.Item>
                  <Form.Item
                    label=""
                    name="password"
                    rules={[{ required: true, message: '请输入密码!' }]}
                  >
                    <Input.Password
                      prefix={
                        <LockOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
                      }
                      placeholder="请输入密码"
                    />
                  </Form.Item>

                  <Row>
                    <Col span={14}>
                      <Form.Item
                        label=""
                        name="captcha"
                        rules={[{ required: true, message: '请输入验证码!' }]}
                      >
                        <Input
                          prefix={
                            <SafetyCertificateOutlined
                              style={{ fontSize: '18px' }}
                              className="site-form-item-icon"
                            />
                          }
                          placeholder="请输入验证码"
                        />
                      </Form.Item>
                    </Col>
                    <Col span={10}>
                      <img className="verification" onClick={() => changeCaptcha()} src={imgUrl} />
                    </Col>
                  </Row>

                  {/* <Form.Item className="remember" name="remember" valuePropName="checked">
                  <Checkbox>记住密码</Checkbox>
                </Form.Item> */}
                  <Form.Item>
                    <Button type="primary" className="w100" htmlType="submit">
                      登 录
                    </Button>
                  </Form.Item>
                </Form>
              </TabPane>
              <TabPane tab="人脸识别登录" key="2" disabled={faceLoginDisable}>
                <Form
                  name="basic2"
                  className="form-box"
                  initialValues={{ remember: true }}
                  form={form2}
                  // onFinish={hanleFaceSubmit.bind(this, null)}
                  onFinish={!whetherIE.current?liveDetectStart:hanleFaceSubmit.bind(this, null)}
                // onFinishFailed={onFinishFailed}
                >
                  <Form.Item
                    label=""
                    name="userName"
                    rules={[{ required: true, message: '请输入用户名!' }]}
                  >
                    <Input
                      prefix={
                        <UserOutlined style={{ fontSize: '18px' }} className="site-form-item-icon" />
                      }
                      placeholder="请输入用户名"
                    />
                  </Form.Item>
                  {/* 加载摄像头 */}
                  {/* <Form.Item hidden={!itemShow}>
                    <div>
                      <span style={{color:classColor(action)}}>{actionText(action)}</span>
                      <span hidden={!timerShow}>{Math.round(timer/1000)}</span>
                    </div>
                  </Form.Item> */}
                  <Form.Item>
                    {!whetherIE.current ? (<video ref={video} width="382" height="200"></video>) : (<FrameFaceLogin faceCompareEvent2={IELiveDetectFinish2} faceCompareEvent={IELiveDetectFinish} faceDetectStatusEvent = {UpdateDetectStatus}/>)}
                    {/* <video ref={video} width="382" height="200"></video> */}
                  </Form.Item>
                  <Form.Item>
                    {/* onClick={() => {hanleFaceSubmit(null, null);}} */}
                    <Button type="primary" className="w100" loading={submitLoading} htmlType="submit">
                      {submitLoading ? actionText(action, Math.round(timer/1000)) : '登 录'}
                    </Button>
                  </Form.Item>
                </Form>
              </TabPane>
            </Tabs>
          </div>
        </div>
        <Modal
          title="修改密码"
          visible={isModalVisible}
          onCancel={() => setIsModalVisible(false)}
          footer={[
            <Button onClick={() => handleOk()} loading={spinning}>确 定</Button>,
            <Button onClick={() => setIsModalVisible(false)}>取 消</Button>
          ]}
          width={600}
        >
          <Spin spinning={spinning}>
            <Form
              {...layout}
              name="basic"
              form={changeForm}
            >
              <Form.Item
                label="身份证(用户名)"
                name="identityCard"
                rules={[
                  {
                    required: true,
                    message: '请输入身份证(用户名)',
                  },
                ]}
              >
                <Input />
              </Form.Item>
              <Form.Item
                label="原密码"
                name="oldPassword"
                rules={[
                  {
                    required: true,
                    message: '请输入原始密码',
                  },
                ]}
              >
                <Input.Password />
              </Form.Item>
              <Form.Item
                label="新密码"
                name="newPassword"
                rules={[
                  {
                    required: true,
                    validator: (rule, value, callback) => {
                      const oNumber = new RegExp(/\d/);
                      const oLetter = new RegExp(/[a-zA-Z]/);
                      const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';
                      if (!value) {
                        callback('请输入新密码');
                        return;
                      }
                      if (value.length < 6) {
                        callback('密码不能小于六位，至少含字母、数字、特殊字符其中的2种！');
                        return;
                      }
                      try {
                        [...value].forEach(val => {
                          if (
                            !(
                              oNumber.test(val) ||
                              oLetter.test(val) ||
                              oSpecial.indexOf(val) >= 0
                            )
                          ) {
                            throw new Error();
                          }
                        });
                      } catch (e) {
                        callback('密码不能小于六位，至少含字母、数字、特殊字符其中的2种！');
                      }
                      const contain: boolean[] = [];
                      [...value].forEach(val => {
                        if (oNumber.test(val)) {
                          contain[0] = true;
                        }
                        if (oLetter.test(val)) {
                          contain[1] = true;
                        }
                        if (oSpecial.indexOf(val) >= 0) {
                          contain[2] = true;
                        }
                      });
                      if (contain.filter(item => item === true).length < 2) {
                        callback('密码不能小于六位，至少含字母、数字、特殊字符其中的2种！');
                        return;
                      }
                      callback();
                    }
                  }
                ]}
              // rules={[
              //   {
              //     required: true,
              //     message: '请输入新密码',
              //   },
              // ]}
              >
                <Input.Password />
              </Form.Item>
              <Form.Item
                label="新密码确认"
                name="newPassword1"
                rules={[
                  {
                    required: true,
                    message: '请再次输入新密码',
                  },
                ]}
              >
                <Input.Password />
              </Form.Item>
            </Form>
          </Spin>
        </Modal>
      </div>
    </Spin>
  );
};

export default Index;

