/**
 * 播放过程中必要的context，效果与state一致仅用于操作，但是包含方法，好处是可以在任意地方调用，操作播放状态
 */

import { Toast } from 'vant'
import { reactive, watchEffect } from 'vue'
import store from 'store'
import { constant, throttle, debounce } from 'lodash'
import {
  getActtiveNoteByTimes,
  getDuration,
  getIndex,
  getNoteBySlursStart,
  setStepIndex,
  getSlursNote,
  getVoicePartInfo,
  formatBeatUnit,
} from './helpers'
import SectionHint from '/src/helpers/section-hint'
import { browser, formatTime, getPlatform, getRequestHostname } from '/src/helpers/utils'
import request from '/src/helpers/request'
// import * as Tone from 'tone'
import router from '/src/router'
import appState from '/src/state'
import detailState from './state'
import SettingState from '/src/pages/detail/setting-state'
// import fixtimeRela from '/src/constant/fixtime'
import TickPlayer, { getTickTime } from '/src/components/tick/player'
// import { tickByNumerator } from '/src/components/tick/constant'
import { postMessage, listenerMessage, promisefiyPostMessage } from '/src/helpers/native-message'

import EventEmitter from 'eventemitter3'
import { useClientType, useOriginSearch } from '/src/subpages/colexiu/uses'
import { evaluatPlayerStop } from '/src/subpages/colexiu/buttons/evaluating'
import { unitTestData } from '/src/subpages/colexiu/unitTest'
import { modelType } from '/src/subpages/colexiu/buttons'
import { metronomeData } from '/src/helpers/metronome'

export const event = new EventEmitter()

const browserInfo = browser()

const initBehaviorId = '' + new Date().valueOf()

const getLinkId = (): string => {
  const seearchid = useOriginSearch().id as string
  return location.hash.split('?')[0].split('/').pop() || seearchid || ''
}

export const getFixtimeRelaVal = () => {
  const route: any = router.currentRoute.value
  const linkId = location.hash.split('?')[0].split('/').pop()
  return 0 //(fixtimeRela as any)[(route.params.id || linkId)] || 0
}


export const getFixTime = (speed: number) => {
  const duration: any = getDuration(state.osmd)
  let numerator = duration.numerator || 0
  let denominator = duration.denominator || 4
  const beatUnit = duration.beatUnit || 'quarter'
  if (detailState.repeatedBeats) {
    // 音频制作问题仅2拍不重复
    numerator = numerator === 2 ? 4 : numerator
  }
  //酷乐秀计算方法
  // const time = !detailState.needTick && !detailState.skipTick ? ((denominator * 60) / speed / denominator) * numerator : 0
  // 管乐迷计算方法
  // console.log('diff', speed, duration, formatBeatUnit(beatUnit), denominator, numerator, (numerator / denominator))
  // console.log('👀时间')
  const time = !detailState.needTick && !detailState.skipTick ? (60 / speed * formatBeatUnit(beatUnit)) * (numerator / denominator) : 0
  // console.log({duration, t:(60 / speed * formatBeatUnit(beatUnit)) * (numerator / denominator), time, numerator,denominator, "duration.numerator": duration.numerator})
  return time
}

let prevIndex: number = 0

export type IPlayState = 'init' | 'play' | 'pause' | 'suspend'

export type IMode = 'background' | 'music'

export type ISonges = {
  background?: string
  music?: string
}

const state = reactive({
  /** 曲目信息 */
  songs: {} as ISonges,
  /** 播放状态 */
  playState: 'init' as IPlayState,
  /** 当前播放背景 */
  sectionHint: new SectionHint(),
  /** 音频播放器实例 */
  audiosInstance: null as any,
  /** 原声伴奏 */
  mode: 'music' as IMode,
  /** 是否是第一次播放 */
  isFirstPlay: true,
  metro: null as any,
  metroing: false,
  /** 时长 */
  duration: '0:00',
  durationNum: 0,
  /** 当前时间 */
  currentTime: '0:00',
  currentTimeNum: 0,
  loading: false,
  /** 速度 */
  speed: 90,
  browser: browser(),
  /** 调速是否可见 */
  speedShow: false,
  /** 播放进度进度是否可见 */
  progressShow: false,
  touched: false,
  /** opendisplaymusicdisplay 实例 */
  osmd: null as any,
  /** 节拍器实例 */
  tickPlayer: null as any,
  /** 评测状态 */
  evaluatingStatus: false,
  /** 评测提示 */
  evaluatingTips: false,
  clickTime: 0,
  evaluatingFixTime: 0,
  /** 摄像头状态 */
  cameraStatus: false,
  /** 录制状态 */
  captureStatus: false,
  ticking: false,
  /** 第几分轨 */
  partIndex: 0,
  /** 当前音符index */
  activeIndex: 0,
  /** 音频播放结束钩子 */
  playEndCallback: {
    /** 结束评测 */
    endEvaluat: () => {}
  } as {[key: string]: () => void},  
  /** 阶段评测，延迟检测是否检测过 */
  delayCheckFirst: false,  
  /** 开始播放时，记录的mp3播放倍率，用户当前设置的速度/当前小节的速度 */
  basePlayRate: 1,
  /** 播放中，更加当前小节速度动态计算的展示速度 */
  playIngSpeed: 90,
  /** 上一次app返回的播放进度 */
  preAppAudioPlayTime: 0,
  /** app返回的音频文件总时长 */
  appAudioTotalTime: 0,
  /** 播放倍率不等于1，或者是选段评测，APP暂时不支持保存演奏，需要给出提示 */
  initShow: true,
})

const syncStepIndex = (i: number) => {
  console.log("🚀 ~ i", i)
  
  if (state.osmd.hidden !== false) {
    state.osmd.cursor.show()
  }
  prevIndex = i
  setStepIndex(state.osmd, i)
  // console.log(66666664444)
  refreshIndex(detailState.times[i]?.time)
}

/**播放状态改变时,向父页面发送事件 */
export const sendParentMessage = (playState: string) => {
  window.parent.postMessage(
    {
      api: 'headerTogge',
      playState: playState
    },
    '*'
  )
}
watchEffect(() => {
  detailState.maskStatus = state.playState === 'play'
  if(['play', 'pause'].includes(state.playState)) {
    sendParentMessage(state.playState)
  }
})

const syncPlayState = async () => {
  if (detailState.activeDetail.isAppPlay) {
    const cloudGetMediaStatus = await promisefiyPostMessage({
      api: 'cloudGetMediaStatus',
    })
    const status = cloudGetMediaStatus?.content.status
    state.playState = status
  } else {
    state.playState = state.audiosInstance.getStatus()
  }
}

export default state

export const setCurrentTime = (time: number) => {
  console.log('setCurrentTime', time)
  const fixt = time // - 5
  // console.log('set', fixt)
  detailState.fixedKey = 0
  state.currentTimeNum = fixt
  state.currentTime = formatTime(fixt)
  state.audiosInstance.setCurrentTime(fixt)
  if (detailState.activeDetail.isAppPlay) {
    promisefiyPostMessage({
      api: 'cloudSetCurrentTime',
      content: {
        currentTime: time * 1000,
        songID: detailState.activeDetail.examSongId,
      },
    })
  } else {
    state.audiosInstance.setCurrentTime(fixt)
  }
  refreshView()
  syncPlayState()
  const index = getIndex(detailState.times, state.currentTimeNum)
  syncStepIndex(index)

  // changeMode(state.mode)
}

export const onTimeChanged = (num: number) => {
  const time = Math.min(num, state.durationNum)
  const index = getIndex(detailState.times, state.currentTimeNum)
  setCurrentTime(time)
  syncStepIndex(index)
  // console.log('onTimeChanged', time)
  // changeMode(state.mode)
}

/** 获取当前MidiId */
export const getActiveMidiId = () => {
  return state.osmd?.sheet?.instruments?.[0]?.subInstruments?.[0]?.midiInstrumentID ?? 0
}

/**
 * 修改原音或伴奏
 * @param val IMode
 */
export const changeMode = async (val: IMode, type?: string | undefined) => {
  // console.log('切换音源',val,state.songs)
  const cm: IMode = val === 'background' ? 'music' : 'background'
  // console.log(!state.songs[val], val, cm)
  if (detailState.activeDetail.isAppPlay) {
    const data = new Map()
    for (const name of detailState.partListNames) {
      data.set(name, 60)
    }
    for (const name of getVoicePartInfo().partListNames) {
      data.set(name, cm === 'background' ? 100 : 0)
    }
    promisefiyPostMessage({
      api: 'cloudVolume',
      content: {
        activeMidiId: getActiveMidiId(),
        activeMidiVolume: cm === 'background' ? 100 : 0,
        parts: Array.from(data.keys()).map((item) => ({
          name: item,
          volume: data.get(item),
        })),
      },
    })

    // state.mode = val
    // promisefiyPostMessage({
    //   api: 'cloudSwitch',
    //   content: {
    //     songID: detailState.activeDetail.examSongId,
    //     parts: cm === 'background' ? [] : getVoicePartInfo().partListNames,
    //   }
    // })
  }
  // if (!state.songs[val]) {
  //   return
  // }
  state.mode = val
  // 如果没有伴奏，音源切换按钮文案重置为原音
  if (!state.songs.background) {
    state.mode = 'music'
  }
  if (type === 'all') {
    state.audiosInstance?.setMute(true, state.songs[cm])
    state.audiosInstance?.setMute(true, state.songs[val])
  } else {
    state.audiosInstance?.setMute(true, state.songs[cm])
    state.audiosInstance?.setMute(false, state.songs[val])
  }
}

export const changeAllMode = () => {
  if (detailState.activeDetail?.isAppPlay) {
    const data = new Map()
    for (const name of detailState.partListNames) {
      data.set(name, 1)
    }
    promisefiyPostMessage({
      api: 'cloudVolume',
      content: {
        activeMidiId: getActiveMidiId(),
        activeMidiVolume: 100,
        parts: Array.from(data.keys()).map((item) => ({
          name: item,
          volume: data.get(item),
        })),
      },
    })
  } else {
    state.mode = 'background'
    state.audiosInstance?.setMute(true)
  }
}

// 重置播放倍率
export const resetBaseRate = () => {
  const currentItem: any = detailState.times[0];
  const currentSpeed = currentItem?.measureSpeed ? currentItem.measureSpeed : detailState.baseSpeed;
  state.speed = currentSpeed
  state.playIngSpeed = currentSpeed
  state.activeIndex = 0
  state.basePlayRate = 1;
  changeSpeed(currentSpeed)
}

export const changeSpeed = (speed: number, isSave: boolean = true) => {
  // console.log('速度设置',speed,isSave)
  // const route: any = router.currentRoute.value
  const speeds = store.get('speeds') || {}
  if (isSave){
    speeds[getLinkId()] = speed
    store.set('speeds', speeds)
  }
  state.speed = speed
  state.playIngSpeed = speed
  // 当前的音符
  const currentItem: any = detailState.times[state.activeIndex];
  state.basePlayRate = currentItem?.measureSpeed ? state.speed / currentItem.measureSpeed : state.speed / detailState.baseSpeed;
  if (!detailState.activeDetail) return
  state.audiosInstance?.setSpeed(state.basePlayRate)
  promisefiyPostMessage({
    api: 'cloudChangeSpeed',
    content: {
      speed: speed,
      originalSpeed: detailState.activeDetail.originalSpeed,
      songID: detailState.activeDetail.examSongId,
    },
  })
  // changeMode(state.mode)
  if (state.playState === 'play') {
    syncStepIndex(getIndex(detailState.times, state.currentTimeNum))
  }
}

let nextLook: boolean = false

let syncTimed: boolean = false

export const resetCursor = () => {
  if (state.osmd) {
    if(state.osmd.product){
      state.osmd.cursor.setPosition({...detailState.times[0].cursorBox})
    } else {
      state.osmd.cursor.reset()
    }
    state.osmd.cursor.hide()
    detailState.fixedKey = 0
  }
}

export const refreshIndexBase = (index: number) => {
  
  if (index < 0) return
  const { osmd }: any = state
  if (osmd) {
    if (detailState.times[index]) {
      if (!detailState.sectionStatus) {
        state.sectionHint.show()
      }
      if (detailState.times[index] && detailState.times[index].noteElement) {
        state.sectionHint.showForElement(detailState.times[index])
      }
      if (!osmd.product){
        if (osmd.cursor.hidden !== false) {
          osmd.cursor.reset()
          osmd.cursor.show()
          detailState.fixedKey = 0
        }
      }
      if (prevIndex !== index) {
        setStepIndex(state.osmd, detailState.times[index].i, prevIndex)
        prevIndex = index
      }
      detailState.fixedKey = detailState.times[index].realKey
      detailState.activeNote = detailState.times[index]
    }
  }
}

// 练习模式下，开始播放时，记录mp3的播放倍率
export const initSetPlayRate = () => {
  const item: any = (detailState.sectionStatus && detailState.section.length === 2) ? detailState.section[0] : detailState.times[state.activeIndex];
  if (item && modelType.value === "practice" && item.measureSpeed) {
    const ratio = state.speed / item.measureSpeed
    // state.audiosInstance?.setSpeed(ratio)
    state.basePlayRate = ratio || 1;
    console.log('播放倍率',state.basePlayRate)
  }
}

// 根据当前小节动态设置，右上角展示的速度
const dynamicShowPlaySpeed = (index: number) => {
  const item: any = detailState.times[index];

  // if (item && state.playState === "play" && item.measureSpeed ) {
  //   state.playIngSpeed = Math.floor(state.basePlayRate * item.measureSpeed)
  // }
  if (item && item.measureSpeed ) {
    state.playIngSpeed = Math.floor(state.basePlayRate * item.measureSpeed)
  }
}

export const refreshIndex = (ctime?: number) => {
  const { osmd }: any = state
  if (osmd && (ctime || state.audiosInstance.audio)) {
    let currentTimeNum = ctime || (state.audiosInstance.audio as HTMLAudioElement).currentTime
    // 如果是评测状态，当前时间取app返回的进度
    if (state.evaluatingStatus) {
      currentTimeNum = ctime ? ctime : 0
    }
    try {
      metronomeData?.metro?.sound(currentTimeNum);
    } catch (error) {}

    const index = getIndex(detailState.times, currentTimeNum)
    // 监听app返回的ctime
    // console.log(777777777,index,ctime,state.audiosInstance.audio.currentTime)
    // if (state.evaluatingStatus) {
    //   console.log('评测模式','app返回的播放进度',ctime)
    // } else {
    //   console.log('练习模式','h5播放器的播放进度',state.audiosInstance.audio.currentTime)
    // }
    dynamicShowPlaySpeed(index);
    state.activeIndex = index
    removeRepateBackground(index)
    // console.log(currentTimeNum, index, detailState.times[detailState.times.length - 1]?.endtime)
    const lastNote = detailState.times[detailState.times.length - 1]
    const endtime = lastNote?.sourceEndTime || lastNote?.endtime
    if (currentTimeNum > endtime) {
      state.osmd.cursor.hide()
      state.sectionHint.destroy()
    } else {
      if (detailState.times[index]) {
        refreshIndexBase(index)
      }
    }
  }
}

/** 重复中移除重复的背景 */
export const removeRepateBackground = (index: number) => {
  if (state.evaluatingStatus && index) {
    const activeNote = detailState.times[index]
    const note = detailState.times[index + 1] || activeNote
    const number = note?.noteElement?.sourceMeasure?.measureListIndex
    // 0 比较特殊重置等操作会导致误操作所以跳过第0个
    if (note && detailState.evaluatings[number] && index > 0) {
      detailState.evaluatings = {
        ...detailState.evaluatings,
        [number]: undefined,
      }
    }
  }
}

/**
 * 刷新播放的状态
 * @param ctime 当前时间
 * @returns
 */
export const refreshPlayer = async (ctime?: number) => {
  // if (!state.durationNum) {
  //   loadedmetadata()
  // }
  // const status: IPlayState = state.audiosInstance.getStatus()
  const { osmd }: any = state
  if (osmd && (ctime || state.audiosInstance.audio)) {
    // state.playState = status
    const currentTimeNum = ctime || (state.audiosInstance.audio as HTMLAudioElement).currentTime
    // console.log('refreshPlayer', currentTimeNum)

    try {
      metronomeData?.metro?.sound(currentTimeNum);
    } catch (error) {}

    const mintime = 0 //detailState.times[0].time
    if (currentTimeNum + 1 < mintime) {
      setCurrentTime(mintime)
      return
    } else {
      syncTimed = false
    }
    const nextTime = () => {
      if (detailState.sectionStatus && detailState.section.length === 2) {
        if (currentTimeNum >= detailState.section[0].time) {
          detailState.sectionFlash = false
        }
        const nextNote = detailState.times[detailState.section[1].i + 1]
        const time = nextNote
          ? nextNote.halfTone === 0
            ? detailState.section[1].endtime
            : nextNote.time
          : state.durationNum
        return currentTimeNum + (browserInfo.xiaomi ? 0.2 : 0.08) >= time
      }
      return false
    }
    const isNext = nextTime()
    // console.log('选段123',detailState.section,detailState.sectionStatus)
    // 选段播放结束
    if (isNext) {
      // console.log("isNext", detailState.section[1], detailState.section[1].endtime, currentTimeNum)
      state.audiosInstance.setMute(true)
      state.osmd.cursor.hide()
      if (detailState.activeDetail?.isAppPlay) {
        pause()
      } else {
        await state.audiosInstance.pause()
      }
      // 如果是单元测验 和课后训练，或者是选段评测，选段播放结束 直接结束
      if ((unitTestData.isSelectMeasureMode || detailState.section.length === 2) && state.evaluatingStatus){
        console.log('选段播放结束')
        event.emit('ended')
        return
      }
      setSectionModeCurrentTime()
      clearAccelerateRefreshPlayer()
      setTimeout(() => {
        // 开启了循环播放
        if (detailState.section.length && SettingState.sett.loop){
          setPlayState()
        }
      }, 1000)
      state.loading = false
      return
    }
    // 当MIDI进度超过最后一个音符时间触发结束事件
    if(detailState.activeDetail?.isAppPlay && state.durationNum + 3 < currentTimeNum) {
      if (state.evaluatingStatus) {
        pause()
        console.log(2)
        event.emit('ended', new Event('ended'))
      } else {
        if (SettingState.sett.loop) {
          await pause()
          await setCurrentTime(0)
          await play()
        } else {
          pause()
        }
      }
    }
  }
}

/**
 * 重置播放状态
 * @param notStop 是否停止播放
 */
export const resetPlayStatus = async (notStop?: boolean) => {
  try {
    prevIndex = 0
    state.osmd.cursor.reset()
    state.osmd.cursor.hide()
    detailState.fixedKey = 0
    detailState.sectionFlash = false
    if (state.sectionHint) {
      state.sectionHint.destroy()
    }
    if (!notStop) {
      if (detailState.activeDetail.isAppPlay) {
        await promisefiyPostMessage({
          api: 'cloudSuspend',
          content: {
            songID: detailState.activeDetail.examSongId,
          },
        })
      } else {
        console.log('resetPlayStatus调用暂停')
        state.audiosInstance.pause()
      }
    }
    syncPlayState()
  } catch (error) {
    console.log('resetPlayStatus错误', error)
  }
}

export const play = async () => {
  console.log('播放执行')
  // 评测是app播放，非h5播放
  if (modelType.value === 'evaluation') return
  if (state.isFirstPlay) {
    resetPlayStatus()
    detailState.fixedKey = 0
  }
  if (detailState.activeDetail.isAppPlay) {
    await syncPlayState()
    promisefiyPostMessage({
      api: 'cloudSuspend',
      content: {
        songID: detailState.activeDetail.examSongId,
      },
    })
  } else {
    state.playState = state.audiosInstance.getStatus()
    clearAccelerateRefreshPlayer()
    accelerateRefreshPlayer()
  }
}

const refreshNote = () => {
  if (state.playState === 'play') {
    const time = state.preAppAudioPlayTime / 1000;
    state.currentTimeNum = time
    refreshPlayer(time)
    // console.log(66666663333)
    refreshIndex(time)
    // 播放到最后一秒，停止播放
    if (state.appAudioTotalTime > 1000 && state.preAppAudioPlayTime >= state.appAudioTotalTime) {
      console.log('播放结束123')
      state.playState = 'pause'
      state.playEndCallback.endEvaluat()
      ended(new Event('ended'))
    }
  }
  refreshView()
}

// 评测播放刷新音符进度
export const setEvaluatingStep = () => {
  // console.log('播放状态',state.playState)
  if (state.playState !== "play") {
    console.log("暂停播放");
    return;
  }
  let startTime = Date.now();
  requestAnimationFrame(() => {
    const endTime = Date.now();
    // 渲染时间大于16.6,就会让页面卡顿, 如果渲染时间大与16.6就下一个渲染帧去计算
    if (endTime - startTime < 16.7) {
      refreshNote()
      setEvaluatingStep()
    } else {
      setTimeout(() => {
        refreshNote()
        setEvaluatingStep()
      }, 16.7);
    }
  });
};

const setDelayTime = async (time: number) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(time)
    }, time)
  })
}

/**
 * 暂停播放
 */
export const pause = async () => {
  if (detailState.sectionStatus) {
    state.osmd.cursor.hide()
  }
  if (detailState.activeDetail.isAppPlay) {
    await syncPlayState()
    await promisefiyPostMessage({
      api: 'cloudSuspend',
    })
    await setDelayTime(200)
  } else {
    state.playState = state.audiosInstance.getStatus()
    clearAccelerateRefreshPlayer()
    state.audiosInstance.pause()
  }
}

export const waiting = () => {
  state.loading = true
}

export const playing = () => {
  state.loading = false
}

export const ended = debounce(async (evt: Event) => {
  resetPlayStatus()
  detailState.fixedKey = 0
  if (!state.evaluatingStatus) {
    refreshPlayer(0)
    if (SettingState.sett.loop) {
      await setPlayState()
    }
  }
  setCurrentTime(0)
  event.emit('ended', evt)
}, 300, {
  'leading': true,
  'trailing': false
})

let timer: any = null

let now = 0

let nowTime = 0

let prevTime: number = 0

// 播放中一直触发
const accelerateRefreshPlayer = () => {
  if (timer || !state.audiosInstance) {
    return
  }
  timer = setInterval(() => {
    requestAnimationFrame(() => {
      refreshPlayer()
      if (state.audiosInstance.getStatus() === 'play') {
        refreshIndex()
      }
    })
  }, 16.7)
}

const clearAccelerateRefreshPlayer = () => {
  clearInterval(timer)
  timer = null
  now = 0
}

/**
 * 选择段落
 */
export const sectionChange = () => {
  detailState.sectionStatus = !detailState.sectionStatus
  clearAccelerateRefreshPlayer()
  resetPlayStatus()
  if (!detailState.sectionStatus) {
    setCurrentTime(0)
    detailState.fixedKey = 0
   resetBaseRate();
  }
  if (detailState.sectionStatus && detailState.section.length != 2) {
    resetCursor()
  }
}

export const clearSectionStatus = () => {
  detailState.section = []
  detailState.sectionBoundingBoxs = []
  detailState.sectionStatus = false
}

export const getFirsrNoteByMeasureListIndex = (index: number, tie = true) => {
  for (const note of detailState.times) {
    if (note?.noteElement?.sourceMeasure?.measureListIndex === index) {
      let noteTies: any = null
      for (const item of note.measures) {
        if (getSlursNote(item)) {
          noteTies = getSlursNote(item)
        }
      }
      if (noteTies) {
        if (noteTies.sourceMeasure?.measureListIndex !== index) {
          for (const n of detailState.times) {
            if (n.noteElement.NoteToGraphicalNoteObjectId === noteTies.NoteToGraphicalNoteObjectId) {
              return n
            }
          }
        }
      }
      return note
    }
  }
  return null
}

export const setSectionModeCurrentTime = () => {
  if (detailState.needTick) {
    setCurrentTime(detailState.section[0].sourceStartTime || detailState.section[0].time)
  } else {
    const measureListIndex = detailState.section[0].noteElement?.sourceMeasure?.measureListIndex
    if (measureListIndex > 0) {
      setCurrentTime(getFirsrNoteByMeasureListIndex(measureListIndex - 1).time)
      // 如果没有节拍器,默认提前一个小节
      // setCurrentTime(getFirsrNoteByMeasureListIndex(measureListIndex).time)
      detailState.sectionFlash = true
    } else {
      setCurrentTime(0)
    }
  }
}

export const setPlayerView = () => {
  if (detailState.sectionStatus) {
    syncStepIndex(getIndex(detailState.times, state.currentTimeNum))
    if (detailState.section.length === 2) {
      setSectionModeCurrentTime()
    } else {
      detailState.section = []
      detailState.sectionBoundingBoxs = []
      detailState.sectionStatus = false
      Toast.clear()
    }
  }
}

const cloudToggleState = async () => {
  const cloudGetMediaStatus = await promisefiyPostMessage({
    api: 'cloudGetMediaStatus',
  })
  const status = cloudGetMediaStatus?.content.status
  if (status === 'init') {
    return
  }
  if (status === 'suspend') {
    await promisefiyPostMessage({
      api: 'cloudPlay',
      content: {
        songID: detailState.activeDetail.examSongId,
        startTime: state.currentTimeNum * 1000,
        originalSpeed: detailState.activeDetail.originalSpeed,
        speed: state.speed,
        hertz: SettingState.sett.hertz,
      },
    })
  } else {
    await promisefiyPostMessage({
      api: 'cloudSuspend',
    })
  }
  const cloudGetMediaStatused = await promisefiyPostMessage({
    api: 'cloudGetMediaStatus',
  })
  state.playState = cloudGetMediaStatused?.content.status
  console.log(cloudGetMediaStatused, 'cloudGetMediaStatused')
}

export const toggleState = async (delay?: number) => {
  if (modelType.value === 'init') return
  if (detailState.activeDetail.isAppPlay) {
    await cloudToggleState()
  } else {
    // console.log(detailState.activeDetail)
    // console.log('delay', delay)
    state.isFirstPlay = false
    setPlayerView()
    await state.audiosInstance.togglePlay(delay)
    if (!state.evaluatingStatus) {
      changeMode(state.mode)
    }
    state.playState = state.audiosInstance.getStatus()
  }
}

const setActiveKey = (index: number) => {
  detailState.activeTick = index
}

const setTickStop = () => {
  // console.log('节拍器结束', new Date().getTime() - state.clickTime)
  detailState.activeTick = -1
  detailState.activeTickRepeat = 1
  toggleState(getTickTime(state.speed / detailState.baseSpeed))
}

let timeliner: any = -1

export const startIntervalTimeline = (maxTime: number, end: () => void) => {
  const nowTimeline = new Date().getTime()
  let currenttTime = 0
  const throttleIndex = throttle(() => {
    if (currenttTime) {
      refreshView()
    }
  }, 1200)
  const start = () => {
    requestAnimationFrame(() => {
      currenttTime = (new Date().getTime() - nowTimeline) / 1000
      // console.log(66666661111)
      refreshIndex(currenttTime)
      if (maxTime && currenttTime >= maxTime) {
        clearIntervalTimeline()
        end()
      }
      throttleIndex()
    })
  }
  start()
  timeliner = setInterval(() => {
    start()
  }, 16.7)
}

export const clearIntervalTimeline = () => {
  clearInterval(timeliner)
}

const onTickDestroy = () => {
  event.emit('tickDestroy')
}

export const setTick = (stop: () => void, speed?: number) => {
  // 节拍时间是固定的无需调整
  const mixStop = () => {
    stop()
    event.emit('tickEnd')
  }
  if (detailState.needTick) {
    let { numerator, denominator } = getDuration(state.osmd)
    if (state.osmd.numerator && state.osmd.denominator){
      numerator = state.osmd.numerator
      denominator = state.osmd.denominator
    }
    if (detailState.activeDetail.isAppPlay) {
      state.ticking = true
      postMessage(
        {
          api: 'cloudMetronome',
          content: {
            // 少量情况下需要重复
            repeat: numerator === 2 ? 2 : 1,
            denominator,
            numerator,
          },
        },
        (res) => {
          state.ticking = false
          if (res?.content.status === 'finish') {
            mixStop()
          } else if (res?.content.status === 'cancel') {
            event.emit('tickDestroy')
          }
        }
      )
    } else {
      const activeTickRepeat = numerator === 2 ? 2 : 1
      detailState.activeTickRepeat = activeTickRepeat
      console.log('ticking')
      state.tickPlayer = new TickPlayer(numerator, (speed || state.speed) / 90)
      state.tickPlayer?.start(numerator, (speed || state.speed) / 90, activeTickRepeat)
      state.tickPlayer?.event.off('tick', setActiveKey)
      state.tickPlayer?.event.off('stop', mixStop)
      state.tickPlayer?.event.off('destroy', onTickDestroy)
      state.tickPlayer?.event.on('tick', setActiveKey)
      state.tickPlayer?.event.on('stop', mixStop)
      state.tickPlayer?.event.on('destroy', onTickDestroy)
    }
  } else {
    mixStop()
  }
}

/**设置播放状态 */
export const setPlayState = async () => {
  if (detailState.activeTick > -1 || state.ticking) {
    return
  }
  await syncPlayState()
  if (state.playState !== 'pause' && state.playState !== 'suspend') {
    await toggleState()
    return
  }
  setPlayerView()
  setTick(setTickStop)
}

export const testPlay = async () => {
  if (detailState.activeTick > -1 || state.ticking) {
    return
  }
  await syncPlayState()
  if (state.playState !== 'pause' && state.playState !== 'suspend') {
    await toggleState()
    return
  }
  setPlayerView()
  //setTick(setTickStop)
}

// 有系统节拍器的，评测需要播放系统节拍器
export const setEvaluatTick = async () => {
  await setTick(setTickStop)
}

export const stopTick = () => {
  if (state.tickPlayer) {
    state.tickPlayer.destroy()
  }
  event.emit('stopTick')
  detailState.activeTickRepeat = 1
  detailState.activeTick = -1
}

export const windowResize = () => {
  const index = getIndex(detailState.times, state.currentTimeNum)
  setTimeout(() => {
    state.sectionHint?.showForElement(detailState.times[index]?.noteElement)
  }, 200)
}

export const loadedmetadata = () => {
  state.duration = formatTime(state.audiosInstance.duration)
  state.durationNum = state.audiosInstance.duration
}

let prevDiff: number = 0
let viewing: boolean = false

export const refreshView = () => {
  let cursorEl : any = undefined
  let containerEl : any = undefined
  if (state?.osmd?.product){
    cursorEl = state.osmd.cursor.img
    containerEl = document.querySelector('#colexiu-detail-music-sheet')
  }
  const top = Math.max(parseFloat((cursorEl || state.osmd.cursor.cursorElement).style.top), 0)
  if (Math.abs(prevDiff - top) > 10 && !viewing) {
    viewing = true
    setTimeout(() => {
      viewing = false
      const scrollElement = containerEl ? containerEl :
        appState.clintNmae === 'colexiu'
          ? state.osmd.container.parentElement.parentElement
          : state.osmd.container.parentElement
      scrollElement.scrollTo({
        top: top,
        left: 0,
        behavior: 'smooth',
      })
      prevDiff = top
    }, 100)
  }
}
const updatePlayTime = async (time: number) => {
  const search = useOriginSearch()
  const behaviorId = sessionStorage.getItem('behaviorId') || search.behaviorId || initBehaviorId
  const prefix = getRequestHostname()
  const clientType = useClientType()
  // 已有全局记录时长, 单独记录不需要了
  // if (!state.evaluatingStatus) {
  //   // 如果是后台不需要统计时长
  //   if (clientType === 'web') return
  //   try {
  //     const res = await request.post('/musicPracticeRecord/save', {
  //       prefix: prefix,
  //       requestType: 'json',
  //       data: {
  //         musicSheetId: getLinkId(),
  //         sysMusicScoreId: getLinkId(),
  //         feature: search.feature,
  //         playTime: time,
  //         deviceType: getPlatform(),
  //         behaviorId,
  //       },
  //     })
  //     event.emit('updatePlayTimeSuccess', res.data)
  //   } catch (error) {}
    
  // }
  
}

export const setAudioInit = () => {
  state.audiosInstance.event.on('loadedmetadata', loadedmetadata)
  state.audiosInstance.event.on('waiting', waiting)
  state.audiosInstance.event.on('playing', playing)
  state.audiosInstance.event.on('play', play, false)
  state.audiosInstance.event.on('pause', pause, false)
  state.audiosInstance.event.on('ended', ended, false)
  state.audiosInstance.event.on('updatePlayTime', updatePlayTime, false)
  listenerMessage('cloudplayed', async () => {
    await syncPlayState()
    state.currentTimeNum = 0
    state.currentTime = '00:00'
    state.audiosInstance.event.emit('ended', new Event('ended'))
  })
  listenerMessage('cloudTimeUpdae', (res) => {
    // console.log('cloudTimeUpdae', res?.content.currentTime)
    const time = res?.content.currentTime / 1000
    // requestAnimationFrame(async () => {
    // const cloudGetMediaStatus = await promisefiyPostMessage({
    //   api: 'cloudGetMediaStatus',
    //   content: {
    //     songID: detailState.activeDetail.examSongId,
    //   }
    // })
    // const status = cloudGetMediaStatus?.content.status
    if (state.playState === 'play') {
      state.currentTimeNum = time
      state.currentTime = formatTime(time)
      refreshPlayer(time)
      // console.log(66666662222)
      refreshIndex(time)
    }
    refreshView()
    // })
  })
  // 监听评测曲谱音频播放进度，返回
  listenerMessage("playProgress", (res) => {
    if (state.playState === 'play') {
      const time = res?.content.currentTime / 1000
      const diffTime = res?.content?.currentTime - state.preAppAudioPlayTime;
      
      // console.log('app返回的mp3进度',time)
      if (diffTime < 0) {
        console.log('进度返回异常','本次时间比上次慢',diffTime,'当前播放时间:',res?.content?.currentTime)
        return
      }
      state.preAppAudioPlayTime = res?.content?.currentTime
      state.appAudioTotalTime = res?.content?.totalDuration
      // requestAnimationFrame(async () => {
      //   if (state.playState === 'play') {
      //     state.currentTimeNum = time
      //     refreshPlayer(time)
      //     // console.log(66666663333)
      //     refreshIndex(time)
      //     // 播放到最后一秒，停止播放
      //     if (res?.content?.totalDuration > 1000 && res?.content?.currentTime >= res?.content?.totalDuration) {
      //       console.log('播放结束123')
      //       state.playState = 'pause'
      //       state.playEndCallback.endEvaluat()
      //       ended(new Event('ended'))
      //     }
      //   }
      //   refreshView()
      // })
    }
  });
  state.audiosInstance.event.on('timeupdate', () => {
    state.currentTimeNum = state.audiosInstance.currentTime
    state.currentTime = formatTime(state.audiosInstance.currentTime)
    requestAnimationFrame(() => {
      if (state.audiosInstance.getStatus() === 'play') {
        refreshPlayer()
      }
      refreshView()
    })
  })

  window.addEventListener('resize', windowResize)
}

export const back = () => {
  if (state.browser.isApp) {
    postMessage({
      api: 'back',
    })
  } else {
    // (this as any).$router.replace({
    //   path: '/',
    // }) 
  }
}

export const setStepView = (activeNote: any, time?: number) => {
  prevIndex = Math.max(activeNote.i, 0)
  syncStepIndex(activeNote.i)
  if (time) {
    // console.log(time)
    refreshPlayer(time)
  }
  refreshView()
}

export const noteClick = (evt: MouseEvent) => {
  if (state.isFirstPlay) {
    Toast('开始播放后才能调整进度')
    return
  }
  state.speedShow = false;
  let activeNote = getNoteBySlursStart(getActtiveNoteByTimes(evt))
  console.log('点击音符',activeNote)
  if (activeNote) {
    const time = activeNote.sourceStartTime || activeNote.time
    // 点击音符，动态设置右上角的速度，非选段模式
    if (activeNote.measureSpeed && detailState.section.length < 2) {
      state.speed = Math.floor(state.basePlayRate * activeNote.measureSpeed)
      state.playIngSpeed = state.speed
    }
    setCurrentTime(time)
    setStepView(activeNote.i, time)
    detailState.fixedKey = activeNote.realKey
    detailState.activeNote = activeNote
  }
}

let playStartTime: number = 0

export const startCapture = async () => {
  console.log('SettingState.sett.camera:', SettingState.sett.camera, " SettingState.eva.save:",  SettingState.eva.save)
  if (
    SettingState.sett.camera &&
    SettingState.eva.save
  ) {
    postMessage({
      api: 'startCapture',
    })
  }
}

export const endCapture = async () => {
  if (SettingState.eva.save && SettingState.sett.camera ) {
    postMessage(
      {
        api: 'endCapture',
      })
  }
}

export const setCaptureMode = async () => {
  if (browserInfo.isApp && SettingState.sett.camera) {
    postMessage({
      api: 'setCaptureMode',
      content: {
        mode: state.evaluatingStatus ? 'evaluating' : 'practice',
      },
    })
  }
}


export const getBoundingBoxByNote = (note: any, extra?: any) => {
  const mBoundingBox = note.sourceMeasure?.verticalMeasureList?.[0]?.boundingBox
  if (!mBoundingBox) {
    return null
  }
  const boundingBox = {
    ...mBoundingBox.absolutePosition,
    ...mBoundingBox.size,
    ...extra,
  }
  boundingBox.x = boundingBox.x * 10
  boundingBox.y = boundingBox.y * 10
  boundingBox.width = boundingBox.width * 10
  boundingBox.height = boundingBox.height * 10
  if (note?.sourceMeasure?.verticalMeasureList?.[0]?.stave?.height) {
    boundingBox.height = note.sourceMeasure?.verticalMeasureList?.[0]?.stave?.height
  }
  return boundingBox
}