import { defineComponent, onMounted, Ref, ref, watch } from 'vue'
import request from '/src/helpers/request'
import originRequest from 'umi-request'
import MusicSheet from '/src/music-sheet'
import runtime from '/src/pages/detail/runtime'
import {
  formatXML,
  onlyVisible,
  getAllNodes,
  getCustomInfo,
  getBoundingBoxByverticalNote,
  getParentNote,
} from '/src/pages/detail/helpers'
import SettingState from '/src/pages/detail/setting-state'
import detailState from '/src/pages/detail/state'
import { useOriginSearch } from '../colexiu/uses'
import styles from '../colexiu/index.module.less'
import detailStyles from './index.module.less'
import { OpenSheetMusicDisplay } from '/osmd-extended/src'
import { MusicSheelDetail, ShaeetStatusType } from '../colexiu'
import Header, { active } from './header'
import { colorsClass } from '/src/pages/report'
import { getLeveByScoreMeasure } from '/src/pages/detail/evaluating/helper'
import { Button, Skeleton } from 'vant'
import Empty from '/src/components/empty'
import { useSpecialShapedScreen } from '../colexiu/uses/use-app'

const search = useOriginSearch()

const useXml = async (url: string, detail: MusicSheelDetail) => {
  const xml = await originRequest(url)
  let score = ref<string>('')
  const parseXmlInfo = getCustomInfo(xml)
  score.value = formatXML(parseXmlInfo.parsedXML, {
    title: detail.musicSheetName,
  })
  const partIndex = Number(search['part-index']) || 0
  score.value = onlyVisible(score.value, partIndex)
  return score
}

const useDetail = (id: number | string): [Ref<ShaeetStatusType>, Ref<MusicSheelDetail>, Ref<any>] => {
  const status = ref<ShaeetStatusType>('loading')
  const data = ref<MusicSheelDetail>({})
  const record = ref<any>({})
  onMounted(async () => {
    status.value = 'loading'
    try {
      const recordRes = await request.get('/sysMusicRecord/getLastEvaluationMusicalNotesPlayStats', {
        params: {
          recordId: search.id,
        },
      })

      if (!recordRes.data) {
        status.value = 'error'
        return
      }

      record.value = recordRes.data
      console.log(record.value)
      const res = await request.get(`/music/sheet/detail/${record.value?.musicalNotesPlayStats.examSongId}`)
      data.value = res.data
      detailState.partIndex = recordRes.data.partIndex || 0
      status.value = 'success'
    } catch (error) {
      status.value = 'error'
      console.log(error)
    }
  })
  return [status, data, record]
}

export default defineComponent({
  name: 'Colexiu',
  setup() {
    const headerRef = ref()
    const renderLoading = ref(true)
    const renderError = ref(false)
    const score = ref<string>('')
    const useedid = ref<string[]>([])
    const allNote = ref<any[]>([])
    const [detailStatus, detail, record] = useDetail(search.id as string)
    watch(detailStatus, async () => {
      if (detailStatus.value === 'success' && detail.value.xmlFileUrl) {
        const xml = await useXml(detail.value.xmlFileUrl, detail.value)
        // console.log(runtime.songs, detailState.partListNames)
        score.value = xml.value
      }
    })

    // useUser()

    useSpecialShapedScreen()

    const getOffsetPosition = (type: keyof typeof colorsClass): string => {
      switch (type) {
        case 'CADENCE_FAST':
          return 'translateX(2px)'
        case 'CADENCE_SLOW':
          return 'translateX(-2px)'
        case 'INTONATION_HIGH':
          return 'translateY(-2px)'
        case 'INTONATION_LOW':
          return 'translateY(2px)'
        default:
          return ''
      }
    }

    const filterNotes = () => {
      const include = ['RIGHT', 'WRONG', 'CADENCE_WRONG']
      if (active.value === 'pitch') {
        include.push(...['CADENCE_FAST', 'CADENCE_SLOW'])
      } else if (active.value === 'rhythm') {
        include.push(...['INTONATION_HIGH', 'INTONATION_LOW'])
      } else if (active.value === 'completion') {
        include.push(...['INTEGRITY_WRONG'])
      }
      return record.value.musicalNotesPlayStats.notesData.filter((item: any) => include.includes(item.musicalErrorType))
    }

    const setViewColor = () => {
      clearViewColor()
      renderLoading.value = false
      for (const note of filterNotes()) {
        const active = allNote.value[note.musicalNotesIndex]
        setTimeout(() => {
          if (useedid.value.includes(active.id)) {
            return
          }
          useedid.value.push(active.id)
          const svgEl = document.getElementById('vf-' + active.id)
          const stemEl = document.getElementById('vf-' + active.id + '-stem')
          const errType = note.musicalErrorType as keyof typeof colorsClass
          const isNeedCopyElement = ['INTONATION_HIGH', 'INTONATION_LOW', 'CADENCE_FAST', 'CADENCE_SLOW'].includes(
            errType
          )
          stemEl?.classList.add(colorsClass[errType])
          svgEl?.classList.add(colorsClass[errType])
          if (svgEl && isNeedCopyElement) {
            stemEl?.classList.remove(colorsClass[errType])
            stemEl?.classList.add(colorsClass.RIGHT)
            svgEl?.classList.remove(colorsClass[errType])
            svgEl?.classList.add(colorsClass.RIGHT)
            const copySvg = svgEl.querySelector('.vf-notehead')!.cloneNode(true) as SVGSVGElement
            copySvg.style.transform = getOffsetPosition(errType)
            svgEl.style.opacity = '.7'
            if (stemEl) {
              stemEl.style.opacity = '.7'
            }
            copySvg.id = 'vf-' + active.id + '-copy'
            copySvg?.classList.add(colorsClass[errType])
            // stemEl?.classList.add(colorsClass.RIGHT)
            // @ts-ignore
            osmd?.container.querySelector('svg')!.insertAdjacentElement('afterbegin', copySvg)
            // svgEl?.parentElement?.appendChild(copySvg)
          }
        }, 300)
      }
    }

    const removeClass = (el?: HTMLElement | null) => {
      if (!el) return
      const classList = el.classList.values()
      for (const val of classList) {
        if (val?.indexOf('vf-') !== 0) {
          el.classList.remove(val)
        }
      }
    }

    const clearViewColor = () => {
      for (const id of useedid.value) {
        removeClass(document.getElementById('vf-' + id))
        removeClass(document.getElementById('vf-' + id + '-stem'))
        const qid = 'vf-' + id + '-copy'
        const copyEl = document.getElementById(qid)
        if (copyEl) {
          copyEl.remove()
        }
      }
      useedid.value = []
    }

    const onRerender = (osmd: OpenSheetMusicDisplay) => {
      renderLoading.value = false
      headerRef.value?.autoShow()
      setTimeout(() => {
        for (const item of Array.from(document.querySelectorAll('.vf-beam'))) {
          ;(item as SVGAElement).querySelector('path')?.setAttribute('fill', '#aeaeae')
        }
      })
      runtime.osmd = osmd
      allNote.value = getAllNodes(runtime.osmd)
      setViewColor()
      const setEvaluatings = (note: any, data: any, dontTransition = true) => {
        const startNote = getBoundingBoxByverticalNote(note)
        detailState.evaluatings = {
          ...detailState.evaluatings,
          [startNote.measureIndex]: {
            ...startNote,
            ...getLeveByScoreMeasure(data.score),
            score: data.score,
            dontTransition,
          },
        }
      }

      if (record.value.userMeasureScore) {
        for (const key in record.value.userMeasureScore) {
          if (Object.prototype.hasOwnProperty.call(record.value.userMeasureScore, key)) {
            const data = record.value.userMeasureScore[key]
            for (const time of allNote.value) {
              if (data.measureRenderIndex == time.noteElement.sourceMeasure.MeasureNumberXML - 1) {
                if (!time.noteElement.tie) {
                  setEvaluatings(time, data)
                } else {
                  for (const item of time.noteElement.tie.notes) {
                    const note = getParentNote(item)
                    if (!note) continue
                    setEvaluatings(note, data, item !== time.noteElement.tie.StartNote)
                  }
                }
              }
            }
          }
        }
      }
      // console.log(detailState.evaluatings, record.value.userMeasureScore)
      // detailState.activeDetail.originalSpeed = osmd.Sheet.userStartTempoInBPM
      // RuntimeUtils.setAudioInit()
    }

    const onRenderError = () => {
      renderError.value = true
      renderLoading.value = false
    }
    return () => {
      const loading = renderLoading.value || detailStatus.value === 'loading'
      const error = renderError.value || detailStatus.value === 'error'
      // console.log('ColexiuRender', detail.value.musicSubject, score.value)
      return (
        <div
          class={[
            styles.container,
            SettingState.sett.eyeProtection && 'eyeProtection',
            SettingState.sett.camera && 'openCamera',
          ]}
        >
          <Header
            className={styles.header}
            detail={detail.value}
            record={record}
            ref={headerRef}
            style={{
              paddingLeft: detailState.isSpecialShapedScreen ? detailState.notchHeight / 2 + 'px' : 'auto',
            }}
            onActiveChange={() => setViewColor()}
          />
          <div
            id="colexiu-detail-music-sheet"
            class={[styles.musicSheet, detailStyles.musicSheet]}
            style={{
              paddingLeft: detailState.isSpecialShapedScreen ? detailState.notchHeight / 2 + 'px' : 'auto',
            }}
          >
            {loading && !error && <Skeleton class={styles.skeleton} rowWidth="80%" title row={3} />}
            {error && <Empty />}
            {score.value && (
              <>
                <h3
                  style={{
                    fontSize: '24px',
                    fontWeight: 'normal',
                    textAlign: 'center',
                    padding: '0 10px',
                    marginTop: '36px',
                    marginBottom: '0px',
                    marginLeft: 'auto',
                  }}
                  class="van-ellipsis"
                >
                  {detail.value.musicSheetName}
                </h3>
                <MusicSheet
                  score={score.value}
                  showSection
                  opotions={{
                    drawTitle: false,
                    drawComposer: false,
                    drawLyricist: false,
                    drawMetronomeMarks: true,
                    drawMeasureNumbers: true,
                    autoResize: false,
                  }}
                  EngravingRules={{
                    DefaultColorNotehead: '#aeaeae',
                    DefaultColorRest: '#aeaeae',
                    DefaultColorMusic: '#aeaeae',
                    DefaultColorStem: '#aeaeae',
                    DefaultColorChordSymbol: '#aeaeae',
                    DefaultColorLabel: '#aeaeae',
                    DYMusicScoreType: SettingState.sett.type,
                  }}
                  onRerender={onRerender}
                  onRenderError={onRenderError}
                />
              </>
            )}
          </div>
        </div>
      )
    }
  },
})
