import { Transition, defineComponent, onMounted, reactive, watch, defineAsyncComponent, computed, onUnmounted } from "vue";
import { connectWebsocket, evaluatingData, handleEndBegin, handleStartBegin, handleStartEvaluat, handleViewReport, startCheckDelay, checkUseEarphone, handleCancelEvaluat, checkMinInterval, handleEndEvaluat } from "/src/view/evaluating";
import Earphone from "./earphone";
import styles from "./index.module.less";
import SoundEffect from "./sound-effect";
import state, { handleRessetState, resetPlaybackToStart, musicalInstrumentCodeInfo, clearSelection, initSetPlayRate, resetBaseRate } from "/src/state";
import { storeData } from "/src/store";
import { browser } from "/src/utils";
import { getNoteByMeasuresSlursStart } from "/src/helpers/formateMusic";
import { Icon, Popup, showToast, closeToast, showLoadingToast } from "vant";
import EvaluatResult from "./evaluat-result";
import EvaluatAudio from "./evaluat-audio";
import { api_getDeviceDelay, api_openAdjustRecording, api_proxyServiceMessage, api_videoUpdate, getEarphone, api_back, api_startDelayCheck, api_cancelDelayCheck, api_remove_cancelDelayCheck, api_closeDelayCheck, api_finishDelayCheck, api_retryEvaluating, api_remove_finishDelayCheck } from "/src/helpers/communication";
import EvaluatShare from "./evaluat-share";
import { Vue3Lottie } from "vue3-lottie";
import startData from "./data/start.json";
import startingData from "./data/starting.json";
import iconTastBg from "./icons/task-bg.svg";
import iconEvaluat from "./icons/evaluating.json";
import { headImg } from "/src/page-instrument/header-top/image";
import { api_musicPracticeRecordVideoUpload } from "../api";
import { headTopData } from "../header-top/index";
import { getQuery } from "/src/utils/queryString";
import Countdown from "./countdown";
import { IPostMessage } from "/src/utils/native-message";
import tipErjiBg from "./icons/tip_erji.png"
import tipErjiBtn from "./icons/tip_btn.png"

// const DelayCheck = defineAsyncComponent(() =>
//   import('./delay-check')
// )

// frequency 频率, amplitude 振幅, decibels 分贝
type TCriteria = "frequency" | "amplitude" | "decibels";

/**
 * 节拍器时长
 * 评测模式时，应该传节拍器时长
 * 阶段评测时，判断是否从第一小节开始，并且曲子本身含有节拍器，需要传节拍器时长，否则传0
 */
let actualBeatLength = 0;
let calculateInfo: any = {};
let checkErjiTimer: any = null

export const reCheckDelay = () => {
  evaluatingData.onceErjiPopShow = false;
  evaluatingData.needCheckErjiStatus = true;
  headTopData.settingMode = false
  state.setting.soundEffect = false
  api_startDelayCheck({});
}

export default defineComponent({
  name: "evaluat-model",
  setup() {
    const query = getQuery();
    const evaluatModel = reactive({
      tips: true,
      evaluatUpdateAudio: false,
      isSaveVideo: state.setting.camera && state.setting.saveToAlbum,
      shareMode: false,
    });
    /**
     * 检测返回
     */
    const handleDelayBack = () => {
      if (query.workRecord) {
        evaluatingData.soundEffectMode = false;
        api_back();
      } else {
        evaluatingData.soundEffectMode = false;
        // handleRessetState();
        // headTopData.modeType = "init";
      }
    };
    /**
     * 执行检测
     */
    const handlePerformDetection = async () => {
      console.log(evaluatingData.checkStep, evaluatingData, "检测123");
      // 检测完成不检测了
      if (evaluatingData.checkEnd) return;
      // 延迟检测

      if (evaluatingData.checkStep === 0) {
        evaluatingData.checkStep = 10;
        // 没有设备延迟数据 或 开启了效音 显示检测组件,并持续检测耳机状态

        if (state.setting.soundEffect) {
          evaluatingData.soundEffectMode = true;
          return;
        }
        // 判断只有开始了设备检测之后才去调用api
        if (state.setting.soundEffect) {
          const delayData = await api_getDeviceDelay();
          // console.log("🚀 ~ delayTime:", delayData);
          if (delayData && delayData.content?.value < 0) {
            evaluatingData.soundEffectMode = true;
            return;
          }
        }

        handlePerformDetection();
        return;
      }
      // 效验完成
      if (evaluatingData.checkStep === 10) {
        const erji = await checkUseEarphone();
        if (!erji) {
          evaluatingData.earphoneMode = true;
        }
        evaluatingData.checkEnd = true;
        console.log("检测结束,生成数据");
        handleConnect();
      }
    };
    const browserInfo = browser();
    /** 是否是节奏练习 */
    const isRhythmicExercises = () => {
      const examSongName = state.examSongName || "";
      return examSongName.indexOf("节奏练习") > -1;
    };

    /** 获取评测标准 */
    const getEvaluationCriteria = () => {
      let criteria: TCriteria = "frequency";
      // 声部打击乐
      if ([23, 113, 121].includes(state.subjectId)) {
        criteria = "amplitude";
      } else if (isRhythmicExercises()) {
        // 分类为节奏练习
        criteria = "decibels";
      }
      return criteria;
    };

    /** 校验耳机状态 */
    const checkEarphoneStatus = async (type?: string) => {
      clearTimeout(checkErjiTimer);
      checkErjiTimer = null;
      if (type !== "start") {
        // const erji = await checkUseEarphone();
        const res = await getEarphone();
        const erji = res?.content?.checkIsWired || false;
        // 是否已经提示过耳机弹窗，重新进入评测页面，重置该状态为false，手动关掉耳机弹窗，改变该状态为true，本次评测都不在提示耳机状态弹窗
        if (!evaluatingData.onceErjiPopShow) {
          evaluatingData.earphoneMode = true;
        } else {
          clearTimeout(checkErjiTimer);
          checkErjiTimer = null;
          return;
        }
        evaluatingData.earPhoneType = res?.content?.type || "";
        if (evaluatingData.earPhoneType === "有线耳机") {
          clearTimeout(checkErjiTimer);
          checkErjiTimer = null;
          setTimeout(() => {
            evaluatingData.earphoneMode = false;
          }, 3000);
        } else {
          // 如果没有佩戴有限耳机，需要持续检测耳机状态
          checkErjiTimer = setTimeout(() => {
            checkEarphoneStatus();
          }, 1000);
        }
      }
      console.log("检测结束,生成数据", evaluatingData.websocketState, evaluatingData.startBegin, evaluatingData.checkEnd);
      handleConnect();
    };

    /** 生成评测曲谱数据 */
    const formatTimes = () => {
      console.log('评测111')
      let starTime = 0;
      let ListenMode = false;
      let dontEvaluatingMode = false;
      let skip = false;
      const datas = [];
      let selectTimes = state.times;
      let unitTestIdx = 0;
      let preTime = 0;
      let preTimes = [];
      // 系统节拍器时长
      actualBeatLength = Math.round((state.times[0].fixtime * 1000) / 1);
      // 如果是阶段评测，选取该阶段的times
      if (state.isSelectMeasureMode && state.section.length) {
        const startIndex = state.times.findIndex((n: any) => n.noteId == state.section[0].noteId);
        let endIndex = state.times.findIndex((n: any) => n.noteId == state.section[1].noteId);
        endIndex = endIndex < state.section[1].i ? state.section[1].i : endIndex;
        if (startIndex > 1) {
          // firstNoteTime应该取预备小节的第一个音符的开始播放的时间
          const idx = startIndex - 1 - state.times[startIndex - 1].si;
          preTime = state.times[idx] ? state.times[idx].time * 1000 : 0;
        }
        actualBeatLength = startIndex == 0 && state.isOpenMetronome ? actualBeatLength : 0;
        selectTimes = state.times.filter((n: any, index: number) => {
          return index >= startIndex && index <= endIndex;
        });
        preTimes = state.times.filter((n: any, index: number) => {
          return index < startIndex;
        });
        unitTestIdx = startIndex;
        starTime = selectTimes[0].sourceRelativeTime || selectTimes[0].relativeTime;
      }
      // 阶段评测beatLength需要加上预备小节的持续时长
      actualBeatLength = preTimes.length ? actualBeatLength + preTimes[preTimes.length - 1].relaMeasureLength * 1000 : actualBeatLength;
      // 如果是弱起，并且预备小节是第一节
      if (state.section.length && state.sectionFirst && state.sectionFirst.measureListIndex == 0) {
        actualBeatLength = actualBeatLength < Math.round((state.times[0].fixtime * 1000) / 1) ? Math.round((state.times[0].fixtime * 1000) / 1) : actualBeatLength;
      }
      
      let firstNoteTime = unitTestIdx > 1 ? preTime : 0;
      let measureIndex = -1;
      let recordMeasure = -1;

      for (let index = 0; index < selectTimes.length; index++) {
        const item = selectTimes[index];
        const note = getNoteByMeasuresSlursStart(item);
        // #8701 bug： 评测模式，是以曲谱本身的速度进行评测，所以rate取1，不需要转换
        // const rate = state.speed / state.originSpeed;
        const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
        // const difftime = item.difftime;
        const difftime = 0;
        const start = difftime + (item.sourceRelativeTime || item.relativeTime) - starTime;
        const end = difftime + (item.sourceRelaEndtime || item.relaEndtime) - starTime;
        const isStaccato = note.noteElement.voiceEntry.isStaccato();
        const noteRate = isStaccato ? 0.5 : 1;
        if (note.formatLyricsEntries.contains("Play") || note.formatLyricsEntries.contains("Play...")) {
          ListenMode = false;
        }
        if (note.formatLyricsEntries.contains("Listen")) {
          ListenMode = true;
        }
        if (note.formatLyricsEntries.contains("纯律结束")) {
          dontEvaluatingMode = false;
        }
        if (note.formatLyricsEntries.contains("纯律")) {
          dontEvaluatingMode = true;
        }
        const nextNote = selectTimes[index + 1];
        // console.log("noteinfo", note.noteElement.isRestFlag && !!note.stave && !!nextNote)
        if (skip && (note.stave || !item.noteElement.isRestFlag || (nextNote && !nextNote.noteElement.isRestFlag))) {
          skip = false;
        }
        if (note.noteElement.isRestFlag && !!note.stave && !!nextNote && nextNote.noteElement.isRestFlag) {
          skip = true;
        }
        // console.log(note.measureOpenIndex, item.measureOpenIndex, note);
        // console.log("skip", skip)
        // console.log(end,start,rate,noteRate, '评测')
        if (note.measureOpenIndex != recordMeasure) {
          measureIndex++;
          recordMeasure = note.measureOpenIndex;
        }
        // 是否是需要延续、不停顿演奏的音符
        let isTenutoSound = false;
        if (item?.noteElement?.tie && item.noteElement.tie?.StartNote) {
          const startId = item.noteElement.tie?.StartNote?.NoteToGraphicalNoteObjectId
          isTenutoSound = item.NoteToGraphicalNoteObjectId === startId ? false : true
        }
        // 音符是否不需要评测
        let noteNeedEvaluat = item.hasGraceNote || ListenMode || dontEvaluatingMode || !!item?.voiceEntry?.ornamentContainer || !!item.noteElement?.speedInfo?.startWord?.includes('rit.') || item.skipMode
        noteNeedEvaluat = noteNeedEvaluat == true ? true : false;
        const data = {
          timeStamp: (start * 1000) / rate,
          duration: ((end * 1000) / rate - (start * 1000) / rate) * noteRate,
          frequency: item.frequency,
          nextFrequency: item.nextFrequency,
          prevFrequency: item.prevFrequency,
          // 重复的情况index会自然累加,render的index是谱面渲染的index
          measureIndex: measureIndex,
          measureRenderIndex: item.measureListIndex,
          //  item.MeasureNumberXML >= 1 ? item.MeasureNumberXML - 1 : note.noteElement.sourceMeasure.measureListIndex,
          dontEvaluating: noteNeedEvaluat,
          musicalNotesIndex: index,
          denominator: note.noteElement?.Length.denominator,
          // isOrnament: !!note?.voiceEntry?.ornamentContainer,
          isTenutoSound,
          isStaccato: item?.voiceEntry?.isStaccato ? true : false, // 是否是重音
        };
        datas.push(data);
      }
      return {
        datas,
        firstNoteTime,
      };
    };
    /** 连接websocket */
    const handleConnect = async () => {
      const behaviorId = localStorage.getItem("behaviorId") || localStorage.getItem("BEHAVIORID") || undefined;
      // let rate = state.speed / state.originSpeed;
      const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
      // rate = parseFloat(rate.toFixed(2));
      console.log("速度比例", rate, "速度", state.speed);
      calculateInfo = formatTimes();
      // 评测的速度，如果是选段，则选选段开头小节的速度
      const evaluatSpeed = state.sectionStatus && state.section.length === 2 && state.section[0].measureSpeed ? state.section[0].measureSpeed * state.basePlayRate : state.speed;
      evaluatingData.evaluatSpeed = evaluatSpeed;
      const content = {
        musicXmlInfos: calculateInfo.datas,
        subjectId: state.musicalCode,
        detailId: state.detailId,
        examSongId: state.examSongId,
        xmlUrl: state.xmlUrl,
        partIndex: state.partIndex,
        behaviorId,
        platform: browserInfo.ios ? "IOS" : browserInfo.android ? "ANDROID" : "WEB",
        clientId: storeData.platformType === "STUDENT" ? "student" : storeData.platformType === "TEACHER" ? "teacher" : "education",
        hertz: state.setting.frequency,
        reactionTimeMs: state.setting.reactionTimeMs ? Number(state.setting.reactionTimeMs) : 0,
        speed: evaluatSpeed,
        heardLevel: state.setting.evaluationDifficulty,
        // beatLength: Math.round((state.fixtime * 1000) / rate),
        beatLength: actualBeatLength / rate,
        evaluationCriteria: state.evaluationStandard,
        speedRate: parseFloat(rate.toFixed(2)), // 播放倍率
      };
      await connectWebsocket(content);
      // state.playSource = "music";
    };

    /** 评测结果按钮处理 */
    const handleEvaluatResult = (type: "practise" | "tryagain" | "look" | "share" | "update" | "selfCancel") => {
      if (type === "update") {
        if (state.isAppPlay) {
          evaluatModel.evaluatUpdateAudio = true;
          resetPlaybackToStart();
          return;
        } else if (evaluatingData.resultData?.recordIdStr || evaluatingData.resultData?.recordId) {
          const rate = state.basePlayRate * state.originAudioPlayRate; // 播放倍率
          // 上传云端
          // evaluatModel.evaluatUpdateAudio = true;
          api_openAdjustRecording({
            recordId: evaluatingData.resultData?.recordIdStr || evaluatingData.resultData?.recordId,
            title: state.examSongName || "曲谱演奏",
            coverImg: state.coverImg,
            speedRate: parseFloat(rate.toFixed(2)), // 播放倍率
            musicRenderType: state.musicRenderType,
            musicSheetId: state.examSongId,
            'part-index': state.partIndex
          });
          return;
        }
      } else if (type === "share") {
        // 分享
        evaluatModel.shareMode = true;
        return;
      } else if (type === "look") {
        // 跳转
        handleViewReport("recordId", "instrument");
        return;
      } else if (type === "practise") {
        // 去练习
        handleStartEvaluat();
      } else if (type === "tryagain") {
        startBtnHandle();
      } else if (type === "selfCancel") {
        // 再来一次，需要手动取消评测，不生成评测记录，不显示评测结果弹窗
        evaluatingData.oneselfCancleEvaluating = true;
        // handleCancelEvaluat();
        handleEndEvaluat(true, 'selfCancel');
        // evaluatingData.isBeginMask = true;
        evaluatingData.evaluatings = {};
        state.playState = "paused";
      }
      resetPlaybackToStart();
      evaluatingData.resulstMode = false;
    };

    /** 上传音视频 */
    const hanldeUpdateVideoAndAudio = async (update = false) => {
      if (!update) {
        evaluatModel.evaluatUpdateAudio = false;
        return;
      }
      if (state.setting.camera && state.setting.saveToAlbum) {
        evaluatModel.evaluatUpdateAudio = false;
        api_videoUpdate((res: any) => {
          if (res) {
            if (res?.content?.type === "success") {
              handleSaveResult({
                id: evaluatingData.resultData?.recordId,
                videoFilePath: res?.content?.filePath,
              });
            } else if (res?.content?.type === "error") {
              showToast({
                message: res.content?.message || "上传失败",
              });
            }
          }
        });
        return;
      }
      evaluatModel.evaluatUpdateAudio = false;
      showToast("上传成功");
    };
    const handleSaveResult = async (_body: any) => {
      await api_musicPracticeRecordVideoUpload(_body);
      showToast("上传成功");
    };

    const startBtnHandle = async () => {
      // 如果打开了延迟检测开关，需要先发送开始检测的消息
      const delayData = await api_getDeviceDelay();
      console.log('设备的延迟值',delayData.content?.value)
      if (delayData && delayData.content?.value <= 0) {
        await api_startDelayCheck({});
        return;
      }
      evaluatingData.needReplayEvaluat = false;
      // 选段未完成时，清除选段状态
      if (state.sectionStatus && state.section.length < 2) {
        clearSelection();
      }
      // 如果是异常状态，先等待500ms再执行后续流程
      if (evaluatingData.isErrorState && !state.setting.soundEffect) {
        // console.log('异常流程1')
        showLoadingToast({
          message: "处理中",
          duration: 1000,
          overlay: true,
          overlayClass: styles.scoreMode,
        });
        await new Promise<void>((resolve) => {
          setTimeout(() => {
            closeToast();
            evaluatingData.isErrorState = false;
            // console.log('异常流程2')
            resolve();
          }, 1000);
        });
      }
      // console.log('异常流程3')
      // 非选段状态，从头开始评测，重置速度
      if (!state.sectionStatus && state.section.length === 0) {
        state.activeNoteIndex = 0;
        state.speed = state.times[0].measureSpeed * state.basePlayRate
      }
      initSetPlayRate();
      // 检测APP端socket状态
      const res: any = await startCheckDelay();
      if (res?.checked) {
        handleConnect();
        handleStartBegin(calculateInfo.firstNoteTime);
        if (evaluatingData.isErrorState) {
          evaluatingData.isErrorState = false;
          evaluatingData.resulstMode = false;
        }
      }
    };

    // 监听到APP取消延迟检测
    const handleCancelDelayCheck = async (res?: IPostMessage) => {
      console.log("监听取消延迟检测", res);
      if (res?.content) {
        // 关闭延迟检测页面，并返回到模式选择页面
        // await api_closeDelayCheck({});
        handleDelayBack();
      }
    };

    // 监听APP延迟成功的回调
    const handleFinishDelayCheck = async (res?: IPostMessage) => {
      console.log("监听延迟检测成功", res);
      evaluatingData.socketErrorPop = false;
      if (res?.content) {
        evaluatingData.checkEnd = true;
        state.setting.soundEffect = false;
        evaluatingData.tipErjiShow = true;
      }
    };

    // 监听重复评测消息
    const handRetryEvaluating = () => {
      handleEvaluatResult("tryagain");
    };

    const earPhonePopShow = computed(() => {
			return evaluatingData.earphoneMode && !state.isLoading && !state.hasDriverPop;
		});

    const tipErjiPopShow = computed(() => {
			return evaluatingData.tipErjiShow && !state.isLoading && !state.hasDriverPop;
		});

    // watch(
    //   () => state.setting.soundEffect,
    //   (val) => {
    //     if (val) {
    //       headTopData.settingMode = false
    //       api_startDelayCheck({});
    //       state.setting.soundEffect = false
    //     }
    //   }
    // );

    // 手动取消评测，需要自动再次评测
    // watch(
    //   () => evaluatingData.needReplayEvaluat,
    //   (val) => {
    //     if (val && evaluatingData.oneselfCancleEvaluating) {
    //       setTimeout(() => {
    //         startBtnHandle();
    //       }, 500);
    //     }
    //   }
    // );

    onMounted(async () => {
      // 如果打开了延迟检测开关，需要先发送开始检测的消息
      const delayData = await api_getDeviceDelay();
      console.log('设备的延迟值',delayData.content?.value)
      if (delayData && delayData.content?.value <= 0) {
        await api_startDelayCheck({});
      } else {
        evaluatingData.checkEnd = true;
        // 点击评测模式进入评测模块的需要检测耳机状态，通过返回按钮进入评测模块的，不检测耳机状态
        if (evaluatingData.needCheckErjiStatus) {
          checkEarphoneStatus();
        }
      }
      evaluatingData.isDisabledPlayMusic = true;
      // handlePerformDetection();
      api_cancelDelayCheck(handleCancelDelayCheck);
      api_finishDelayCheck(handleFinishDelayCheck);
      api_retryEvaluating(handRetryEvaluating);
    });
    
    onUnmounted(() => {
      api_remove_finishDelayCheck(handleFinishDelayCheck);
      api_remove_cancelDelayCheck(handleCancelDelayCheck);
			clearTimeout(checkErjiTimer);
      checkErjiTimer = null;
		});

    return () => (
      <div>
        <div class={styles.operatingBtn}>
          {!evaluatingData.startBegin && (
            <img
              class={[styles.iconBtn, "evaluting-1"]}
              src={headImg("icon_play.png")}
              onClick={() => {
                startBtnHandle();
              }}
            />
          )}
          {evaluatingData.startBegin && (
            <>
              <img class={styles.iconBtn} src={headImg("icon_reset.png")} onClick={() => {
                // 校验评测最小间隔时间
                const currentTime = +new Date();
                // 开始评测和结束评测的间隔时间小于800毫秒，则不处理
                if (currentTime - evaluatingData.recordingTime < 800) {
                  return;
                }
                handleEvaluatResult("selfCancel")
              }} />
              <img class={styles.iconBtn} src={headImg("submit.png")} onClick={() => {
                // 校验评测最小间隔时间
                const currentTime = +new Date();
                // 开始评测和结束评测的间隔时间小于800毫秒，则不处理
                if (currentTime - evaluatingData.recordingTime < 800) {
                  return;
                }
                handleEndBegin()
              }} />
            </>
          )}
        </div>

        {/* {evaluatingData.soundEffectMode && (
          <DelayCheck
            onClose={() => {
              evaluatingData.soundEffectMode = false;
              handlePerformDetection();
            }}
            onBack={() => handleDelayBack()}
          />
        )} */}

        {/* 倒计时 */}
        <Countdown />
        {/* 遮罩 */}
        {
          evaluatingData.isBeginMask && <div class={styles.beginMask}></div>
        }
        <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={tipErjiPopShow.value}>
          <div class={styles.earphoneBox}>
            <img class={styles.earphoneBg} src={tipErjiBg} />
            <img class={styles.earphoneBtn} src={tipErjiBtn} onClick={() => {
              evaluatingData.tipErjiShow = false;
              checkEarphoneStatus();
            }} />
          </div>
        </Popup>        
        <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={earPhonePopShow.value}>
          <Earphone
            earphoneType={evaluatingData.earPhoneType}
            onClose={() => {
              evaluatingData.onceErjiPopShow = true;
              clearTimeout(checkErjiTimer);
              checkErjiTimer = null;
              // #11035,可能刚好关闭耳机弹窗的时候，第二次又出现了弹窗
              setTimeout(() => {
                evaluatingData.earphoneMode = false;
              }, 300);
              // handlePerformDetection();
              checkEarphoneStatus("start");
            }}
          />
        </Popup>

        {/* 评测作业，非完整评测不显示评测结果弹窗 */}
        {evaluatingData.hideResultModal ? (
          <EvaluatResult onClose={handleEvaluatResult} />
        ) : (
          <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatingData.resulstMode}>
            <EvaluatResult onClose={handleEvaluatResult} />
          </Popup>
        )}

        <Popup teleport="body" closeOnClickOverlay={false} class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatModel.evaluatUpdateAudio}>
          <EvaluatAudio onClose={hanldeUpdateVideoAndAudio} />
        </Popup>
        <Popup teleport="body" class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatModel.shareMode}>
          <EvaluatShare onClose={() => (evaluatModel.shareMode = false)} />
        </Popup>
      </div>
    );
  },
});
