import { reactive } from "vue";
import { IAbc, IMeasure, INote } from "../types";
import { getImage } from "./images";
import { ABC_KEYS, ABC_NOTE_DATA } from "./noteData";
import { TuneObject } from "abcjs";

export const ABC_DATA = {
  /** 音符 */
  types: [
    { name: "全音符", value: "4", icon: "icon-quanyinfu" },
    { name: "2分音符", value: "2", icon: "icon-a-2fenyinfu" },
    { name: "4分音符", value: "", icon: "icon-a-4fenyinfu" },
    { name: "8分音符", value: "/", icon: "icon-a-8fenyinfu" },
    { name: "16分音符", value: "//", icon: "icon-a-16fenyinfu" },
    { name: "32音符", value: "///", icon: "icon-a-32fenyinfu" },
  ],
  /** 休止符 */
  reset: [{ name: "休止符", value: "z", icon: "icon-a-4fenxiuzhifu" }],
  /** 临时升降记号 */
  accidentals: [
    { name: "重降号", value: "__", icon: getImage("icon_2.png") },
    { name: "降号", value: "_", icon: getImage("icon_3.png") },
    { name: "还原号", value: "=", icon: getImage("icon_4.png") },
    { name: "升号", value: "^", icon: getImage("icon_5.png") },
    { name: "重升号", value: "^^", icon: getImage("icon_6.png") },
  ],
  /** 谱号 */
  clef: [
    { name: "低音谱号", value: "K:bass", icon: "icon-puhao-diyinpuhao" },
    { name: "高音谱号", value: "K:treble", icon: "icon-puhao-gaoyinpuhao" },
    { name: "次中音谱号", value: "K:tenor", icon: "icon-puhao-cizhongyinpuhao" },
    { name: "中音谱号", value: "K:alto", icon: "icon-puhao-zhongyinpuhao" },
    { name: "打击乐谱号", value: "K:perc", icon: "icon-puhao-gupu" },
  ],
  /** 调号 */
  key: [
    { name: "C大调", value: "K:C", step: 0, icon: "icon-a-diaohao-cdadiaoaxiaodiao1" },
    { name: "F#大调", value: "K:F#", step: 6, icon: "icon-a-diaohao-fdadiaodxiaodiao" },
    { name: "F大调", value: "K:F", step: 5, icon: "icon-a-diaohao-fdadiaodxiaodiao1" },
    { name: "E大调", value: "K:E", step: 4, icon: "icon-a-diaohao-edadiaocxiaodiao" },
    { name: "Eb大调", value: "K:Eb", step: 3, icon: "icon-a-diaohao-ebdadiaocxiaodiao" },
    { name: "D大调", value: "K:D", step: 2, icon: "icon-a-diaohao-Ddaxiaoexiaodiao" },
    { name: "C#大调", value: "K:C#", step: 1, icon: "icon-a-diaohao-cdadiaoaxiaodiao" },
    { name: "B大调", value: "K:B", step: -1, icon: "icon-a-diaohao-bdadiaogxiaodiao" },
    { name: "Cb大调", value: "K:Cb", step: -1, icon: "icon-a-diaohao-cbdadiaoabxiaodiao" },
    { name: "Db大调", value: "K:Db", step: -1, icon: "icon-a-diaohao-dbdadiaobbxiaodiao" },
    { name: "Bb大调", value: "K:Bb", step: -2, icon: "icon-a-diaohao-bbdadiaogxiaodiao" },
    { name: "A大调", value: "K:A", step: -3, icon: "icon-a-diaohao-Adadiaofxiaodiao" },
    { name: "Ab大调", value: "K:Ab", step: -4, icon: "icon-a-diaohao-abdadiaofxiaodiao" },
    { name: "G大调", value: "K:G", step: -5, icon: "icon-a-diaohao-Gdadiaoexiaodiao" },
    { name: "Gb大调", value: "K:Gb", step: -6, icon: "icon-a-diaohao-gbdadiaoebxiaodiao" },
  ],
  /** 拍号 */
  meter: [
    { name: "4/4", value: "M:4/4", icon: "icon-paihao-44" },
    { name: "2/2", value: "M:2/2", icon: "icon-paihao-22" },
    { name: "2/4", value: "M:2/4", icon: "icon-paihao-24" },
    { name: "3/4", value: "M:3/4", icon: "icon-paihao-34" },
    { name: "3/8", value: "M:3/8", icon: "icon-paihao-38" },
    { name: "6/8", value: "M:6/8", icon: "icon-paihao-68" },
    { name: "9/8", value: "M:9/8", icon: "icon-paihao-98" },
    { name: "12/8", value: "M:12/8", icon: "icon-a-paihao-128" },
  ],
  /** 演奏技法 */
  play: [
    { name: "加强音", value: "!marcato!", icon: getImage("icon_9.png") },
    { name: "重音", value: "!>!", icon: getImage("icon_10.png") },
    { name: "保持音", value: "!tenuto!", icon: getImage("icon_11.png") },
    { name: "断音", value: "!wedge!", icon: getImage("icon_12.png") },
    { name: "花型重复记号", value: "S", icon: "icon-fanfuyutiaoyue-sbiao" },
    { name: "Coda", value: "O", icon: "icon-fanfuyutiaoyue-weisheng" },
    { name: "波音", value: "P", icon: "icon-e1" },
    { name: "逆波音", value: "M", icon: "icon-d1" },
    { name: "换气符号(逗号)", value: "!breath!", icon: "icon-c1" },
    { name: "回音", value: "!turn!", icon: "icon-b" },
    // { name: "逆回音", value: "!turnx!", icon: "icon-b" },
    { name: "颤音", value: "T", icon: "icon-a1" },
    { name: "跳音", value: ".", icon: "icon-a-zoufajihao-duanzouhaoshang" },
    { name: "延迟音记号", value: "!fermata!", icon: "icon-f1" },
  ],
  /** 小节线 */
  bar: [
    { name: "单小节线", value: "|", icon: "icon-xiaojiexian-danxiaojiexian" },
    { name: "双小节线", value: "||", icon: "icon-xiaojiexian-shuangxiaojiexian" },
    { name: "结束线", value: "|]", icon: "icon-xiaojiexian-zhongzhixiaojiexian" },
    { name: "重复线开始", value: "|:", icon: "icon-a-xiaojiexian-zuoqishifanfuhao" },
    { name: "重复线结束", value: ":|", icon: "icon-a-xiaojiexian-youzhongzhifanfuhao" },
    { name: "双重复", value: "::", icon: "icon-xiaojiexian-jieshuyuqishifanfubiaozhi" },
  ],
  /** 连线 */
  tie: [
    { name: "延音线", value: "-", icon: getImage("icon_7.png") }, // 延音必须同音高
    { name: "连音线", value: ["(", ")"], icon: getImage("icon_8.png") }, // 需要是音符和结束音符,最低两个音符
  ],
  /** 8度线 */
  octave: [
    // 暂不支持
    { name: "高8度开始", value: ["!8va(!", "!8va)!"] },
    { name: "低8度", value: ["!8vb(!", "!8vb)!"] },
  ],
  /** 力度记号 */
  dynamics: [
    { name: "极弱", value: "!ppp!", icon: "icon-lidujihao-ppp" },
    { name: "很弱", value: "!pp!", icon: "icon-lidujihao-pp" },
    { name: "弱", value: "!p!", icon: "icon-lidujihao-p" },
    { name: "中弱", value: "!mp!", icon: "icon-lidujihao-mp" },
    { name: "中强", value: "!mf!", icon: "icon-lidujihao-mf" },
    { name: "强", value: "!f!", icon: "icon-lidujihao-f" },
    { name: "很强", value: "!ff!", icon: "icon-lidujihao-ff" },
    { name: "极强", value: "!fff!", icon: "icon-lidujihao-fff" },
    { name: "渐强", value: ["!<(!", "!<)!"], icon: "icon-lidujihao-jianqianghao" }, // 需要是音符范围,最低两个音
    { name: "渐弱", value: ["!>(!", "!>)!"], icon: "icon-lidujihao-jianruohao" }, //需要是音符范围,最低两个音
  ],
  repeat: [
    { name: "第一跳跃", value: "1", icon: "icon-fanfuyutiaoyue-diyitiaoyuehao" },
    { name: "第二跳跃", value: "2", icon: "icon-fanfuyutiaoyue-di2kaifangtiaoyuehao" },
    // { name: "重复3房", value: "3", icon: "" },
    // { name: "重复4房", value: "4", icon: "" },
  ],
  speeds: [
    { name: "60", value: "Q:1/4=60", icon: "" },
    { name: "70", value: "Q:1/4=70", icon: "" },
    { name: "80", value: "Q:1/4=80", icon: "" },
    { name: "90", value: "Q:1/4=90", icon: "" },
    { name: "100", value: "Q:1/4=100", icon: "" },
    { name: "120", value: "Q:1/4=120", icon: "" },
  ],
  slus: [
    { name: "3连音", value: "(3", icon: "" },
    { name: "4连音", value: "(4", icon: "" },
    { name: "5连音", value: "(5", icon: "" },
    { name: "6连音", value: "(6", icon: "" },
    { name: "7连音", value: "(7", icon: "" },
  ],
  /** 3连音等多连音
   * 1. 将连音的音符小括号起来,并在括号前加上数字表示连音的音符数
   */
};

export const settings = reactive({
  /** 光标跟随 音符, 节拍 */
  cursorType: "note" as "note" | "beat",
});

export const createNote = (options: Partial<INote>): INote => {
  return {
    accidental: options.accidental || "",
    content: options.content || "",
    noteType: options.noteType || "",
    clef: options.clef || "",
    play: options.play || [],
    key: options.key || "",
    speed: options.speed || "",
    dynamics: options.dynamics || "",
    dCode: options.dCode || "",
    tie: options.tie || "",
    tCode: options.tCode || "",
    dot: options.dot || "",
    slus: options.slus || "",
    tieline: options.tieline || "",
    segno: options.segno || "",
  };
};

export const createMeasure = (): IMeasure => {
  return {
    notes: [
      createNote({
        content: "z",
        noteType: "4",
      }),
    ],
    barline: "|",
    repeat: "",
    measureNumber: 0,
    celf: "",
    key: "",
    meter: "",
  };
};

interface IRenderMeasuresOption {
  /** 是否生成index */
  hiddenIndex?: boolean;
  showTitle?: boolean;
  showCreator?: boolean;
  jianpu?: boolean;
}
/**
 * 生成小节
 * @param abc
 *
 * @returns
 */
export const renderMeasures = (abc: IAbc, option?: IRenderMeasuresOption) => {
  // console.log("🚀 ~ abc:", abc)
  let wrap = 1;
  let text = `X:1\n`;
  if (option?.jianpu) {
    text += "%%jianpu 1 \n";
  }

  if (option?.showTitle) {
    abc.title && (text += `T:${abc.title}` + "\n");
  }
  if (option?.showCreator) {
    abc.creator && (text += `C:${abc.creator}` + "\n");
  }
  if (!option?.hiddenIndex) {
    text += "%%barnumbers 1" + "\n";
  }

  if (abc.isrhythm === "rhythm") {
    text += "K:perc" + "\n";
  } else {
    abc.celf && (text += abc.celf + "\n");
  }
  abc.meter && (text += abc.meter + "\n");
  abc.minUnit && (text += abc.minUnit + "\n");
  abc.speed && (text += abc.speed + "\n");
  if (abc.key) {
    text += abc.key + " ";

    // text += "style=harmonic";
    if (abc.isrhythm === "rhythm") {
      text += "style=x";
    }
    // text += "style=x";
    // text += "style=triangle";

    text += "\n";
  }
  // text += "V:1 style=jianpu" + "\n";

  const measures = abc.measures;
  for (let i = 0; i < measures.length; i++) {
    const measure = measures[i];
    text += measure.repeat ?? ""; // 重复
    text += measure.meter ?? ""; // 拍号
    for (let j = 0; j < measure.notes?.length; j++) {
      const note = measure.notes[j];
      const playStr = note.play?.join("") ?? "";

      text += note.clef ?? ""; // 谱号
      text += note.key ?? ""; // 调号
      text += note.speed ?? ""; // 速度
      text += note.slus ?? ""; // 3连音
      if (note.tie?.includes("(")) {
        // 连音线 前
        text += note.tie ?? "";
      }
      if (!option?.hiddenIndex) {
        text += `"<${i + "." + j}"`; // 音符 id
      }
      text += playStr ?? ""; // 演奏技法
      text += note.dynamics ?? ""; // 力度符号
      if (abc.isrhythm !== "rhythm") {
        text += note.accidental ?? ""; // 临时升降记号
      }
      if (!note.content.includes("z") && abc.isrhythm === "rhythm") {
        text += "B";
      } else {
        text += note.content ?? ""; // 音符
      }
      // 音符时值
      text += note.noteType ?? "";
      text += note.dot ?? ""; // 点

      text += note.tieline ?? ""; // 延音
      if (note.tie?.includes(")")) {
        // 连音线 后
        text += note.tie ?? "";
      }
      text += note.segno ?? ""; // 分割
    }
    // let _i = i + 1;
    // if (!option?.hiddenIndex) {
    // 	text += `"<${_i}"`;
    // }
    text += measure.barline ?? "";
    if (wrap % 4 === 0) {
      text += "\n";
    }
    wrap++;
  }
  // console.log(text)
  return text;
};

export const getKeyStep = (key: string, oldKey: string, keyType: "inset" | "up" | "down") => {
  let step = 0;
  const _key = ABC_KEYS[oldKey][key];
  if (keyType === "down") {
    step = _key.down;
  } else if (keyType === "up") {
    step = _key.up;
  } else {
    step = Math.abs(_key.up) > Math.abs(_key.down) ? _key.down : _key.up;
  }
  return { step, move: _key.move };
};
export const moveNoteKey = (note: string, moveData: { step: number; move: number }) => {
  let x = -1;
  for (let i = 0; i < ABC_NOTE_DATA.length; i++) {
    const notes = ABC_NOTE_DATA[i];
    if (Array.isArray(notes) && notes.includes(note)) {
      x = i;
      break;
    }
    if (note === notes) {
      x = i;
      break;
    }
  }
  console.log(note, moveData.step, x);
  if (x >= 0) {
    const _note = ABC_NOTE_DATA[x + moveData.step];
    if (Array.isArray(_note)) {
      return _note[moveData.move];
    } else {
      return _note ? _note : note;
    }
  }
  return note;
};

const formateGetData = {
  getNoteType: (duration: number) => {
    const type = 0.25 / duration;
    // console.log(type, duration);
    const noteType = [
      { name: 0.25, value: "4" },
      { name: 0.5, value: "2" },
      { name: 1, value: "" },
      { name: 2, value: "/" },
      { name: 4, value: "//" },
      { name: 8, value: "///" },
    ];
    let _duration = noteType.find((n) => n.name === type)?.value || "";
    const noteDuration: any = {
      "0.046875": "1/6",
      "0.09375": "1/3",
      "0.1875": "2/3",
      "0.375": "3/2",
      "0.75": "3",
    };
    if (_duration === "") {
      _duration = noteDuration[duration] || "";
    }
    return _duration;
  },
  getSegno(ele: any, nextEle: any) {
    let segno = " ";
    if (nextEle && ele) {
      // console.log("🚀 ~ nextEle:", nextEle)
      if (nextEle?.abselem?.beam?.elems && Array.isArray(nextEle.abselem.beam.elems)) {
        const _ele = nextEle.abselem.beam.elems.find((n: any) => n.abcelem.startChar === ele.startChar);
        // console.log("🚀 ~ elems:", _ele)
        if (_ele) {
          segno = "";
        }
      }
    }
    return segno;
  },
};

export const formateAbc = (visualObj: TuneObject, option: any) => {
  let speed = visualObj?.metaText?.tempo?.bpm ? visualObj.metaText.tempo.bpm : visualObj.getBpm();
  const abc = {
    celf: "K:treble",
    minUnit: "L:1/4",
    meter: "M:4/4",
    speed: `Q:1/4=${speed}`,
    key: "K:C",
    visualTranspose: 0,
    subjectCode: option.subjectCode ?? "acoustic_grand_piano",
    title: visualObj?.metaText?.title ?? "",
    creator: visualObj?.metaText?.composer ?? "",
  };
  const list = [];
  let notes = [];
  let measureIndex = 0;

  const get_accidental = (noteItem: INote) => {
    let accidental = "";

    if (noteItem.content.includes("_")) {
      accidental = "_";
    }
    if (noteItem.content.includes("__")) {
      accidental = "__";
    }
    if (noteItem.content.includes("=")) {
      accidental = "=";
    }
    if (noteItem.content.includes("^")) {
      accidental = "^";
    }
    if (noteItem.content.includes("^^")) {
      accidental = "^^";
    }
    return accidental;
  };
  for (let i = 0; i < visualObj.lines.length; i++) {
    const line = visualObj.lines[i];
    if (line.staff) {
      for (let j = 0; j < line.staff.length; j++) {
        const staff = line.staff[j];
        if (i === 0) {
          if (staff.clef) {
            abc.celf = `K:${staff.clef.type}`;
          }
          if (staff.key) {
            abc.key = `K:${staff.key.root}${staff.key.acc}`;
          }
          if (staff.meter?.value?.[0]) {
            abc.meter = `M:${staff.meter.value[0].num}/${staff.meter.value[0].den}`;
          }
        }
        if (staff.voices) {
          let measure = {
            notes: [] as INote[],
            barline: "|",
            repeat: "",
            measureNumber: measureIndex,
            celf: "",
            key: "",
            meter: "",
          };
          for (let k = 0; k < staff.voices.length; k++) {
            const voice = staff.voices[k];
            for (let l = 0; l < voice.length; l++) {
              const element = voice[l];
              const nextElement = voice[l + 1];
              if (element.el_type === "bar") {
                measureIndex++;
                list.push(measure);
                notes = [];
                measure = {
                  notes: [] as INote[],
                  barline: "|",
                  repeat: "",
                  measureNumber: measureIndex,
                  celf: "",
                  key: "",
                  meter: "",
                };
              }
              if (element.el_type === "note") {
                // const abcEle = visualObj.getElementFromChar(element.startChar);
                // console.log("🚀 ~ abcEle:", element);
                let noteItem = {
                  clef: "", //// 谱号
                  key: "", // 调号
                  speed: "", // 速度
                  slus: "", // 3连音
                  tie: "", // 连音线 前,连音线 后
                  content: "", // 音符
                  noteType: formateGetData.getNoteType(element.duration), // 音符时值
                  play: [],
                  dynamics: "", // 力度符号
                  accidental: "", // 临时升降记号
                  dot: "", //附点
                  tieline: "", // 延音线
                  segno: formateGetData.getSegno(element, nextElement), // 分割
                };
                if (element.rest) {
                  noteItem.content = "z";
                } else {
                  noteItem.content = element.pitches?.[0]?.name ?? "";
                }
                noteItem.accidental = get_accidental(noteItem as any);
                if (noteItem.accidental) {
                  noteItem.content = noteItem.content.replace(noteItem.accidental, "");
                }
                const note = createNote(noteItem);
                measure.notes.push(note);
              }
            }
          }
        }
      }
    }
  }
  console.log(measureIndex, list);
  return {
    ...abc,
    measures: list,
  };
};
