import {faSquare, faThLarge, faUserFriends} from '@fortawesome/free-solid-svg-icons';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {Room, RoomEvent, setLogLevel, VideoPresets} from 'livekit-client';
import {DisplayContext, DisplayOptions, LiveKitRoom} from '@livekit/react-components';
import {useState} from 'react';
import 'react-aspect-ratio/aspect-ratio.css';
import {useNavigate, useLocation} from 'react-router-dom';

// 新增代码
let currentRoom: Room;

export const RoomPage = () => {
  const [numParticipants, setNumParticipants] = useState(0);
  const [displayOptions, setDisplayOptions] = useState<DisplayOptions>({
    stageLayout: 'grid',
    showStats: false,
  });
  const navigate = useNavigate();
  const query = new URLSearchParams(useLocation().search);
  const url = query.get('url');
  const token = query.get('token');
  const recorder = query.get('recorder');

  if (!url || !token) {
    return <div>url and token are required</div>;
  }

  const onLeave = () => {
    navigate('/');
  };

  const updateParticipantSize = (room: Room) => {
    setNumParticipants(room.participants.size + 1);
  };

  const onParticipantDisconnected = (room: Room) => {
    updateParticipantSize(room);

    /* Special rule for recorder */
    if (recorder && parseInt(recorder, 10) === 1 && room.participants.size === 0) {
      console.log('END_RECORDING');
    }
  };

  const updateOptions = (options: DisplayOptions) => {
    setDisplayOptions({
      ...displayOptions,
      ...options,
    });
  };

  // 新增代码开始
  const encoder = new TextEncoder();
  const decoder = new TextDecoder();
  const enterText = () => {
    const textField = document.getElementById('entry') as HTMLInputElement;
    const chat = document.getElementById('chat') as HTMLDivElement;
    if (textField.value.trim()) {
      textField.focus();
      const msg = encoder.encode(textField.value);
      currentRoom.localParticipant.publishData(msg, 0);
      chat.innerHTML += `<div style="color:yellow">${currentRoom.localParticipant.identity} (me): ${textField.value}</div>`;
      chat.scrollTop = chat.scrollHeight;
      textField.value = '';
    }
  };
  const handleData = (msg: Uint8Array, participant?: any) => {
    const chat = document.getElementById('chat') as HTMLDivElement;
    const str = decoder.decode(msg);
    let from = 'server';
    if (participant) {
      from = participant.identity;
    }
    chat.innerHTML += `<div>${from}: ${str}</div>`;
    chat.scrollTop = chat.scrollHeight;
  };
  const closeChat = () => {
    const chatArea: any = document.getElementById('chat-area');
    chatArea.style.display = 'none';
  }
  const handleKeydown = (e: any) => {
    if (e.target.value.trim() && e.key === 'Enter') {
      enterText()
    }
  }
  // 新增代码结束

  return (
    <DisplayContext.Provider value={displayOptions}>
      <div className="video-chat">
        <div className="roomContainer">
          <div className="topBar">
            <h2>Zoom Video</h2>
            <div className="right">
              <div>
                <input
                  id="showStats"
                  type="checkbox"
                  onChange={(e) => updateOptions({showStats: e.target.checked})}
                />
                <label htmlFor="showStats">Show Stats</label>
              </div>
              <div>
                <button
                  className="iconButton"
                  disabled={displayOptions.stageLayout === 'grid'}
                  onClick={() => {
                    updateOptions({stageLayout: 'grid'});
                  }}
                >
                  <FontAwesomeIcon height={32} icon={faThLarge}/>
                </button>
                <button
                  className="iconButton"
                  disabled={displayOptions.stageLayout === 'speaker'}
                  onClick={() => {
                    updateOptions({stageLayout: 'speaker'});
                  }}
                >
                  <FontAwesomeIcon height={32} icon={faSquare}/>
                </button>
              </div>
              <div className="participantCount">
                <FontAwesomeIcon icon={faUserFriends}/>
                <span>{numParticipants}</span>
              </div>
            </div>
          </div>
          <LiveKitRoom
            url={url}
            token={token}
            onConnected={(room) => {
              setLogLevel('debug');
              onConnected(room, query);
              room.on(RoomEvent.ParticipantConnected, () => updateParticipantSize(room));
              room.on(RoomEvent.ParticipantDisconnected, () => onParticipantDisconnected(room));
              room.on(RoomEvent.DataReceived, handleData);
              updateParticipantSize(room);
            }}
            roomOptions={{
              adaptiveStream: isSet(query, 'adaptiveStream'),
              dynacast: isSet(query, 'dynacast'),
              publishDefaults: {
                simulcast: isSet(query, 'simulcast'),
              },
              videoCaptureDefaults: {
                resolution: VideoPresets.h720.resolution,
              },
            }}
            onLeave={onLeave}
          />
        </div>
        {
          currentRoom &&
          <div className="chat-area" id="chat-area">
            <div className="title">
              <h2>Chat</h2>
              <div className="close" onClick={closeChat}>x</div>
            </div>
            <div className="chat" id="chat"></div>
            <div className="send">
              <input type="text" className="input" id="entry" placeholder="Enter your message"
                     onKeyDown={event => handleKeydown(event)}/>
              <button className="chat-btn" onClick={enterText}>
                Send
              </button>
            </div>
          </div>
        }
      </div>
    </DisplayContext.Provider>
  );
};

async function onConnected(room: Room, query: URLSearchParams) {
  // make it easier to debug
  // (window as any).currentRoom = room;
  // 新增代码
  currentRoom = room;

  if (isSet(query, 'audioEnabled')) {
    const audioDeviceId = query.get('audioDeviceId');
    if (audioDeviceId && room.options.audioCaptureDefaults) {
      room.options.audioCaptureDefaults.deviceId = audioDeviceId;
    }
    await room.localParticipant.setMicrophoneEnabled(true);
  }

  if (isSet(query, 'videoEnabled')) {
    const videoDeviceId = query.get('videoDeviceId');
    if (videoDeviceId && room.options.videoCaptureDefaults) {
      room.options.videoCaptureDefaults.deviceId = videoDeviceId;
    }
    await room.localParticipant.setCameraEnabled(true);
  }
}

function isSet(query: URLSearchParams, key: string): boolean {
  return query.get(key) === '1' || query.get(key) === 'true';
}
