/**
 * 双向视频通话应用主文件
 * 负责初始化视频设备、建立WebRTC连接、处理信令和显示视频流
 */

// 导入必要的模块
import { SendVideo } from "./sendvideo.js"; // 视频发送和接收处理
import { getServerConfig, getRTCConfiguration } from "../../js/config.js"; // 服务器配置和RTC配置
import { createDisplayStringArray } from "../../js/stats.js"; // 统计信息处理
import { RenderStreaming } from "../../module/renderstreaming.js"; // WebRTC连接管理
import { Signaling, WebSocketSignaling } from "../../module/signaling.js"; // 信令管理

// 默认视频流尺寸
const defaultStreamWidth = 1280;
const defaultStreamHeight = 720;

// 预定义的视频分辨率列表
const streamSizeList =
  [
    { width: 640, height: 360 },    // 标清
    { width: 1280, height: 720 },   // 高清
    { width: 1920, height: 1080 },  // 全高清
    { width: 2560, height: 1440 },  // 2K
    { width: 3840, height: 2160 },  // 4K
    { width: 360, height: 640 },    // 竖屏标清
    { width: 720, height: 1280 },   // 竖屏高清
    { width: 1080, height: 1920 },  // 竖屏全高清
    { width: 1440, height: 2560 },  // 竖屏2K
    { width: 2160, height: 3840 },  // 竖屏4K
  ];

// DOM元素引用
const localVideo = document.getElementById('localVideo'); // 本地视频元素
const remoteVideo = document.getElementById('remoteVideo'); // 远程视频元素
const localVideoStatsDiv = document.getElementById('localVideoStats'); // 本地视频统计信息
const remoteVideoStatsDiv = document.getElementById('remoteVideoStats'); // 远程视频统计信息
const textForConnectionId = document.getElementById('textForConnectionId'); // 连接ID输入框
textForConnectionId.value = getRandom(); // 生成随机连接ID
const videoSelect = document.querySelector('select#videoSource'); // 视频设备选择
const audioSelect = document.querySelector('select#audioSource'); // 音频设备选择
const videoResolutionSelect = document.querySelector('select#videoResolution'); // 视频分辨率选择
const cameraWidthInput = document.querySelector('input#cameraWidth'); // 自定义宽度输入
const cameraHeightInput = document.querySelector('input#cameraHeight'); // 自定义高度输入

// 编解码器偏好设置
const codecPreferences = document.getElementById('codecPreferences');
// 检查浏览器是否支持设置编解码器偏好
const supportsSetCodecPreferences = window.RTCRtpTransceiver &&
  'setCodecPreferences' in window.RTCRtpTransceiver.prototype;
const messageDiv = document.getElementById('message'); // 消息显示区域
messageDiv.style.display = 'none'; // 初始隐藏消息区域

let useCustomResolution = false; // 是否使用自定义分辨率

// 初始化输入选择和编解码器选择
setUpInputSelect();
showCodecSelect();

/** @type {SendVideo} */
let sendVideo = new SendVideo(localVideo, remoteVideo); // 视频处理实例
/** @type {RenderStreaming} */
let renderstreaming; // WebRTC连接管理实例
let useWebSocket; // 是否使用WebSocket信令
let connectionId; // 连接ID

// 按钮事件绑定
const startButton = document.getElementById('startVideoButton');
startButton.addEventListener('click', startVideo); // 启动视频按钮
const setupButton = document.getElementById('setUpButton');
setupButton.addEventListener('click', setUp); // 设置连接按钮
const hangUpButton = document.getElementById('hangUpButton');
hangUpButton.addEventListener('click', hangUp); // 挂断按钮

// 页面卸载前清理
window.addEventListener('beforeunload', async () => {
  if(!renderstreaming)
    return;
  await renderstreaming.stop(); // 停止WebRTC连接
}, true);

// 初始化配置
setupConfig();

/**
 * 初始化服务器配置
 * @async
 * @returns {Promise<void>}
 */
async function setupConfig() {
  const res = await getServerConfig(); // 获取服务器配置
  useWebSocket = res.useWebSocket; // 设置是否使用WebSocket
  showWarningIfNeeded(res.startupMode); // 显示启动模式警告
}

/**
 * 根据启动模式显示警告信息
 * @param {string} startupMode - 启动模式，可能的值包括"public"和"private"
 */
function showWarningIfNeeded(startupMode) {
  const warningDiv = document.getElementById("warning");
  if (startupMode == "public") {
    warningDiv.innerHTML = "<h4>Warning</h4> This sample is not working on Public Mode.";
    warningDiv.hidden = false;
  }
}

/**
 * 启动本地视频
 * @async
 * @returns {Promise<void>}
 */
async function startVideo() {
  // 禁用相关输入控件
  videoSelect.disabled = true;
  audioSelect.disabled = true;
  videoResolutionSelect.disabled = true;
  cameraWidthInput.disabled = true;
  cameraHeightInput.disabled = true;
  startButton.disabled = true;

  let width = 0;
  let height = 0;

  // 根据选择的分辨率设置视频尺寸
  if (useCustomResolution) {
    width = cameraWidthInput.value ? cameraWidthInput.value : defaultStreamWidth;
    height = cameraHeightInput.value ? cameraHeightInput.value : defaultStreamHeight;
  } else {
    const size = streamSizeList[videoResolutionSelect.value];
    width = size.width;
    height = size.height;
  }

  // 启动本地视频
  await sendVideo.startLocalVideo(videoSelect.value, audioSelect.value, width, height);

  // 启用设置按钮
  setupButton.disabled = false;
}

/**
 * 设置WebRTC连接
 * @async
 * @returns {Promise<void>}
 */
async function setUp() {
  setupButton.disabled = true; // 禁用设置按钮
  hangUpButton.disabled = false; // 启用挂断按钮
  connectionId = textForConnectionId.value; // 获取连接ID
  codecPreferences.disabled = true; // 禁用编解码器选择

  // 创建信令实例
  const signaling = useWebSocket ? new WebSocketSignaling() : new Signaling();
  const config = getRTCConfiguration(); // 获取RTC配置
  renderstreaming = new RenderStreaming(signaling, config); // 创建WebRTC连接管理实例

  // 连接建立回调
  renderstreaming.onConnect = () => {
    const tracks = sendVideo.getLocalTracks(); // 获取本地媒体轨道
    for (const track of tracks) {
      renderstreaming.addTransceiver(track, { direction: 'sendonly' }); // 添加发送轨道
    }
    setCodecPreferences(); // 设置编解码器偏好
    showStatsMessage(); // 显示统计信息
  };

  // 连接断开回调
  renderstreaming.onDisconnect = () => {
    hangUp(); // 挂断连接
  };

  // 轨道事件回调
  renderstreaming.onTrackEvent = (data) => {
    const direction = data.transceiver.direction;
    if (direction == "sendrecv" || direction == "recvonly") {
      sendVideo.addRemoteTrack(data.track); // 添加远程轨道
    }
  };

  // 启动WebRTC连接
  await renderstreaming.start();
  await renderstreaming.createConnection(connectionId);

}

/**
 * 设置编解码器偏好
 */
function setCodecPreferences() {
  /** @type {RTCRtpCodecCapability[] | null} */
  let selectedCodecs = null;

  if (supportsSetCodecPreferences) {
    const preferredCodec = codecPreferences.options[codecPreferences.selectedIndex];
    if (preferredCodec.value !== '') {
      const [mimeType, sdpFmtpLine] = preferredCodec.value.split(' ');
      const { codecs } = RTCRtpSender.getCapabilities('video');
      const selectedCodecIndex = codecs.findIndex(c => c.mimeType === mimeType && c.sdpFmtpLine === sdpFmtpLine);
      const selectCodec = codecs[selectedCodecIndex];
      selectedCodecs = [selectCodec];
    }
  }

  if (selectedCodecs == null) {
    return;
  }

  // 获取视频收发器并设置编解码器偏好
  const transceivers = renderstreaming.getTransceivers().filter(t => t.receiver.track.kind == "video");
  if (transceivers && transceivers.length > 0) {
    transceivers.forEach(t => t.setCodecPreferences(selectedCodecs));
  }
}

/**
 * 挂断WebRTC连接
 * @async
 * @returns {Promise<void>}
 */
async function hangUp() {
  clearStatsMessage(); // 清除统计信息
  messageDiv.style.display = 'block';
  messageDiv.innerText = `Disconnect peer on ${connectionId}.`;

  hangUpButton.disabled = true; // 禁用挂断按钮
  setupButton.disabled = false; // 启用设置按钮

  // 删除连接并停止WebRTC
  await renderstreaming.deleteConnection();
  await renderstreaming.stop();
  renderstreaming = null;
  remoteVideo.srcObject = null; // 清除远程视频源

  textForConnectionId.value = getRandom(); // 生成新的随机连接ID
  connectionId = null;

  // 启用编解码器选择
  if (supportsSetCodecPreferences) {
    codecPreferences.disabled = false;
  }
}

/**
 * 生成随机连接ID
 * @returns {string} 5位随机数字字符串
 */
function getRandom() {
  const max = 99999;
  const length = String(max).length;
  const number = Math.floor(Math.random() * max);
  return (Array(length).join('0') + number).slice(-length); // 补零确保5位
}

/**
 * 设置输入选择控件
 * @async
 * @returns {Promise<void>}
 */
async function setUpInputSelect() {
  // 获取媒体设备列表
  const deviceInfos = await navigator.mediaDevices.enumerateDevices();

  // 填充视频设备选择
  for (let i = 0; i !== deviceInfos.length; ++i) {
    const deviceInfo = deviceInfos[i];
    if (deviceInfo.kind === 'videoinput') {
      const option = document.createElement('option');
      option.value = deviceInfo.deviceId;
      option.text = deviceInfo.label || `camera ${videoSelect.length + 1}`;
      videoSelect.appendChild(option);
    } else if (deviceInfo.kind === 'audioinput') {
      // 填充音频设备选择
      const option = document.createElement('option');
      option.value = deviceInfo.deviceId;
      option.text = deviceInfo.label || `mic ${audioSelect.length + 1}`;
      audioSelect.appendChild(option);
    }
  }

  // 填充视频分辨率选择
  for (let i = 0; i < streamSizeList.length; i++) {
    const streamSize = streamSizeList[i];
    const option = document.createElement('option');
    option.value = i;
    option.text = `${streamSize.width} x ${streamSize.height}`;
    videoResolutionSelect.appendChild(option);
  }

  // 添加自定义分辨率选项
  const option = document.createElement('option');
  option.value = streamSizeList.length;
  option.text = 'Custom';
  videoResolutionSelect.appendChild(option);
  videoResolutionSelect.value = 1; // 默认选择1280 x 720

  // 分辨率选择变化事件
  videoResolutionSelect.addEventListener('change', (event) => {
    const isCustom = event.target.value >= streamSizeList.length;
    cameraWidthInput.disabled = !isCustom;
    cameraHeightInput.disabled = !isCustom;
    useCustomResolution = isCustom;
  });
}

/**
 * 显示编解码器选择
 */
function showCodecSelect() {
  if (!supportsSetCodecPreferences) {
    messageDiv.style.display = 'block';
    messageDiv.innerHTML = `Current Browser does not support <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpTransceiver/setCodecPreferences">RTCRtpTransceiver.setCodecPreferences</a>.`;
    return;
  }

  // 获取视频编解码器能力
  const codecs = RTCRtpSender.getCapabilities('video').codecs;
  codecs.forEach(codec => {
    // 跳过冗余和FEC编解码器
    if (['video/red', 'video/ulpfec', 'video/rtx'].includes(codec.mimeType)) {
      return;
    }
    const option = document.createElement('option');
    option.value = (codec.mimeType + ' ' + (codec.sdpFmtpLine || '')).trim();
    option.innerText = option.value;
    codecPreferences.appendChild(option);
  });
  codecPreferences.disabled = false;
}

// 统计信息相关变量
let lastStats; // 上次统计信息
let intervalId; // 统计信息更新间隔ID

/**
 * 显示统计信息
 */
function showStatsMessage() {
  // 每秒更新一次统计信息
  intervalId = setInterval(async () => {
    // 显示本地视频分辨率
    if (localVideo.videoWidth) {
      localVideoStatsDiv.innerHTML = `<strong>Sending resolution:</strong> ${localVideo.videoWidth} x ${localVideo.videoHeight} px`;
    }
    // 显示远程视频分辨率
    if (remoteVideo.videoWidth) {
      remoteVideoStatsDiv.innerHTML = `<strong>Receiving resolution:</strong> ${remoteVideo.videoWidth} x ${remoteVideo.videoHeight} px`;
    }

    if (renderstreaming == null || connectionId == null) {
      return;
    }

    // 获取WebRTC统计信息
    const stats = await renderstreaming.getStats();
    if (stats == null) {
      return;
    }

    // 创建统计信息显示数组
    const array = createDisplayStringArray(stats, lastStats);
    if (array.length) {
      messageDiv.style.display = 'block';
      messageDiv.innerHTML = array.join('<br>');
    }
    lastStats = stats;
  }, 1000);
}

/**
 * 清除统计信息
 */
function clearStatsMessage() {
  if (intervalId) {
    clearInterval(intervalId); // 清除定时器
  }
  lastStats = null;
  intervalId = null;
  localVideoStatsDiv.innerHTML = '';
  remoteVideoStatsDiv.innerHTML = '';
  messageDiv.style.display = 'none';
  messageDiv.innerHTML = '';
}
