import { closeToast, showToast } from "vant";
import { reactive } from "vue";
import { OpenSheetMusicDisplay } from "../osmd-extended/src";
import { metronomeData } from "./helpers/metronome";
import { GradualNote, GradualTimes, GradualVersion } from "./type";
import { handleEndEvaluat, handleStartEvaluat } from "./view/evaluating";
import { IFingering } from "src/view/fingering/fingering-config";
import { handleStartTick } from "./view/tick";
import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate } from "./view/audio-list";
import { toggleFollow } from "./view/follow-practice";
import { browser, setStorageSpeed } from "./utils";

/** 入门 | 进阶 | 大师 */
export type IDifficulty = "BEGINNER" | "ADVANCED" | "PERFORMER";
/** 渲染类型: 五线谱,简谱 */
export enum EnumMusicRenderType {
	/** 五线谱 */
	staff = "staff",
	/** 简谱 */
	firstTone = "firstTone",
	/** 固定音高 */
	fixedTone = "fixedTone"
}
export const musicscoresettingKey = "musicscoresetting";
/** 有声音的是那个音源 */
export type IPlayState = "music" | "background"
/** 播放状态 */
export type IAudioState = "play" | "paused"

/** 来源 */
export enum IPlatform {
	APP = "APP",
	PC = "PC"
}

const state = reactive({
	/** 来源 : PC , app */
	platform: '' as IPlatform,
	appName: "" as "GYM" | "COLEXIU",
	musicRenderType: EnumMusicRenderType.staff as EnumMusicRenderType,
	/**曲谱是否渲染完成 */
	musicRendered: false,
	/** 当前曲谱数据ID, 和曲谱ID不一致 */
	detailId: "",
	/** 曲谱资源URL */
	xmlUrl: "",
	/** 声部ID */
	subjectId: 0 as number,
	/** 分类ID */
	categoriesId: 0,
	/** 分类名称 */
	categoriesName: "",
	/** 是否支持评测 */
	enableEvaluation: true,
	/** 是否支持转谱 */
	enableNotation: false,
	/** 曲谱ID */
	examSongId: "",
	/** 曲谱名称 */
	examSongName: "",
	/** 扩展字段 */
	extConfigJson: {} as any,
	/** 扩展样式字段 */
	extStyleConfigJson: {} as any,
	/** 是否开启节拍器 */
	isOpenMetronome: false,
	/** 是否显示指法 */
	isShowFingering: false,
	/** 原音 */
	music: "",
	/** 伴奏 */
	accompany: "",
	/** midiURL */
	midiUrl: "",
	/** 父分ID */
	parentCategoriesId: 0,
	/** 资源类型: mp3 | midi */
	playMode: "MP3" as "MP3" | "MIDI",
	/** 设置的速度 */
	speed: 0,
	/** 曲谱音频正常的速度 */
	originSpeed: 0,
	/** 分轨名称 */
	track: "",
	/** 当前显示声部索引 */
	partIndex: 0,
	/** 是否需要节拍器 */
	needTick: false,
	/** 曲谱实例 */
	osmd: null as unknown as OpenSheetMusicDisplay,
	/**是否是特殊乐谱类型, 主要针对管乐迷  */
	isSpecialBookCategory: false,
	/** 播放状态 */
	playState: "paused" as IAudioState,
	/** 播放结束状态 */
	playEnd: false,
	/** 播放那个: 原音,伴奏 */
	playSource: "music" as IPlayState,
	/** 播放进度 */
	playProgress: 0,
	/** 激活的note index */
	activeNoteIndex: 0,
	/** 激活的小节 */
	activeMeasureIndex: 0,
	/** 选段状态 */
	sectionStatus: false,
	/** 选段数据 */
	section: [] as any[],
	/** 选段背景 */
	sectionBoundingBoxs: [] as any[],
	/** 开启选段预备 */
	isOpenPrepare: false,
	/** 选段预备 */
	sectionFirst: null as any,
	/** 音符数据 */
	times: [] as any[],
	/** 播放模式 */
	modeType: "practise" as "practise" | "follow" | "evaluating",
	/** 设置 */
	setting: {
		/** 效音提醒 */
		soundEffect: true,
		/** 护眼模式 */
		eyeProtection: false,
		/** 摄像头 */
		camera: false,
		/** 摄像头透明度 */
		cameraOpacity: 70,
		/** 循环播放 */
		repeatAutoPlay: true,
		/** 显示指法 */
		displayFingering: true,
		/** 显示光标 */
		displayCursor: true,
		/** 频率 */
		frequency: 442,
		/** 评测难度 */
		evaluationDifficulty: "ADVANCED" as IDifficulty,
		/** 保存到相册 */
		saveToAlbum: false,
		/** 开启伴奏 */
		enableAccompaniment: true,
		/** 反应时间 */
		reactionTimeMs: 0,
	},
	/** 节拍器的时间 */
	fixtime: 0,
	/** 指法信息 */
	fingeringInfo: {} as IFingering,
	/** 滚动容器的ID */
	scrollContainer: "musicAndSelection",
	/** 是否是打击乐 */
	isPercussion: false,
	/** 是否重复节拍器的时间 */
	repeatedBeats: 0,
	/**当前曲谱中所有声部名字 */
	partListNames: [] as string[],
	/** 渐变速度信息 */
	gradual: [] as GradualNote[],
	/** 渐变速度版本 */
	gradualVersion: GradualVersion.BASE as GradualVersion,
	/** 渐变时间信息 */
	gradualTimes: null as GradualTimes,
	/** 单声部多声轨 */
	multitrack: 0,
	/** 缩放 */
	zoom: 0.8,
	/** 渲染曲谱比例 */
	musicZoom: 1,
	/** 练习,评测是否是选段模式 */
	isSelectMeasureMode: false,
	/** 是否是评分显示 */
	isReport: false
});
const browserInfo = browser()
let offset_duration = 0
/** 自定义数据 */
export const customData = reactive({
	/** 自定义音符时值 */
	customNoteRealValue: [] as any,
	/** 自定义音符按读取到的时值 */
	customNoteCurrentTime: false
})
/** 在渲染前后计算光标应该走到的音符 */
const setStep = () => {
	if (state.playState !== "play") {
		console.log("暂停播放");
		return;
	}
	let startTime = Date.now();
	requestAnimationFrame(() => {
		const endTime = Date.now();
		// 渲染时间大于16.6,就会让页面卡顿, 如果渲染时间大与16.6就下一个渲染帧去计算
		if (endTime - startTime < 16.7) {
			handlePlaying();
			setStep();
		} else {
			setTimeout(() => {
				handlePlaying();
				setStep();
			}, 16.7)
		}
		
	});
};
/** 开始播放 */
export const onPlay = () => {
	console.log("开始播放");
	state.playEnd = false;
	offset_duration = browserInfo.xiaomi ? 0.2 : 0.08
	setStep();
};

/** 播放模式结束自动重播 */
const autoResetPlay = () => {
	if (state.modeType !== "practise") return;
	skipNotePlay(0, true);
	// 没有开启自动重播, 不是练习模式
	if (!state.setting.repeatAutoPlay) return;
	scrollViewNote();
	setTimeout(() => {
		togglePlay("play");
	}, 1000);
};

/** 播放完成事件 */
export const onEnded = () => {
	console.log("音频播放结束");
	// 修改状态为结束
	state.playEnd = true;
	state.playState = "paused";
	// 结束播放
	audioListStart(state.playState);
	// 调用结束评测
	handleEndEvaluat(true);
	// 调用自动重复播放
	autoResetPlay();
};

/**
 * 播放一直触发的事件
 */
const handlePlaying = () => {
	const currentTime = getAudioCurrentTime();
	const duration = getAudioDuration();
	state.playProgress = (currentTime / duration) * 100;
	let item = getNote(currentTime);

	if (item) {
		// 选段状态下
		if (state.sectionStatus && state.section.length === 2) {
			// 如果开启了预备拍
			const selectStartItem = state.sectionFirst ? state.sectionFirst : state.section[0];
			const selectEndItem = state.section[1];
				
			if (Math.abs(selectEndItem.endtime - currentTime) < offset_duration) {
				console.log("选段播放结束");
				// 如果为选段评测模式
				if (state.modeType === "evaluating" && state.isSelectMeasureMode) {
					onEnded();
					return;
				}
				item = selectStartItem;
				setAudioCurrentTime(selectStartItem.time, selectStartItem.i);
			}
		}
		gotoNext(item);
	}

	metronomeData.metro?.sound(currentTime);
};
/** 跳转到指定音符开始播放 */
export const skipNotePlay = (itemIndex: number, isStart = false) => {
	const item = state.times[itemIndex];
	let itemTime = item.time;
	if (isStart) {
		itemTime = 0;
	}
	// console.log("🚀 ~ itemTime:", itemTime);
	if (item) {
		setAudioCurrentTime(itemTime, itemIndex);
		gotoNext(item);
		metronomeData.metro?.sound(itemTime);
	}
};

/**
 * 切换曲谱播放状态
 * @param playState 可选: 默认 undefined, 需要切换的状态 play:播放, paused: 暂停
 */
export const togglePlay = async (playState?: "play" | "paused") => {
	state.playState = playState ? playState : state.playState === "paused" ? "play" : "paused";
	// 设置为开始播放时, 如果需要节拍,先播放节拍器
	if (state.playState === "play" && state.needTick) {
		const tickend = await handleStartTick();
		// console.log("🚀 ~ tickend:", tickend)
		// 节拍器返回false, 取消播放
		if (!tickend) {
			state.playState = "paused";
			return false;
		}
	}
	// 如果选段没有结束, 直接开始播放,清空选段状态
	if (state.playState == "play") {
		if (state.sectionStatus && state.section.length < 2) {
			clearSelection();
		}
	}
	audioListStart(state.playState);
	return true;
};
/** 结束播放 */
export const handleStopPlay = () => {
	state.playState = "paused";
	audioListStart(state.playState);
};

/** 重置播放为开始 */
export const resetPlaybackToStart = () => {
	// 如果为选段状态
	if (state.sectionStatus && state.section.length === 2) {
		state.section = formateSelectMearure(state.section);
		return;
	}
	skipNotePlay(0, true);
};

/** 跳转到指定音符 */
export const gotoCustomNote = (index: number) => {
	try {
		state.osmd.cursor.reset();
	} catch (error) {}
	for (let i = 0; i < index; i++) {
		state.osmd.cursor.next();
	}
};
/** 跳转到下一个音符 */
export const gotoNext = (note: any) => {
	const num = note.i;
	// console.log('next', state.activeNoteIndex, num)
	if (state.activeNoteIndex === note.i) return;
	const osmd = state.osmd;
	let prev = state.activeNoteIndex;
	state.activeNoteIndex = num;
	state.activeMeasureIndex = note.MeasureNumberXML;

	if (prev && num - prev === 1) {
		osmd.cursor.next();
	} else if (prev && num - prev > 0) {
		while (num - prev > 0) {
			prev++;
			osmd.cursor.next();
		}
	} else {
		gotoCustomNote(num);
	}

	scrollViewNote();
};
/** 获取指定音符 */
export const getNote = (currentTime: number) => {
	const times = state.times;
	const len = state.times.length;
	/** 播放超过了最后一个音符的时间,直接结束, 2秒误差 */
	if (currentTime > times[len - 1].endtime + 2) {
		onEnded();
		return;
	}
	let _item = null as any;
	for (let i = state.activeNoteIndex; i < len; i++) {
		const item = times[i];
		const prevItem = times[i - 1];
		if (currentTime >= item.time) {
			if (!prevItem || item.time != prevItem.time) {
				_item = item;
			}
		} else {
			break;
		}
	}
	// console.log("activeNoteIndex", currentTime, state.activeNoteIndex, _item.i);
	return _item;
};

/** 重播 */
export const handleResetPlay = () => {
	resetPlaybackToStart();
	// 如果是暂停, 直接播放
	togglePlay('play')
};
/** 设置速度 */
export const handleSetSpeed = (speed: number) => {
	setStorageSpeed(state.examSongId, speed)
	state.speed = speed;
};
/** 清除选段状态 */
export const clearSelection = () => {
	state.sectionStatus = false;
	state.section = [];
	closeToast();
};

/** 开启选段 */
export const handleChangeSection = () => {
	// 如果开启了选段,再次点击取消选段
	if (state.sectionStatus) {
		togglePlay('paused')
		skipNotePlay(0, true);
		clearSelection();
		return;
	}
	state.sectionStatus = true;
	// 开启
	if (state.sectionStatus) {
		togglePlay("paused");
	}
	showToast({
		message: "请选择开始小节",
		duration: 0,
		position: "top",
		className: "selectionToast",
	})
};

/** 效验并格式化选段小节 */
const formateSelectMearure = (_list: any[]): any[] => {
	if (!_list.length) return [];
	const list = _list.sort((a, b) => a.time - b.time);
	const startXml = list[0]?.measureOpenIndex;
	const endXml = list.last()?.measureOpenIndex;
	const selectStartMeasure = state.times.filter((n: any) => startXml === n.measureOpenIndex) || [];
	const selectEndMeasure = state.times.filter((n: any) => endXml === n.measureOpenIndex) || [];
	// 没有找到选段小节
	if (!selectStartMeasure.length || !selectEndMeasure.length) {
		clearSelection();
		return [];
	}
	list[0] = selectStartMeasure[0];
	list[1] = selectEndMeasure.last();
	let startItemINdex = list[0].i;
	// 开启预备拍
	if (state.isOpenPrepare) {
		const startXmlIndex = list[0].MeasureNumberXML;
		state.sectionFirst = state.times.find((n: any) => startXmlIndex - n.MeasureNumberXML === 1);
		startItemINdex = state.sectionFirst ? state.sectionFirst.i : startItemINdex;
	}
	skipNotePlay(startItemINdex, startItemINdex === 0);
	return list;
};

/** 选择选段 */
export const handleSelection = (item: any) => {
	if (!state.sectionStatus || state.section.length > 1) return;
	if (state.section.length !== 2 && item) {
		state.section.push(item);
		if (state.section.length === 2) {
			state.section = formateSelectMearure(state.section);
			closeToast();
		}
	}
	if (state.section.length === 1) {
		showToast({
			message: "请选择结束小节",
			duration: 0,
			position: "top",
			className: "selectionToast",
		})
	}
};

/** 直接设置选段 */
export const hanldeDirectSelection = (list: any[]) => {
	if (!Array.isArray(list) || list.length !== 2) return;
	state.sectionStatus = true;
	state.section = formateSelectMearure(list);
};
let offsetTop = 0;
/**
 * 窗口内滚动到音符的区域
 * @param isScroll 可选: 强制滚动到顶部, 默认: false
 * @returns void
 */
export const scrollViewNote = () => {
	const cursorElement = document.getElementById("cursorImg-0")!;
	const musicAndSelection = document.getElementById(state.scrollContainer)!;
	if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop) return;
	offsetTop = cursorElement.offsetTop;
	if (offsetTop > 50) {
		musicAndSelection.scrollTo({
			top: (offsetTop - 50) * state.musicZoom ,
			behavior: "smooth",
		});
	} else {
		musicAndSelection.scrollTo({
			top: 0,
			behavior: "smooth",
		});
	}
};

/** 检测是否是节奏练习 */
export const isRhythmicExercises = () => {
	return state.examSongName.indexOf("节奏练习") > -1;
};

/** 重置状态 */
export const handleRessetState = () => {
	if (state.modeType === "evaluating") {
		handleStartEvaluat();
	} else if (state.modeType === "practise") {
		togglePlay("paused");
	} else if (state.modeType === "follow") {
		toggleFollow(false);
	}
};
export default state;
