import { defineComponent, nextTick } 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'

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 this.osmd.load(this.score)
          // if (this.osmd.graphic.musicSheet.instruments[0]?.playbackTranspose) {
            // this.osmd.TransposeCalculator = new TransposeCalculator()
            // this.osmd.sheet.Transpose = this.osmd.graphic.musicSheet.instruments[0]?.playbackTranspose
            // await this.osmd.updateGraphic()
          // }
          // this.osmd.updateGraphic()
          this.osmd.zoom = formatZoom()
          await this.osmd.render()
          this.onRerender(osmd)
        } catch (error) {
          console.log(error)
          this.onRerender(null)
        }
        // this.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() {
    // this.$refs.container.removeEventListener('click', this.noteClickEvent, false)
    this.$refs.container?.removeEventListener('touchstart', this.noteClickEvent, false)
  },
  async mounted() {
    console.log(this.$refs.container)
    // this.$refs.container.addEventListener('click', this.noteClickEvent, false)
    this.$refs.container.addEventListener('touchstart', this.noteClickEvent, false)
    await nextTick()
    this.osmd = await new OpenSheetMusicDisplay(this.$refs.container, {
      followCursor: false,
      autoResize: true,
      drawSubtitle: false,
      drawTitle: false,
      autoBeam: true,
      drawMetronomeMarks: false,
      drawMeasureNumbers: false,
      drawComposer: false,
      drawLyricist: false,
      drawPartNames: this.showPartNames,
      ...this.opotions,
    })
    // this.osmd.EngravingRules.UseJustifiedBuilder = false
    this.osmd.EngravingRules.CompactMode = true // 页面顶部底部间距
    // this.osmd.EngravingRules.DYSlursStartingAtSameStaffEntryYOffset = 2
    this.osmd.EngravingRules.DYMinNoteWidth = 3
    // this.osmd.EngravingRules.WedgePlacementBelowY = 4
    // this.osmd.EngravingRules.LyricUnderscoreLineWidth = 0.12 // 1------ 线粗细
    this.osmd.EngravingRules.VoiceSpacingMultiplierVexflow = 0.65;
    this.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 this.osmd.rules.BetweenStaffDistance for example
    this.osmd.EngravingRules.MinSkyBottomDistBetweenStaves = 2.0; // default 1.0. this can cause collisions with slurs and dynamics sometimes
    this.osmd.EngravingRules.MinSkyBottomDistBetweenSystems = 2.0; // default 5.0
    // note that this.osmd.EngravingRules === this.osmd.rules, since it's passed as a reference

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

    // this.osmd.rules.RehearsalMarkXOffsetSystemStartMeasure = -20;
    this.osmd.rules.RehearsalMarkXOffset = -18;
    this.osmd.rules.RehearsalMarkYOffset = 10;

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

    // this.osmd.EngravingRules.PickupMeasureWidthMultiplier = 1.8

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

    console.log(osmd, this.$refs.container)
    this.loadRender()
  },
  render() {
    return (
      <div class={styles.container} ref="container"></div>
    )
  }
})
