// import { isSpecialMark, isSpeedKeyword, isGradientWords, GRADIENT_SPEED_RESET_TAG } from "./speed-tag"

// import { isSpecialMark, isSpeedKeyword, isGradientWords, GRADIENT_SPEED_RESET_TAG } from "./speed-tag"

export class StringUtil {
   public static StringContainsSeparatedWord(str: string, wordRegExString: string, ignoreCase = false): boolean {
      const regExp = new RegExp("( |^)" + wordRegExString + "([ .]|$)", ignoreCase ? "i" : undefined)
      return regExp.test(str)
   }
}

export const formatXML = (xml: string): string => {
   if (!xml) return ""
   const xmlParse = new DOMParser().parseFromString(xml, "text/xml")
   const measures: any = xmlParse.getElementsByTagName("measure")
   // const repeats: any = Array.from(xmlParse.querySelectorAll('repeat'))
   // 处理重复小节信息
   // let speed = -1
   let beats = -1
   let beatType = -1
   // 小节中如果没有节点默认为休止符
   for (const measure of measures) {
      if (beats === -1 && measure.getElementsByTagName("beats").length) {
         beats = parseInt(measure.getElementsByTagName("beats")[0].textContent || "4")
      }
      if (beatType === -1 && measure.getElementsByTagName("beat-type").length) {
         beatType = parseInt(measure.getElementsByTagName("beat-type")[0].textContent || "4")
      }
      // if (speed === -1 && measure.getElementsByTagName('per-minute').length) {
      //   speed = parseInt(measure.getElementsByTagName('per-minute')[0].textContent || this.firstLib?.speed)
      // }
      const divisions = parseInt(measure.getElementsByTagName("divisions")[0]?.textContent || "256")
      if (measure.getElementsByTagName("note").length === 0) {
         const forwardTimeElement = measure.getElementsByTagName("forward")[0]?.getElementsByTagName("duration")[0]
         if (forwardTimeElement) {
            forwardTimeElement.textContent = "0"
         }
         measure.innerHTML =
            measure.innerHTML +
            `
        <note>
          <rest measure="yes"/>
          <duration>${divisions * beats}</duration>
          <voice>1</voice>
          <type>whole</type>
        </note>`
      }
   }
   return new XMLSerializer().serializeToString(xmlParse)
}

export const onlyVisible = (xml: string, partIndex: number): string => {
   if (!xml) return ""
   const xmlParse = new DOMParser().parseFromString(xml, "text/xml")
   const partList = xmlParse.getElementsByTagName("part-list")?.[0]?.getElementsByTagName("score-part") || []
   // @typescript-eslint/no-unused-vars
   const partListNames = Array.from(partList).map(item => item.getElementsByTagName("part-name")?.[0].textContent || "")
   const parts: any = xmlParse.getElementsByTagName("part")
   // const firstTimeInfo = parts[0]?.getElementsByTagName('metronome')[0]?.parentElement?.parentElement?.cloneNode(true)
   const part: any = parts[0]
   const firstMeasures = [...part.getElementsByTagName("measure")]
   const metronomes = [...part.getElementsByTagName("metronome")]
   //  const words = [...part.getElementsByTagName("words")]
   //  const codas = [...part.getElementsByTagName("coda")]
   //  const rehearsals = [...part.getElementsByTagName("rehearsal")]

   /** 第一分谱如果是约定的配置分谱则跳过 */
   if (partListNames[0]?.toLocaleUpperCase?.() === "COMMON") {
      partIndex++
      partListNames.shift()
   }
   const visiblePartInfo = partList[partIndex]
   // console.log(visiblePartInfo, partIndex)
   if (visiblePartInfo) {
      const id = visiblePartInfo.getAttribute("id")
      Array.from(parts).forEach((part: any) => {
         if (part && part.getAttribute("id") !== id) {
            part.parentNode?.removeChild(part)
            // 不等于第一行才添加避免重复添加
         } else if (part && part.getAttribute("id") !== "P1") {
            // 速度标记仅保留最后一个
            const metronomeData: {
               [key in string]: Element
            } = {}
            for (let i = 0; i < metronomes.length; i++) {
               const metronome = metronomes[i]
               const metronomeContainer = metronome.parentElement?.parentElement?.parentElement
               if (metronomeContainer) {
                  const index = firstMeasures.indexOf(metronomeContainer)
                  metronomeData[index] = metronome
               }
            }
            Object.values(metronomeData).forEach(metronome => {
               const metronomeContainer: any = metronome.parentElement?.parentElement
               const parentMeasure: any = metronomeContainer?.parentElement
               const measureMetronomes = [...(parentMeasure?.childNodes || [])]
               const metronomesIndex = metronomeContainer ? measureMetronomes.indexOf(metronomeContainer) : -1
               // console.log(parentMeasure)
               if (parentMeasure && metronomesIndex > -1) {
                  const index = firstMeasures.indexOf(parentMeasure)
                  const activeMeasure = part.getElementsByTagName("measure")[index]
                  setElementNoteBefore(metronomeContainer, parentMeasure, activeMeasure)
               }
            })
         }

         // 最后一个小节的结束线元素不在最后 调整
         if (part && part.getAttribute("id") === id) {
            const barlines = part.getElementsByTagName("barline")
            const lastParent = barlines[barlines.length - 1]?.parentElement
            if (lastParent?.lastElementChild?.tagName !== "barline") {
               const children: any = lastParent?.children || []
               for (const el of children) {
                  if (el.tagName === "barline") {
                     // 将结束线元素放到最后
                     lastParent?.appendChild(el)
                     break
                  }
               }
            }
         }
      })
      Array.from(partList).forEach(part => {
         if (part && part.getAttribute("id") !== id) {
            part.parentNode?.removeChild(part)
         }
      })
      // 处理装饰音问题
      // const notes = xmlParse.getElementsByTagName("note")
      // const getNextvNoteDuration = (i: number) => {
      //   let nextNote = notes[i + 1]
      //   // 可能存在多个装饰音问题，取下一个非装饰音时值
      //   for (let index = i index < notes.length index++) {
      //     const note = notes[index]
      //     if (!note.getElementsByTagName("grace")?.length) {
      //       nextNote = note
      //       break
      //     }
      //   }
      //   const nextNoteDuration = nextNote?.getElementsByTagName("duration")[0]
      //   return nextNoteDuration
      // }
      // Array.from(notes).forEach((note, i) => {
      //   const graces = note.getElementsByTagName("grace")
      //   if (graces && graces.length) {
      //     // if (i !== 0) {
      //     // note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
      //     // }
      //   }
      // })
   }
   // console.log(xmlParse)
   return new XMLSerializer().serializeToString(appoggianceFormate(xmlParse))
}

// 倚音后连音线
export const appoggianceFormate = (xmlParse: Document): Document => {
   if (!xmlParse) return xmlParse
   const graces: any = xmlParse.querySelectorAll("grace")
   if (!graces.length) return xmlParse
   const getNextElement = (el: HTMLElement): HTMLElement => {
      if (el.querySelector("grace")) {
         return getNextElement(el?.nextElementSibling as HTMLElement)
      }
      return el
   }
   for (const grace of graces) {
      const notations = grace.parentElement?.querySelector("notations")
      if (notations && notations.querySelectorAll("slur").length > 1) {
         const nextEle: Element = getNextElement(grace.parentElement?.nextElementSibling as HTMLElement)
         if (nextEle && nextEle.querySelectorAll("slur").length > 0) {
            const slurNumber = Array.from(nextEle.querySelector("notations")?.children || []).map((el: Element) => {
               return el.getAttribute("number")
            })
            const slurs = notations.querySelectorAll("slur")
            for (const nota of slurs) {
               if (!slurNumber.includes(nota.getAttribute("number"))) {
                  nextEle.querySelector("notations")?.appendChild(nota)
               }
            }
         }
      }
   }
   return xmlParse
}

/**
 * 添加第一分谱信息至当前分谱
 * @param ele 需要插入的元素
 * @param fitstParent 合奏谱第一个分谱
 * @param parent 需要添加的分谱
 */
const setElementNoteBefore = (ele: Element, fitstParent: Element, parent?: Element | null) => {
   let noteIndex = 0
   if (!fitstParent) {
      return
   }
   for (let index = 0; index < fitstParent.childNodes.length; index++) {
      const element = fitstParent.childNodes[index]
      if (element.nodeName === "note") {
         noteIndex++
      }
      if (element === ele) {
         break
      }
   }
   if (noteIndex === 0 && parent) {
      parent.insertBefore(ele, parent.childNodes[0])
      return
   }
   if (parent && parent.childNodes.length > 0) {
      let noteIndex2 = 0
      const notes = Array.from(parent.childNodes).filter(child => child.nodeName === "note")
      const lastNote = notes[notes.length - 1]
      if (noteIndex >= notes.length && lastNote) {
         parent.insertBefore(ele, parent.childNodes[Array.from(parent.childNodes).indexOf(lastNote)])
         return
      }
      for (let index = 0; index < notes.length; index++) {
         const element = notes[index]
         if (element.nodeName === "note") {
            noteIndex2 = noteIndex2 + 1
            if (noteIndex2 === noteIndex) {
               parent.insertBefore(ele, element)
               break
            }
         }
      }
   }
   // console.log(noteIndex, parent)
}

/**
 * 检查传入文字是否为重复关键词
 * @param text 总谱xml
 * @returns 是否是重复关键词
 */
export const isRepeatWord = (text: string): boolean => {
   if (text) {
      const innerText = text.toLocaleLowerCase()
      const dsRegEx = "d\\s?\\.s\\."
      const dcRegEx = "d\\.\\s?c\\."

      return (
         innerText === "@" ||
         StringUtil.StringContainsSeparatedWord(innerText, dsRegEx + " al fine", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, dsRegEx + " al coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, dcRegEx + " al fine", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, dcRegEx + " al coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, dcRegEx) ||
         StringUtil.StringContainsSeparatedWord(innerText, "da\\s?capo", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, dsRegEx, true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "dal\\s?segno", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "al\\s?coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "to\\s?coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "a (la )?coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "fine", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "coda", true) ||
         StringUtil.StringContainsSeparatedWord(innerText, "segno", true)
      )
   }
   return false
}

/** 从xml中获取自定义信息，并删除多余的字符串 */
export const getCustomInfo = (xml: string): any => {
   const data = {
      showSpeed: true,
      parsedXML: xml
   }
   const xmlParse = new DOMParser().parseFromString(xml, "text/xml")
   const words: any = xmlParse.getElementsByTagName("words")
   for (const word of words) {
      if (word && word.textContent?.trim() === "隐藏速度") {
         data.showSpeed = false
         word.textContent = ""
      }
      if (word && word.textContent?.trim() === "@") {
         word.textContent = "segno"
      }
   }
   data.parsedXML = new XMLSerializer().serializeToString(xmlParse)
   return data
}
