import { defineComponent, ref, Ref } from 'vue'
// import opensheetmusicdisplay from 'opensheetmusicdisplay'
// const OpenSheetMusicDisplay = opensheetmusicdisplay.OpenSheetMusicDisplay
// @ts-ignore
// import { OpenSheetMusicDisplay } from '/opensheetmusicdisplay/src/OpenSheetMusicDisplay/OpenSheetMusicDisplay'
// import { TransposeCalculator } from '/opensheetmusicdisplay/src/Plugins/Transpose/TransposeCalculator'
// // @ts-ignore
import { OpenSheetMusicDisplay } from '/osmd-extended/src'
// import runtime from '/src/pages/detail/runtime'
import detailState from '/src/pages/detail/state'
import { formatZoom } from '/src/helpers/utils'
import event from './event'
import styles from './index.module.less'

const container: Ref = ref(null)

let osmd: any = null

export default defineComponent({
  name: 'music-score',
  props: {
    score: {
      type: String,
      default: '',
    },
    showPartNames: {
      type: Boolean,
      default: false,
    },
    onRerender: {
      type: Function,
      default: () => {},
    },
    opotions: {
      type: Object,
      default: () => {},
    },
    EngravingRules: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      osmd: null as any,
      loading: false,
    }
  },
  watch: {
    score() {
      this.loadRender()
    },
  },
  methods: {
    async loadRender() {
      this.loading = true
      if (this.score) {
        try {
          await osmd.load(this.score)
          // if (osmd.graphic.musicSheet.instruments[0]?.playbackTranspose) {
          // osmd.TransposeCalculator = new TransposeCalculator()
          // osmd.sheet.Transpose = osmd.graphic.musicSheet.instruments[0]?.playbackTranspose
          // await osmd.updateGraphic()
          // }
          // osmd.updateGraphic()
          osmd.zoom = formatZoom()
          await osmd.render()
          this.onRerender(osmd)
        } catch (error) {
          console.log(error)
          this.onRerender(null)
        }
        // osmd.zoom = 0.95

        // this.$forceUpdate()
      }
      event.emit('loaded')
      this.loading = false
    },
    noteClickEvent(evt: TouchEvent): any {
      event.emit('container-click', evt)
      const path = (evt as any).path || (evt.composedPath && evt.composedPath())
      for (const el of path) {
        if (el.classList && el.classList.contains('vf-stavenote')) {
          event.emit('click', evt, el)
        }
      }
    },
  },
  beforeUnmount() {
    // container.value.removeEventListener('click', this.noteClickEvent, false)
    container.value.removeEventListener('touchstart', this.noteClickEvent, false)
  },
  async mounted() {
    // container.value.addEventListener('click', this.noteClickEvent, false)
    container.value.addEventListener('touchstart', this.noteClickEvent, false)

    osmd = await new OpenSheetMusicDisplay(container.value, {
      followCursor: false,
      autoResize: true,
      drawSubtitle: false,
      drawTitle: false,
      autoBeam: true,
      drawMetronomeMarks: false,
      drawMeasureNumbers: false,
      drawComposer: false,
      drawLyricist: false,
      drawPartNames: this.showPartNames,
      ...this.opotions,
    })
    // osmd.EngravingRules.UseJustifiedBuilder = false
    osmd.EngravingRules.CompactMode = true // 页面顶部底部间距
    // osmd.EngravingRules.DYSlursStartingAtSameStaffEntryYOffset = 2
    osmd.EngravingRules.DYMinNoteWidth = 3
    // osmd.EngravingRules.WedgePlacementBelowY = 4
    // osmd.EngravingRules.LyricUnderscoreLineWidth = 0.12 // 1------ 线粗细
    osmd.EngravingRules.VoiceSpacingMultiplierVexflow = 0.65
    osmd.EngravingRules.VoiceSpacingAddendVexflow = 2.0

    // tight rendering mode, lower margins and safety distances between systems, staffs etc. may cause overlap.
    // these options can afterwards be finetuned by setting osmd.rules.BetweenStaffDistance for example
    osmd.EngravingRules.MinSkyBottomDistBetweenStaves = 2.0 // default 1.0. this can cause collisions with slurs and dynamics sometimes
    osmd.EngravingRules.MinSkyBottomDistBetweenSystems = 2.0 // default 5.0
    // note that osmd.EngravingRules === osmd.rules, since it's passed as a reference

    osmd.EngravingRules.MinimumStaffLineDistance = 4.0
    osmd.EngravingRules.BetweenStaffDistance = 2.5
    osmd.EngravingRules.StaffDistance = 3.5
    osmd.EngravingRules.MinimumDistanceBetweenSystems = 1
    // osmd.EngravingRules.PageTopMargin = 0.0; // see osmd.EngravingRules.PageTopMarginNarrow used in compact mode
    osmd.EngravingRules.PageBottomMargin = 0.0
    osmd.EngravingRules.PageLeftMargin = 2.0
    osmd.EngravingRules.PageRightMargin = 2.0
    osmd.EngravingRules.PageTopMarginNarrow = 3.0
    osmd.EngravingRules.WedgeEndDistanceBetweenTimestampsFactor = 1
    osmd.EngravingRules.RehearsalMarkXOffset = -18
    osmd.EngravingRules.RehearsalMarkYOffset = 10

    osmd.EngravingRules.DYWorkId = detailState.activeDetail?.parentCategoriesId || 0

    // osmd.EngravingRules.PickupMeasureWidthMultiplier = 1.8

    for (const key in this.EngravingRules) {
      if (Object.prototype.hasOwnProperty.call(this.EngravingRules, key)) {
        const item = this.EngravingRules[key]
        osmd.EngravingRules[key] = item
      }
    }

    this.loadRender()
  },
  render() {
    return <div class={styles.container} ref={container}></div>
  },
})
