import { defineComponent, Ref, ref, reactive } from 'vue'
import opensheetmusicdisplay from 'opensheetmusicdisplay'
import { Skeleton, Popup, Cell, CellGroup, Empty } from 'vant'
import request from 'umi-request'
import MusicScore from '/src/components/music-score'
import RequestAuth from '/src/helpers/request'
import PopupTitle from '/src/components/popup-title'
import Player from '/src/components/SheetMusic/player'
import NetworkError from '/src/components/network-error'
import Fingering from '/src/components/fingering'
import classnames from 'classnames'
// import qs from 'query-string'
import styles from './index.module.less'

const osmd: Ref = ref(null)
const container: Ref = ref(null)
const player: Ref = ref(null)

let Osmd: any = null

const getAllNodes = (osmd: any) => {
  const allNotes = []
  const indexNodes: any = {}
  if (osmd.cursor) {
    try {
      osmd.cursor.reset()
    } catch (error) {}
    const iterator = osmd.cursor.iterator
    let i = 0
    while(!iterator.endReached) {
      for (const v of iterator.currentVoiceEntries) {
        let si = 0
        for (const note of v.notes) {
          if (note) {
            const { realValue } = iterator.currentTimeStamp
            const relativeTime = realValue * 4 * (60 / 90)
            if (indexNodes[i] === undefined) {
              indexNodes[i] = 0
            }
            indexNodes[i] += relativeTime
            const fixedKey = note.ParentVoiceEntry.ParentVoice.Parent.SubInstruments[0].fixedKey || 0
            allNotes.push({
              i,
              si,
              note: note.halfTone + 12, // see issue #224
              relativeTime,
              time: relativeTime + 5,
              realValue,
              noteElement: note,
              svgElelent: note.sourceMeasure.verticalMeasureList[0].vfVoices['1'].tickables,
              fixedKey,
              realKey: note.halfTone - fixedKey * 12
            })
          }
          si++
        }
      }
      iterator.moveToNext()
      i++
    }
  }

  return {
    allNotes,
    fixNoteTime: indexNodes
  }
}

const state = reactive({
  osmd: {},
  times: [],
  fixNoteTime: [],
  scoreData: null,
  loading: true,
  error: false,
  libs: [],
  libIndex: 0,
  libshow: false,
  xmlStatus: 'init',
} as any)

export default defineComponent({
  name: 'SheetMusic',
  data() {
    return {
      activeKey: 0,
      score: '',
    }
  },
  async mounted() {
    // this.setStateOsmd()
    await this.loadAndRender()
  },
  activated() {
    // console.log('activated')
    // this.loadAndRender()
  },
  computed: {
    firstLib() {
      return {
        ...state.libs[state.libIndex],
        speed: state.libs[state.libIndex]?.speed || 90
      }
    }
  },
  methods: {
    setStateOsmd() {
      // osmd.value.innerHTML = ''
      if (osmd) {
        Osmd = new opensheetmusicdisplay.OpenSheetMusicDisplay(osmd.value, {
          followCursor: true,
          autoResize: true,
          // drawLyricist: false,
          // drawLyrics: false,
          drawSubtitle: false,
          drawTitle: false,
          // alignRests: 1,
          drawMetronomeMarks: false,
          drawPartNames: false,
          drawMeasureNumbers: false,
          // drawComposer: true,
          // drawCredits: true,
        })
        // Osmd.EngravingRules.SetWantedStemDirectionByXml = false
        // Osmd.EngravingRules.UnknownTextHeight = 0
      }
    },
    async FetchDetail () {
      state.libs = []
      const parseSearch = (this as any).$router.currentRoute.value.params || {} // qs.parse(location.search)
      try {
        const res = await RequestAuth.get('/sysMusicScoreAccompaniment/queryPage', {
          params: {
            sysMusicScoreId: parseSearch.id
          }
        })
        state.error = false
        state.libs = [...res.data]
        return res.data
      } catch (error) {
        state.error = true
      }
    },
    async FetchXml() {
      state.xmlStatus = 'init'
      try {
        const res = await request.get(this.firstLib.xmlUrl/*'./Fundamental-Level 1 - 4Flute.xml'*/, {
          mode: 'cors'
        })
        return res
      } catch (error) {
        state.xmlStatus = 'error'
      }
    },
    async loadAndRender () {
      try {
        // if (!state.libs.length) {
          state.loading = true
          await this.FetchDetail()
        // }
        if (this.firstLib.xmlUrl) {
          const res = await this.FetchXml()
          this.score = res
          // await state.osmd.load(res)
          // state.osmd.sheet.defaultStartTempoInBpm = this.firstLib.speed
          // state.osmd.sheet.userStartTempoInBPM = this.firstLib.speed
          // console.log(state.osmd)
        } else {
          state.xmlStatus = 'no'
        }
        // await state.osmd.render()
        state.loading = false
        // const { allNotes } = getAllNodes(state.osmd)
        // state.times = allNotes
      } catch (error) {
        state.loading = false
      }
    }
  },
  render() {
    return (
      <div class={styles.container} ref={container}>
        <h3 class={styles.title}>{this.firstLib?.examSongName}</h3>
        {state.xmlStatus === 'no' && !state.error ? (
          <Empty description="暂无曲谱信息"/>
        ) : null}
        {state.xmlStatus === 'error' && !state.error  ? (
          <Empty image="error" description="曲谱信息获取错误"/>
        ) : null}
        <NetworkError
          onReload={() => {
            this.loadAndRender()
          }}
          loading={state.loading}
          isError={state.error}
        >
          <Fingering style={{
            position: 'fixed',
            top: 0,
            width: '100%'
          }} type="flute" fixedKey={this.activeKey}/>
          {state.loading ? (
            <div style={{position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, paddingTop: '2rem'}}>
              <Skeleton row={16} />
            </div>
          ) : null}
          {this.score ? (
            <MusicScore
              score={this.score}
              onRerender={(osmd: any) => state.osmd = osmd}
            />
          ) : null}
          {/* {!state.loading && state.libs.length ? (
            <Player
              ref={player}
              osmd={Osmd}
              times={state.times}
              onActiveKeyChange={(val: number) => this.activeKey = val}
              songs={{
                background: state.libs[state.libIndex]?.mp3Url,
                music: state.libs[state.libIndex]?.url
              }}
              lib={state.libs[state.libIndex]}
              openLib={() => state.libshow = true}
            />
          ) : null} */}
          {/* <Popup
            show={state.libshow}
            round
            closeable
            class={styles.popup}
            teleport="body"
            closeOnPopstate={true}
            onClickCloseIcon={() => state.libshow = false}
          >
            <PopupTitle title="选择声部"/>
            <CellGroup class={styles.lib}>
              {[...state.libs].map((item: any, index: number) => (
                <Cell
                  class={classnames(styles.item, {[styles.active]: index === state.libIndex})}
                  title={item.subjectName}
                  onClick={ () => {
                    if (state.libIndex == index) {
                      state.libshow = false
                      return
                    }
                    state.loading = true
                    state.libIndex = index
                    state.xmlStatus = 'init'
                    try {
                      Osmd.clear()
                    } catch (error) {}
                    this.loadAndRender()
                    state.libshow = false
                  }}
                />
              ))}
            </CellGroup>
          </Popup> */}
        </NetworkError>
      </div>
    )
  },
})
