import { PropType, computed, defineComponent, nextTick, onBeforeMount, onMounted, reactive } from "vue";
import styles from "./index.module.less";
import icons from "./image/icons.json";
import { FIGNER_INSTRUMENT_DATA, IFIGNER_INSTRUMENT_Note } from "/src/view/figner-preview";
import {
	ITypeFingering,
	IVocals,
	getFingeringConfig,
	subjectFingering,
} from "/src/view/fingering/fingering-config";
import { Howl } from "howler";
import { storeData } from "/src/store";
import { api_back } from "/src/helpers/communication";
import Hammer from "hammerjs";

export default defineComponent({
	name: "viewFigner",
	emits: ["close"],
	props: {
		isComponent: {
			type: Boolean,
			default: false,
		},
		subject: {
			type: String as PropType<IVocals>,
			default: "",
		},
	},
	setup(props, { emit }) {
		const subject = props.subject || "pan-flute";
		const data = reactive({
			subject: subject,
			realKey: 0,
			notes: [] as IFIGNER_INSTRUMENT_Note[],
			tones: [] as IFIGNER_INSTRUMENT_Note[],
			activeTone: "",
			soundFonts: {} as any,
			viewIndex: 0,
			noteAudio: null as unknown as Howl,
			transform: {
				scale: 1,
				x: 0,
				y: 0,
				startScale: 1,
				startX: 0,
				startY: 0,
				transition: "",
			},
		});
		const fingerData = reactive({
			relationshipIndex: 0,
			subject: null as unknown as ITypeFingering,
			fingeringInfo: subjectFingering(data.subject),
		});
		const getNotes = () => {
			const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
			if (fignerData) {
				data.tones = fignerData.tones || [];
				if (data.tones.length) {
					data.activeTone = data.tones[0].realName;
				}
				setNotes();
			}
		};
		const setNotes = () => {
			const fignerData = FIGNER_INSTRUMENT_DATA[data.subject as keyof typeof FIGNER_INSTRUMENT_DATA];
			if (fignerData) {
				data.notes = fignerData[`list${data.activeTone}`];
			}
		};
		const getFingeringData = async () => {
			const subject: any = data.subject + (data.viewIndex === 0 ? "" : data.viewIndex);
			// console.log("🚀 ~ subject:", subject);
			fingerData.subject = await getFingeringConfig(subject);
		};
		const getSounFonts = () => {
			const pathname = /(192|localhost)/.test(location.origin) ? "/" : location.pathname;
			for (let i = 0; i < data.notes.length; i++) {
				const note = data.notes[i];
				// console.log("🚀 ~ note:", i)
				let url = `${pathname}soundfonts/${data.subject}/`;
				url += note.realName;
				url += ".mp3";
				const noteAudio = new Howl({
					src: url,
					loop: true,
				});
				data.soundFonts[note.realKey] = noteAudio;
			}
			// console.log("🚀 ~ data.soundFonts:", data.soundFonts);
		};
		onBeforeMount(() => {
			getNotes();
			getFingeringData();
			getSounFonts();
		});

		const noteClick = (item: IFIGNER_INSTRUMENT_Note) => {
			if (data.noteAudio) {
				data.noteAudio.stop();
				if (data.realKey === item.realKey) {
					data.realKey = 0;
					data.noteAudio = null as unknown as Howl;
					return;
				}
			}
			data.realKey = item.realKey;
			data.noteAudio = data.soundFonts[item.realKey];
			data.noteAudio.play();
		};

		/** 返回 */
		const handleBack = () => {
			if (data.noteAudio) {
				data.noteAudio.stop();
				data.realKey = 0;
				data.noteAudio = null as unknown as Howl;
			}
			if (props.isComponent) {
				console.log("关闭");
				emit("close");
				return;
			}
			// 不在APP中,
			if (!storeData.isApp) {
				window.close();
				return;
			}
			api_back();
		};

		onMounted(() => {
			loadElement();
		});
		const loadElement = () => {
			const fingeringContainer = document.getElementById("fingeringContainer");
			// console.log("🚀 ~ fingeringContainer:", fingeringContainer);
			const mc = new Hammer.Manager(fingeringContainer as HTMLElement);
			mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
			mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get("pan")]);
			// mc.get("pan").set({ direction: Hammer.DIRECTION_ALL });
			// mc.get("pinch").set({ enable: true });
			mc.on("panstart pinchstart", function (ev) {
				data.transform.transition = "";
			});
			mc.on("panmove pinchmove", function (ev) {
				if (ev.type === "pinchmove") {
					// console.log("🚀 ~ ev:", ev.type, ev.scale, ev.deltaX, ev.deltaY);
					data.transform.scale = ev.scale * data.transform.startScale;
					data.transform.x = data.transform.startX + ev.deltaX;
					data.transform.y = data.transform.startY + ev.deltaY;
				}
				if (ev.type === "panmove") {
					// console.log("🚀 ~ ev:", ev.type, ev.deltaX, ev.deltaY);
					data.transform.x = data.transform.startX + ev.deltaX;
					data.transform.y = data.transform.startY + ev.deltaY;
				}
			});
			//
			mc.on("hammer.input", function (ev) {
				// console.log("🚀 ~ ev:", ev.type, ev.isFinal);
				if (ev.isFinal) {
					data.transform.startScale = data.transform.scale;
					data.transform.startX = data.transform.x;
					data.transform.startY = data.transform.y;
				}
			});
		};
		const resetElement = () => {
			data.transform.transition = "all 0.3s";
			nextTick(() => {
				data.transform.scale = 1;
				data.transform.x = 0;
				data.transform.y = 0;
				data.transform.startScale = 1;
				data.transform.startX = 0;
				data.transform.startY = 0;
			});
		};
		return () => {
			const relationship = fingerData.subject?.relationship?.[data.realKey] || [];
			const rs: number[] = Array.isArray(relationship[1])
				? relationship[fingerData.relationshipIndex]
				: relationship;
			const canTizhi = Array.isArray(relationship[1]);
			return (
				<div class={styles.fingerBox}>
					<div class={styles.head}>
						<div class={styles.left}>
							<button
								class={[styles.backBtn, data.subject === "pan-flute" && styles.backRight]}
								onClick={() => handleBack()}
							>
								<img src={icons.icon_back} />
							</button>
							{data.subject === "pan-flute" && (
								<div
									class={styles.baseBtn}
									onClick={() => {
										data.viewIndex++;
										if (data.viewIndex > 2) {
											data.viewIndex = 0;
										}
										getFingeringData();
									}}
								>
									切换视图
								</div>
							)}
						</div>
						<div class={styles.rightBtn}>
							<div class={[styles.item]} onClick={() => resetElement()}>
								<img src={icons.icon_2_0} />
								<span>还原</span>
							</div>
							<div class={[styles.item]}>
								<img src={icons.icon_2_1} />
								<span>小技巧</span>
							</div>
						</div>
					</div>
					<div id="fingeringContainer" class={styles.fingerContent}>
						<div
							style={{
								transform: `translate3d(${data.transform.x}px,${data.transform.y}px,0px) scale(${data.transform.scale})`,
								transition: data.transform.transition,
							}}
							class={[styles.fingeringContainer]}
						>
							<div class={styles.imgs}>
								<img src={fingerData.subject?.json?.full} />
								{rs.map((key: number | string, index: number) => {
									const nk: string = typeof key === "string" ? key.replace("active-", "") : String(key);
									return <img data-index={nk} src={fingerData.subject?.json?.[nk]} />;
								})}
							</div>

							<div
								class={[styles.tizhi, canTizhi && styles.canDisplay]}
								onClick={() =>
									(fingerData.relationshipIndex = fingerData.relationshipIndex === 0 ? 1 : 0)
								}
							>
								替指
							</div>
						</div>

						<div class={styles.tones} style={{display: data.tones.length ? '' : 'none'}}>
							{data.tones.map((tone: IFIGNER_INSTRUMENT_Note) => {
								const steps = new Array(Math.abs(tone.step)).fill(1);
								return (
									<div
										draggable={false}
										class={styles.note}
										onClick={() => {
											data.activeTone = tone.realName;
											setNotes();
										}}
									>
										{data.activeTone === tone.realName ? (
											<img draggable={false} src={icons.icon_btn_ylow} />
										) : (
											<img draggable={false} src={icons.icon_btn_blue} />
										)}

										<div class={[styles.noteKey, data.activeTone === tone.realName && styles.keyActive]}>
											{tone.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}

											<div class={styles.noteName}>
												<sup>{tone.mark && (tone.mark === "rise" ? "#" : "b")}</sup>
												{tone.key}
											</div>
											{tone.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
										</div>
									</div>
								);
							})}
						</div>
					</div>
					<div class={styles.notes}>
						{/* <Button>
							<Icon name="arrow-left" />
						</Button> */}
						<div class={styles.noteContent}>
							<div class={styles.noteBox}>
								{data.notes.map((note: IFIGNER_INSTRUMENT_Note) => {
									const steps = new Array(Math.abs(note.step)).fill(1);
									return (
										<div draggable={false} class={styles.note} onClick={() => noteClick(note)}>
											{data.realKey === note.realKey ? (
												<img draggable={false} src={icons.icon_btn_ylow} />
											) : (
												<img draggable={false} src={icons.icon_btn_blue} />
											)}

											<div class={[styles.noteKey, data.realKey === note.realKey && styles.keyActive]}>
												{note.step > 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}

												<div class={styles.noteName}>
													<sup>{note.mark && (note.mark === "rise" ? "#" : "b")}</sup>
													{note.key}
												</div>
												{note.step < 0 ? steps.map((n) => <span class={styles.dot}></span>) : null}
											</div>
										</div>
									);
								})}
							</div>
						</div>
						{/* <Button size="small" >
							<Icon name="arrow" />
						</Button> */}
					</div>
				</div>
			);
		};
	},
});
