import React, { useRef, useState, useCallback, useEffect } from 'react';
import { Card, Col, Row, Select, Spin, Progress, Input,Space } from 'antd';
import Webcam from 'react-webcam'
import { CameraOutlined } from '@ant-design/icons';
import { useLocation, useNavigate } from 'react-router-dom';
import * as storage from '@/utils/storage';

import './style.css'
const { Meta } = Card;

var httpURL = "http://192.168.0.70:1985/rtc/v1/publish/";
var webRTCURL = "webRTC://192.168.0.70/live/1";
var gestureURL = "api/gesture/live";
var wsURL = "ws://192.168.0.50:8888/";

let timer = null as any;
let pc = null as any;// 全局的RTCPeerConnection

// 定义全局属性
let videoStream = null;


const { Option } = Select
const ValidationPage = () => {
  const navigate = useNavigate();
  const { state } = useLocation();
  const myVideo = useRef<HTMLVideoElement>() as any; // video标签
  const [percent, setPercent] = useState(0) as any;
  const [spinning, setSpinning] = useState(false) as any;
  const [cameras, setCameras] = useState([]);
  const [selectedCamera, setSelectedCamera] = useState(null);
  const [wsObj, setWsObj] = useState({}) as any;

  const username = storage.get('username');

  useEffect(() => {
    const getCameras = async () => {
      try {
        const devices = await navigator.mediaDevices.enumerateDevices();
        const videoDevices = devices.filter(device => device.kind === 'videoinput') as any;
        setCameras(videoDevices);

        // 自动选择第一个摄像头，如果有的话
        if (videoDevices.length > 0) {
          setSelectedCamera(videoDevices[0].deviceId);
          // startCamera(videoDevices[0].deviceId);
        }
      } catch (err) {
        console.error('Error enumerating devices:', err);
      }
    };

    getCameras()
  }, []);


  // const startCamera = (deviceId: any) => {
  //   if (navigator.mediaDevices.getUserMedia) {
  //     navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: deviceId } } })
  //       .then(stream => {
  //         console.log(stream);
  //         webcamRef.current.srcObject = stream;
  //       })
  //       .catch(err => {
  //         console.error('Error accessing the camera:', err);
  //       });
  //   }
  // };

  const handleCameraChange = (event: any) => {

    const newDeviceId = event;
    setSelectedCamera(newDeviceId);
    console.log(newDeviceId);

    // startCamera(newDeviceId);
  };


  const createTask = () => {
    navigate('/tasks/0/edit?isNew=true');
  };

  useEffect(() => {
    start()
    initWebSocket(); // 初始化WS链接

    // // 更新时间
    // currentTimeChange = setInterval(() => {
    //   setPercent((prev: any) => {
    //     if (prev < 100) {
    //       return prev + 20
    //     } else {
    //       setSpinning(false)
    //       clearInterval(currentTimeChange) // 清除定时器
    //       return 100
    //     }
    //   })
    // }, 1000)


    return () => {
      stop();
      clearInterval(timer);
      // clearInterval(currentTimeChange) // 清除定时器
    };
  }, []);


  // 开始推流
  const publish = async () => {
    if (pc !== null && pc !== undefined) {
      console.log("已开始推流");
      return;
    }

    var constraints = {
      audio: {
        echoCancellation: true,    // 回声消除
        noiseSuppression: true,    // 降噪
        autoGainControl: true     // 自动增益 
      },
      video: {
        frameRate: { min: 30 },                // 最小帧率
        width: { min: 640, ideal: 1080 }, // 宽度   
        height: { min: 360, ideal: 720 },  // 高度  
        aspectRadio: 16 / 9                        // 宽高比
      }
    }

    // 通过摄像头、麦克风获取音视频流
    videoStream = await navigator.mediaDevices.getUserMedia(constraints);

    //video播放流数据
    myVideo.current!.srcObject = videoStream;
    myVideo.current!.play();

    // 静音
    myVideo.current!.volume = 0;

    // 创建RTC连接对象
    pc = new RTCPeerConnection();


    // RTCPeerConnection方法addTransceiver()创建一个新的RTCRtpTransceiver，并将其添加到与RTCPeerConnection关联的收发器集中。
    // 每个收发器代表一个双向流，RTCRtpSender和RTCRtpReceiver都与之相关联。
    // 注意添加顺序为audio、video,后续RTCPeerConnection创建offer时SDP的m线顺序遵循此顺序创建，SRS自带的信令服务器响应的SDP中m线总是先audio后video。
    // 若本端SDP和远端SDP中的m线顺序不一直，则设置远端描述时会异常，显示offer中的m线与answer中的m线顺序不匹配
    pc.addTransceiver("video", { direction: "recvonly" });
    // 遍历getUserMedia（）获取到的流数据，拿到其中的音频轨道和视频轨道，加入到RTCPeerConnection连接的音频轨道和视频轨道中
    videoStream.getTracks().forEach((track) => {
      console.log(track);

      pc.addTrack(track);
    });
    // 创建本端offer
    var offer = await pc.createOffer();
    // 设置本端
    await pc.setLocalDescription(offer);
    var data = {
      "api": httpURL,
      "streamurl": webRTCURL,
      "sdp": offer.sdp,
    } as any
    // SDP交换，请求SRS自带的信令服务器
    fetch(httpURL, {
      body: JSON.stringify(data),
      headers: {
        "Content-Type": "application/json",
      },
      method: "POST",
    }).then(function (response: any) {
      console.log(response);
      return response.json();
    }).then(async (data: any) => {
      console.log("answer", data);
      // 设置远端描述，开始连接
      await pc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }));
      // setTimeout(() => {
      //   play(gestureURL)
      // }, 4000);
      play(gestureURL)
    }).catch((data) => {
      if (data.code === 400) {
        console.log("SDP交换失败");
      }
    });

  }

  // 开始拉流
  const play = async (httpURL: any) => {
    // 创建RTCPeerConnection连接对象
    // 创建媒体流对象
    var stream = new MediaStream();

    pc.ontrack = (event: any) => {
      // 监听到的流加入MediaStream对象中让video播放
      stream.addTrack(event.track);
      myVideo.current!.srcObject = stream;
      myVideo.current!.play();
    }

    // RTCPeerConnection方法addTransceiver()创建一个新的RTCRtpTransceiver，并将其添加到与RTCPeerConnection关联的收发器集中。
    // 每个收发器代表一个双向流，RTCRtpSender和RTCRtpReceiver都与之相关联。
    // 注意添加顺序为audio、video,后续RTCPeerConnection创建offer时SDP的m线顺序遵循此顺序创建，SRS自带的信令服务器响应的SDP中m线总是先audio后video。
    // 若本端SDP和远端SDP中的m线顺序不一直，则设置远端描述时会异常，显示offer中的m线与answer中的m线顺序不匹配
    pc.addTransceiver("video", { direction: "recvonly" });

    var offer = await pc.createOffer();
    await pc.setLocalDescription(offer)
    var data = {
      "api": httpURL,
      "streamurl": webRTCURL,
      "sdp": offer.sdp,
      type: offer.type,
      video_transform: "rotate",
      username: username
    } as any


    fetch(httpURL, {
      body: JSON.stringify(data),
      headers: {
        "Content-Type": "application/json",
      },
      method: "POST",
    }).then(function (response: any) {
      console.log(response);
      return response.json();
    }).then(async (data: any) => {
      console.log("answer", data);
      // 设置远端描述，开始连接
      await pc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }));
    })
  }

  const negotiate = () => {
    return pc.createOffer().then((offer: any) => {
      return pc.setLocalDescription(offer);
    }).then(() => {
      // wait for ICE gathering to complete
      return new Promise((resolve: any) => {
        if (pc.iceGatheringState === 'complete') {
          resolve();
        } else {
          function checkState() {
            if (pc.iceGatheringState === 'complete') {
              pc.removeEventListener('icegatheringstatechange', checkState);
              resolve();
            }
          }
          pc.addEventListener('icegatheringstatechange', checkState);
        }
      });
    }).then(() => {
      var offer = pc.localDescription;
      return fetch(gestureURL, {
        body: JSON.stringify({
          api: httpURL,
          streamurl: webRTCURL,
          sdp: offer.sdp,
          type: offer.type,
          video_transform: "none",
          username: username
        }),
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'POST'
      });
    }).then((response: any) => {
      return response.json();
    }).then((answer: any) => {
      return pc.setRemoteDescription(answer);
    }).catch((e: any) => {
      console.log(e);
    });
  }


  const createPeerConnection = () => {
    var config = {
      sdpSemantics: 'unified-plan'
    } as any;

    pc = new RTCPeerConnection(config);

    // connect audio / video
    pc.addEventListener('track', (evt: any) => {
      if (evt.track.kind == 'video')
        myVideo.current!.srcObject = evt.streams[0];
      myVideo.current!.play();

    });

    return pc;
  }

  const start = () => {
    var config = {
      sdpSemantics: "unified-plan",
    } as any;
    config.iceServers = [
      {
        urls: "stun:stun1.l.google.com:19302",
      },
      {
        urls: "stun:stun3.l.google.com:19302",
      },
      {
        urls: "stun:stun4.l.google.com:19302",
      },
    ];

    pc = createPeerConnection();



    var constraints = {
      audio: {
        echoCancellation: true,    // 回声消除
        noiseSuppression: true,    // 降噪
        autoGainControl: true     // 自动增益 
      },
      video: {
        frameRate: { min: 30 },                // 最小帧率
        width: { min: 640, ideal: 1080 }, // 宽度   
        height: { min: 360, ideal: 720 },  // 高度  
        aspectRadio: 16 / 9                        // 宽高比
      }
    }

    navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
      stream.getTracks().forEach((track) => {
        pc.addTrack(track, stream);
      });
      return negotiate();
    }, (err) => {
      console.log('Could not acquire media: ' + err);
    });

  }

  const stop = () => {

    // close transceivers
    if (pc.getTransceivers) {
      pc.getTransceivers().forEach((transceiver: any) => {
        if (transceiver.stop) {
          transceiver.stop();
        }
      });
    }

    // close local audio / video
    pc.getSenders().forEach((sender: any) => {
      sender.track.stop();
    });

    // close peer connection
    setTimeout(() => {
      pc.close();
    }, 500);
  }
  // 初始化WS链接
  const initWebSocket = () => {
    connection();
    // 断开重连机制,尝试发送消息,捕获异常发生时重连
    timer = setInterval(() => {
      try {
        // that.stompClient.send("test");
      } catch (err) {
        console.log("断线了: " + err);
        connection();
      }
    }, 5000);
  }
  //连接 后台
  const connection = () => {
    // 手势
    let gesture = new WebSocket(wsURL + "gesture/ws?username=" + username);

    // 手势
    gesture.onmessage = (event) => {
      let data = JSON.parse(event.data);
      setWsObj(data)
    };

  }

  return (
    <>
      <div className="validation">
        <Row gutter={32} justify="space-evenly">
          <Col span={12}>
            <Spin tip="验证模块加载中..." spinning={spinning} size='large'>
              <div className='video'>
                <Progress
                  style={{ display: spinning ? 'block' : 'none' }}
                  strokeColor={{
                    '0%': '#108ee9',
                    '100%': '#87d068',
                  }}
                  percent={percent}
                />
                <div>
                  <Select
                    style={{ width: 120 }}
                    onChange={handleCameraChange}
                    value={selectedCamera}
                    placeholder='请选择摄像头'
                  >
                    {cameras.map((camera: any) => (
                      <Option key={camera.deviceId} value={camera.deviceId}>
                        {camera.label || `Camera ${camera.deviceId}`}
                      </Option >
                    ))}
                  </Select>
                </div>
                <video style={{ width: '100%' }} ref={myVideo}></video>
              </div>
            </Spin>
          </Col>
          <Col span={6}>
            <Space direction="vertical">
              <Input addonBefore="识别结果" value={`${wsObj?.handedness}:${wsObj?.sign_text}`} />
            </Space>
            
          </Col>

        </Row>
      </div>
    </>
  );
};
export default ValidationPage;
