/**
 * 曲谱节拍器
 * auth: lsq
 * time: 2022.11.14
 */
import { reactive, watch } from "vue";
import { Howl } from "howler";
import tockAndTick from "/src/constant/tockAndTick.json";
type IOptions = {
	speed: number;
};

export const metronomeData = reactive({
	disable: true,
	initPlayerState: false,
	lineShow: false,
	isClick: false,
	metro: null as unknown as Metronome,
	metroList: [] as number[],
	activeList: [] as number[],
	metroMeasure: [] as any[],
	activeIndex: null as unknown as number,
	activeMetro: {} as any,
});

class Metronome {
	playType = "tick";
	source = null as any; // 创建音频源头
	source1 = null as any;
	source2 = null as any;

	constructor(option?: IOptions) {}
	init(times: any[]) {
		this.calculation(times);
		metronomeData.activeList = [];
	}
	initPlayer() {
		if (!this.source) {
			this.source = this.loadAudio1();
		}
		this.source.volume(metronomeData.disable ? 0 : 1);
		// if (!this.source2) {
		// 	this.source2 = this.loadAudio2();
		// }
		metronomeData.initPlayerState = true;
	}

	// 播放
	sound = (currentTime: number) => {
		let index = -1;
		let activeMetro = -1;
		for (let i = 0; i < metronomeData.metroList.length; i++) {
			const item = metronomeData.metroList[i];

			if (currentTime >= item) {
				// console.log(currentTime , item)
				index = i;
				activeMetro = item;
			} else {
				break;
			}
		}
		if (index > -1 && metronomeData.activeIndex !== index) {
			metronomeData.activeIndex = index;
			// console.log("播放", index);
			// metronomeData.activeMetro = this.getStep(activeMetro);
			// console.log("🚀 ~ metronomeData.activeMetro",metronomeData.activeMetro.measureNumberIndex, metronomeData.activeMetro.index)
			this.playAudio();
			return;
		}
	};
	// 播放
	playAudio = () => {
		if (!metronomeData.initPlayerState) return;
		this.source.play();
	};

	// 切换
	selectPlay() {}

	loadAudio1 = () => {
		return new Howl({
			src: tockAndTick.tick,
		});
	};
	loadAudio2 = () => {
		return new Howl({
			src: tockAndTick.tock,
		});
	};
	getStep(time: number) {
		for (let i = 0; i < metronomeData.metroMeasure.length; i++) {
			const list = metronomeData.metroMeasure[i];
			const item = list.find((n: any) => n.time === time);
			if (item) {
				// console.log('index',item)
				return item;
			}
		}
		return {};
	}

	// 计算 所有的拍子的时间
	calculation(times: any[]) {
		// console.log("🚀 ~ times", times);
		// 1.统计有多少小节
		const measures: any[] = [];
		let xmlNumber = -1;
		let measureListIndex = -1;
		for (let i = 0; i < times.length; i++) {
			const note = times[i];
			const measureNumberXML = note?.timeNote?.measureNumber;
			// console.log("🚀 ~ note?.noteElement?.sourceMeasure", note?.noteElement?.sourceMeasure)
			// console.log("🚀 ~ measureNumberXML", measureNumberXML , xmlNumber)
			// console.log("🚀 ~ measureNumberXML", note)
			if (measureNumberXML > -1) {
				if (measureNumberXML != measureListIndex) {
					const m = {
						measureNumberXML: measureNumberXML,
						numerator: note?.measure?.numerator || 0,
						time: note?.timeNote?.millisecondsPerMeasure,
						stepList: [] as number[],
						notes: [note] as any[],
					};
					xmlNumber++;
					measures[xmlNumber] = m;
					measureListIndex = measureNumberXML;
				} else {
					measures[xmlNumber].notes.push(note);
				}
			}
		}
		// console.log(measures, measures.length);
		const metroList: number[] = [];
		const metroMeasure: any[] = [];
		// 4.按照拍数将时长平均分配
		try {
			for (let i = 0; i < measures.length; i++) {
				const metro: any[] = [];
				const measure = measures[i];
				const calp = 1 / measure.numerator;
				// console.log("🚀 ~ measure.numerator:", measure.numerator)
				const totalMeasureTime = measure.notes.reduce((total: number, note: any) => {
					return total + note?.abcNote?.duration;
				}, 0);
				const step = Math.floor(totalMeasureTime / calp);
				// console.log('🚀 ~ calp:', calp, 'total', totalMeasureTime, 'step', step)
				const startTime = measure.notes[0].timeNote.milliseconds;
				const stepTime = measure.notes[0].timeNote.millisecondsPerMeasure / measure.numerator;
				for (let j = 0; j < measure.numerator; j++) {
					const time = stepTime * j + startTime;
					metroList.push(time);
					metro.push(time)
				}
				// metroMeasure[measure.measureNumberXML] = metro
			}
		} catch (error) {
			console.log(error);
		}
		// console.log(metroList, metroMeasure);
		// 5.得到所有的节拍时间
		metronomeData.metroList = metroList;
		metronomeData.metroMeasure = metroMeasure;
		metronomeData.activeMetro = metroMeasure[0]?.[0] || {};
	}
}

export default Metronome;
