const players = [];
const mainLoading = new Loading('#main');
mainLoading.show();

async function startLive(rst, onBeforeReconnect) {
  await LivePlayer.init();

  // 是否启用合图
  let useMerge = rst.MergedChannel;

  // 是否关闭摄像头
  let enableCamera = rst.EnableCamera === undefined ? true : rst.EnableCamera;

  // 是否只存在摄像头，遍历 rst.VideoDeviceInfos，如果只有摄像头（VideoDeviceSourceType === 1），那么只存在摄像头
  let isOnlyCamera = rst.VideoDeviceInfos.every(
    (x) => x.VideoDeviceSourceType === 1,
  );
  // 老版本魔盒如果只推摄像头，直接作为主画面来处理，因为会推全屏摄像头画面，无需裁图
  if (rst.IsOldPlatform && isOnlyCamera) {
    isOnlyCamera = false;
    useMerge = false;
    rst.VideoDeviceInfos[0].VideoDeviceSourceType = 0;
  }

  const subSources = rst.VideoDeviceInfos.filter(
    (x) => x.VideoDeviceSourceType === 1,
  );
  if (subSources.length > 0 && enableCamera) {
    $('.sub_channel-list').show();
    for (let i = 0; i < subSources.length; i++) {
      if (isOnlyCamera) {
        buildFullScreenCamera(i, subSources[i].LiveData, useMerge);
      } else {
        buildCamera(i, subSources[i].LiveData, useMerge);
      }
    }
    $('.sub_channel-list .swap-icon').on('click', function (e) {
      // 切换摄像头左右位置
      var parent = $(this).parent();
      if (parent.hasClass('align-left')) {
        // 左→右
        parent.removeClass('align-left');
        parent.addClass('align-right');
        Array.from(parent.find('.sub_channel-box')).forEach((x) => {
          x.resizableBox.updateConfig({
            right: false,
            left: true,
          });
        });
      } else {
        // 右←左
        parent.removeClass('align-right');
        parent.addClass('align-left');
        Array.from(parent.find('.sub_channel-box')).forEach((x) => {
          x.resizableBox.updateConfig({
            right: true,
            left: false,
          });
        });
      }
    });
    $('.sub_channel-list .hide-icon').on('click', function () {
      // 切换摄像头隐藏
      var parent = $(this).parent();
      var swap = parent.find('.swap-icon');
      var visible = swap.css('visibility') === 'visible';
      if (visible) {
        // 收起
        swap.css('visibility', 'hidden');
        parent.find('.sub_channel-box').css('visibility', 'hidden');
        parent.css('border-color', 'transparent');
        if (i18n != undefined) {
          this.title = i18n.translate('Expand');
        }
      } else {
        // 展开
        swap.css('visibility', 'visible');
        parent.find('.sub_channel-box').css('visibility', 'visible');
        parent.css('border-color', '#ccc');
        if (i18n != undefined) {
          this.title = i18n.translate('Collapse');
        }
      }
    });
    if (isOnlyCamera) {
      // 只存在摄像头，隐藏切换按钮，移除 align-right 样式，切换为 fit-center 样式
      $('.sub_channel-list .swap-icon').css('visibility', 'hidden');
      $('.sub_channel-list .hide-icon').css('visibility', 'hidden');
      $('.sub_channel-list').removeClass('align-right');
      $('.sub_channel-list').addClass('fit-center');
      // 移除边框
      $('.sub_channel-list').css('border', 'none');
      $('.sub_channel-list .sub_channel-box').css('border', 'none');
    }
  }

  buildMain(rst, useMerge, subSources.length, onBeforeReconnect);

  const keepPlayerRetry = true;
  players.forEach((x, i) => {
    x.play(keepPlayerRetry);
  });
  window._debug_ = {
    players: players,
  };
}

/**
 * 构建主路画面
 * @param {*} data 直播数据
 * @param {bool} useMerge 是否合图
 * @param {number} cameraCount 摄像头数量
 * @returns
 */
function buildMain(data, useMerge, cameraCount, onBeforeReconnect) {
  let sourceIndex = data.VideoDeviceInfos.findIndex(
    (x) => x.VideoDeviceSourceType === 0,
  );
  let cameraIndex = data.VideoDeviceInfos.findIndex(
    (x) => x.VideoDeviceSourceType === 1,
  );
  if (sourceIndex < 0) {
    // 如果只存在摄像头且为合流模式，那么主路画面使用摄像头画面
    let isOnlyCamera = data.VideoDeviceInfos.every(
      (x) => x.VideoDeviceSourceType === 1,
    );
    if (isOnlyCamera && useMerge) {
      sourceIndex = data.VideoDeviceInfos.findIndex(
        (x) => x.VideoDeviceSourceType === 1,
      );
    } else {
      return;
    }
  }
  const liveData = data.VideoDeviceInfos[sourceIndex].LiveData;
  let cameraData = null;
  if (cameraIndex >= 0) {
    cameraData = data.VideoDeviceInfos[cameraIndex].LiveData;
  }

  // 是否是 RTMP 模式
  let isRtmp = data.LiveProtocol && data.LiveProtocol === 9;
  // mock data
  //   liveData.HttpPullUrl = 'http://192.168.6.6:9111/live/gavin123.flv';

  var player = new LivePlayer('mian_canvas', liveData.HttpPullUrl);
  const mergeWidth = data.MergedVideoOutputWidth;
  const mergeHeight = data.MergedVideoOutputHeight;
  player.onBuffer = function (state) {
    if (state === 'full') {
      mainLoading.hide();
    } else {
      mainLoading.show();
    }
  };
  player.onPlay = function () {
    mainLoading.hide();
  };
  player.onBeforeReconnect = onBeforeReconnect;
  player.onInfo = function (info) {
    if (data.IsOldPlatform) {
      fitOpts.sourceWidth = info.width;
      fitOpts.sourceHeight = info.height;
      if (!data.SupportRtc || cameraCount === 0) {
        fitOpts.width = info.width;
        fitOpts.height = info.height;
      }
      onResize();
    }
  };
  player.onTimeout = function () {
    console.log('%c Line:170 🎂', 'color:#7f2b82');
  };
  if (useMerge && cameraCount > 0) {
    const sourceCanvas = document.getElementById('mian_canvas');
    const cameraCanvas = Array.from($('.sub_channel-list canvas'));
    /// 创建视频裁切处理器（设置裁切方式）
    let processConfigs = [];
    if (data.IsOldPlatform) {
      if (mergeHeight === 720) {
        processConfigs.push({
          type: 'oldTwoPart',
          x: 0.0,
          y: 3 / 4,
          w: 1,
          h: 1 / 4,
        });
      } else {
        processConfigs.push({
          type: 'scaleOnly',
          x: 0.6,
          y: 0.0,
          w: 0.4,
          h: 8 / 9,
        });
      }
    } else {
      if (mergeHeight === 1080) {
        processConfigs.push({
          type: 'scaleOnly',
          x: 2 / 3,
          y: 0.0,
          w: 1 / 3,
          h: 4 / 9,
        });
        if (cameraCount > 1) {
          processConfigs.push({
            type: 'threePart',
            x: 0.0,
            y: 2 / 3,
            w: 1,
            h: 4 / 27,
          });
        }
      } else if (mergeHeight === 720) {
        processConfigs.push({
          type: 'camera720',
          x: 0.0,
          y: 3 / 4,
          w: 1,
          h: 1 / 4,
        });
      }
    }

    if (processConfigs.length > 0) {
      let videoProcessor = new VideoProcessor(processConfigs);
      player.onInfo = function (info) {
        if (data.IsOldPlatform) {
          fitOpts.sourceWidth = info.width;
          fitOpts.sourceHeight = info.height;
          processConfigs = [];
          processConfigs.push(
            getVideoProcessorConfig(
              info.width,
              info.height,
              liveData.Width,
              liveData.Height,
              cameraData.Width,
              cameraData.Height,
              data.IsOldPlatform,
              isRtmp,
            ),
          );
          videoProcessor = new VideoProcessor(processConfigs);
          onResize();
        }
        videoProcessor.initialize(sourceCanvas, cameraCanvas);
      };
      player.onFrame = function () {
        videoProcessor.drawFrame();
      };
    }
  }
  players.push(player);
  let inMergeFrame = useMerge;
  if (!inMergeFrame) {
    if (data.VideoDeviceInfos.length === 1) {
      const viewWHR = liveData.Width / liveData.Height;
      const mergeWHR = mergeWidth / mergeHeight;
      if (!Number.isNaN(mergeWHR) && viewWHR !== mergeWHR) {
        // 仅1路图像，且和总输出尺寸不符，需要裁图
        inMergeFrame = true;
      }
    }
  }
  const fitOpts = {
    width: liveData.Width,
    height: liveData.Height,
    sourceWidth: liveData.Width,
    sourceHeight: liveData.Height,
  };
  if (inMergeFrame) {
    fitOpts.sourceWidth = mergeWidth;
    fitOpts.sourceHeight = mergeHeight;
  }
  const fitbox = new SingleChannelFitBox(
    document.getElementById('main'),
    fitOpts,
  );
  function onResize() {
    const result = fitbox.process(
      window.innerWidth,
      window.innerHeight,
      inMergeFrame,
    );
    player.setViewSize(result.sourceWidth, result.sourceHeight);
    /// set main view canvas css size
    let mainViewCanvas = document.getElementById('mian_canvas');
    if (mainViewCanvas) {
      mainViewCanvas.style.width = result.canvasWidth + 'px';
      mainViewCanvas.style.height = result.canvasHeight + 'px';
    }
  }
  onResize();
  addResizeCallback(onResize);

  /// 通过一系列参数获取视频裁切处理器
  function getVideoProcessorConfig(
    videoWidth,
    videoHeight,
    mainViewWidth,
    mainViewHeight,
    subViewWidth,
    subViewHeight,
    IsOldPlatform,
    isRtmp,
  ) {
    // 该兼容方案参看 http://192.168.6.117:8000/%E9%A1%B9%E7%9B%AE/%E6%96%B0%E7%89%88%E6%9D%8F%E8%81%86%E8%8D%9F/%E8%B6%85%E5%A3%B0%E7%9B%B4%E6%92%AD%E5%85%BC%E5%AE%B9%E8%80%81%E7%89%88%E8%B6%85%E5%A3%B0%E6%9C%BA/
    if (isRtmp) {
      return {
        type: 'scaleOnly',
        x: mainViewWidth / videoWidth,
        y: 0.0,
        w: subViewWidth / videoWidth,
        h: subViewHeight / videoHeight,
      };
    }
    if (videoHeight === 720) {
      if (videoWidth === 1440) {
        return {
          type: 'scaleOnly',
          x: 2 / 3,
          y: 0.0,
          w: 1 / 3,
          h: 0.5,
        };
      } else {
        return {
          type: 'oldTwoPart',
          x: 0.0,
          y: 3 / 4,
          w: 1,
          h: 1 / 4,
        };
      }
    } else if (videoHeight === 1080) {
      return {
        type: 'oldThreePart',
        x: 0.0,
        y: mainViewHeight / 1080, // (720 / 1080)
        w: 1,
        h: 4 / 27, // (160 / 1080)
      };
    } else if (videoHeight === 1088) {
      return {
        type: 'oldThreePart',
        x: 0.0,
        y: mainViewHeight / 1088, // (720 / 1088)
        w: 1,
        h: 5 / 34, // (160 / 1088)
      };
    } else {
      return {
        type: 'scaleOnly',
        x: mainViewWidth / videoWidth,
        y: 0.0,
        w: subViewWidth / videoWidth,
        h: subViewHeight / videoHeight,
      };
    }
  }

  // 是否静音模式 (默认静音且不显示静音按钮)
  let muteMode = data.MuteMode === undefined ? false : data.MuteMode;

  var icon = document.getElementById('muteIcon');
  var isMuted = true;
  if (!muteMode) {
    /// 静音按钮相关
    const volumeOffSVG = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-volume-off" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
      <path d="M15 8a5 5 0 0 1 1.912 4.934m-1.377 2.602a5 5 0 0 1 -.535 .464"></path>
      <path d="M17.7 5a9 9 0 0 1 2.362 11.086m-1.676 2.299a9 9 0 0 1 -.686 .615"></path>
      <path d="M9.069 5.054l.431 -.554a.8 .8 0 0 1 1.5 .5v2m0 4v8a.8 .8 0 0 1 -1.5 .5l-3.5 -4.5h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l1.294 -1.664"></path>
      <path d="M3 3l18 18"></path>
      </svg>`;
    const volumeOnSVG = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-volume" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
      <path d="M15 8a5 5 0 0 1 0 8"></path>
      <path d="M17.7 5a9 9 0 0 1 0 14"></path>
      <path d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a.8 .8 0 0 1 1.5 .5v14a.8 .8 0 0 1 -1.5 .5l-3.5 -4.5"></path>
      </svg>`;
    icon.style.display = 'flex';
    icon.innerHTML = volumeOffSVG;
    icon.addEventListener('click', (event) => {
      isMuted = !isMuted;
      player.enableAudio(!isMuted);
      if (isMuted) {
        icon.innerHTML = volumeOffSVG;
        icon.classList.add('muted');
      } else {
        icon.innerHTML = volumeOnSVG;
        icon.classList.remove('muted');
      }
    });
  }

  player.onAudioInfo = function (info) {
    player.enableAudio(!isMuted);
  };
}

/**
 * 构建分图摄像头
 */
function buildCamera(index, source, useMerge) {
  const $el = addCameraBox(index, useMerge);

  const width = source.Width;
  const height = source.Height;
  let w = 0,
    h = 0;
  let manualScale = 1;
  if (!initSize()) {
    return;
  }

  function initSize() {
    w = window.innerWidth * 0.22;
    if (w < 180) {
      w = 180;
    }
    w *= manualScale; //还原手动缩放比例
    const scale = w / width;
    h = scale * height;

    if (h === $el.height()) {
      // 尺寸未变，无需频繁处理
      return false;
    }
    $el.width(w);
    $el.height(h);
    return true;
  }

  const viewEl = $el.children()[0];
  const fitbox = new SingleChannelFitBox(viewEl, {
    width: width,
    height: height,
    sourceWidth: width,
    sourceHeight: height,
  });

  var player = null;
  if (!useMerge) {
    player = buildCameraPlayer($el, source.HttpPullUrl);
  }

  function onResize(w, h) {
    const result = fitbox.process(w, h, useMerge);
    if (!useMerge) {
      player.setViewSize(result.canvasWidth, result.canvasHeight);
    }
  }

  var el = $el[0];
  var resizableBox = new ResizableFixedAspectBox(el, {
    right: false,
    top: false,
    maxWidth: window.innerWidth * 0.9,
    maxHeight: window.innerHeight * 0.9,
    minWidth: 180,
    isFlipVertical: useMerge, // 合图模式用到了垂直翻转
    onResize: function (width, height) {
      manualScale = width / w;
      onResize(width, height);
    },
  });
  resizableBox.init();
  el.resizableBox = resizableBox;

  addResizeCallback(function () {
    initSize();
    onResize(w, h);
  });
  onResize(w, h);
}

/**
 * 构建仅存在摄像头时的全屏摄像头
 */
function buildFullScreenCamera(index, source, useMerge) {
  const $el = addFullScreenCameraBox(index, useMerge);
  var player = null;
  if (!useMerge) {
    player = buildCameraPlayer($el, source.HttpPullUrl);
    player.setViewSize(window.innerWidth, window.innerHeight);
  } else {
    setCanvasContain($el, source);
  }
  function onResize() {
    if (!useMerge) {
      player.setViewSize(window.innerWidth, window.innerHeight);
    } else {
      setCanvasContain($el, source);
    }
  }
  addResizeCallback(onResize);
}

/// 设置canvas元素的width和height，使其对于窗口居中且contain
function setCanvasContain(el, source) {
  const cameraWidth = source.Width;
  const cameraHeight = source.Height;
  const viewWHR = cameraWidth / cameraHeight;
  const windowWHR = window.innerWidth / window.innerHeight;
  let w = 0,
    h = 0;
  if (viewWHR > windowWHR) {
    w = window.innerWidth;
    h = w / viewWHR;
  } else {
    h = window.innerHeight;
    w = h * viewWHR;
  }
  el.find('canvas').css('width', w);
  el.find('canvas').css('height', h);
}

function buildCameraPlayer(el, url) {
  const loading = new Loading(el);
  const canvas = el.find('canvas')[0];
  loading.show();
  var player = new LivePlayer(canvas.id, url);
  player.onBuffer = function (state) {
    if (state === 'full') {
      mainLoading.hide();
    } else {
      mainLoading.show();
    }
  };
  player.onPlay = function () {
    loading.hide();
  };
  players.push(player);
  return player;
}

function addCameraBox(index, useMerge) {
  var el = $(
    `<div class="sub_channel-box"><div class="channel_view"><canvas id="sub_${index}"></canvas></div></div>`,
  );
  $('.sub_channel-list').append(el);
  if (useMerge) {
    // webgl拷贝是翻转的，需要再翻转一下
    el.find('canvas').css('transform', 'scaleY(-1)');
  }
  return el;
}

function addFullScreenCameraBox(index, useMerge) {
  var el = $(
    `<div class="sub_channel-box full-screen-camera-container"><canvas id="sub_${index}"></canvas></div>`,
  );
  $('.sub_channel-list').append(el);
  if (useMerge) {
    // webgl拷贝是翻转的，需要再翻转一下
    el.find('canvas').css('transform', 'scaleY(-1)');
  }
  return el;
}
