let sharedStream: MediaStream | null = null;

/**
 * 获得摄像头的视频流，可能抛出异常
 * 获得的流只能通过本文件中的 closeMediaStream 关闭
 */
export async function getMediaStream(): Promise<MediaStream> {
  if (sharedStream) {
    logger({ cnl: ["server"], act: "共享sharedStream" });
    return sharedStream;
  }
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
    logger({
      cnl: ["local", "server"],
      pgu: "AUTO",
      act: "检查navigator.mediaDevices.getUserMedia",
      key: "不可能的事情发生了",
    });
  }

  logger({ cnl: ["server"], pgu: "AUTO", act: "启动摄像头" });
  logger({
    cnl: ["server"],
    pgu: "AUTO",
    act: "摄像头打开",
    dtl: "摄像头getSupportedConstraints",
    ext: {
      getSupportedConstraints:
        navigator.mediaDevices.getSupportedConstraints &&
        JSON.stringify(navigator.mediaDevices.getSupportedConstraints()),
    },
  });
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: {
        facingMode: "user",
        aspectRatio: 4 / 3,
        // @ts-expect-error 是支持的属性，应该是typescript的类型还没包含进来
        resizeMode: "crop-and-scale",
        width: 640,
        height: 480,
      },
    });
    if (!stream) {
      logger({
        cnl: ["server"],
        act: "摄像头打开失败",
        dtl: "没有可用的视频流",
        key: "不可能的事情发生了",
      });
    }

    // logger detail info
    {
      const vt0 = stream.getVideoTracks()[0];
      if (vt0 && vt0.getCapabilities && vt0.getSettings) {
        logger({
          cnl: ["local", "server"],
          pgu: "AUTO",
          ext: {
            getCapabilities: vt0.getCapabilities(),
            getConstraints: vt0.getConstraints && vt0.getConstraints(),
            getSettings: vt0.getSettings && vt0.getSettings(),
          },
        });
      } else {
        logger({
          cnl: ["local", "server"],
          pgu: "AUTO",
          dtl: "stream.getVideoTracks()[0] failed",
        });
      }
    }
    sharedStream = stream;
    return stream;
  } catch (error) {
    console.log(error);
    logger({
      cnl: ["server"],
      act: "摄像头打开失败",
      dtl: "无法启用摄像头",
      stk: error instanceof Error ? error.message : error + "",
      ext: { isError: error instanceof Error },
    });

    if (!(error instanceof Error)) throw new Error("not an error");

    let errMsg;
    if (error.name || error.message) {
      errMsg = `${error.name} ${error.message}`;
    } else {
      errMsg = error;
    }

    if (error.name === "NotReadableError") {
      $message.error("无法启用摄像头: " + error.name + " 请重试！");
    } else if (
      error.name === "NotFoundError" ||
      error.name === "DevicesNotFoundError"
    ) {
      $message.error(
        "无法启用摄像头: " +
          error.name +
          " 没有找到合适的摄像头！请重试或更换摄像头！"
      );
    } else {
      $message.error("无法启用摄像头: " + error.name + errMsg);
    }

    const errorMsgLog =
      errMsg + (typeof errMsg === "object" ? JSON.stringify(errMsg) : "");
    logger({
      cnl: ["server"],
      act: "摄像头打开失败",
      dtl: "无法启用摄像头",
      ejn: JSON.stringify(error),
      stk: error.stack,
      ext: {
        errorName: error.name,
        errorMessage: error.message,
        errorMsgLog,
      },
    });

    throw error;
  }
}

export function closeMediaStream() {
  logger({ cnl: ["server"], act: "关闭stream" });
  sharedStream?.getTracks().forEach(function (track) {
    track.stop();
  });
  sharedStream = null;
}
