import { defineComponent, onMounted, onUnmounted, reactive, ref, watch } from "vue";
import state, { gotoNext, resetPlaybackToStart, followBeatPaly, skipNotePlay, initSetPlayRate } from "/src/state";
import { IPostMessage } from "/src/utils/native-message";
import { api_cloudFollowTime, api_cloudToggleFollow } from "/src/helpers/communication";
import { storeData } from "/src/store";
import { audioRecorder } from "./audioRecorder";
import { handleStartTick } from "/src/view/tick";
import { metronomeData } from "/src/helpers/metronome";
import { getDuration } from "/src/helpers/formateMusic";
import { OpenSheetMusicDisplay } from "/osmd-extended/src";
import { browser, getBehaviorId } from "/src/utils";
import { api_musicPracticeRecordSave } from "../../page-instrument/api";
import { getQuery } from "/src/utils/queryString";

const query: any = getQuery();

export const followData = reactive({
	list: [] as any, // 频率列表
	index: 0,
	start: false,
	rendered: false,
	/** 麦克风权限 */
	earphone: false,
	isBeginMask: false, // 倒计时和系统节拍器时候的遮罩，防止用户点击
	dontAccredit: true, // 没有开启麦克风权限，不需要调用结束收音的api
	practiceStart: false,
});

// 记录跟练时长
const handleRecord = (total: number) => {
	if (query.isCbs || state.systemType === 'web') return
	if (total < 0) total = 0;
	const totalTime = total / 1000;

	const body = {
		clientType: storeData.user.clientType,
		musicSheetId: state.examSongId,
		sysMusicScoreId: state.examSongId,
		feature: "FOLLOW_UP_TRAINING",
		practiceSource: "FOLLOW_UP_TRAINING",
		playTime: totalTime,
		deviceType: browser().android ? "ANDROID" : "IOS",
		behaviorId: getBehaviorId(),
	};
	api_musicPracticeRecordSave(body);
};

/** 点击跟练模式 */
export const toggleFollow = (notCancel = true) => {
	state.modeType = state.modeType === "follow" ? "practise" : "follow";
	// 取消跟练
	if (!notCancel) {
		followData.start = false;
		followData.practiceStart = false;
		// 开启了麦克风授权，才需要调用结束收音
		if (storeData.isApp && !followData.dontAccredit) {
			openToggleRecord(false);
		}
	}
};

const noteFrequency = ref(0);
const audioFrequency = ref(0);
const followTime = ref(0);
// 切换录音
const openToggleRecord = async (open: boolean = true) => {
	if (!open) api_cloudToggleFollow(open ? "start" : "end");
	// 记录跟练时长
	if (open) {
		followTime.value = Date.now();
	} else {
		const playTime = Date.now() - followTime.value;
		if (followTime.value !== 0 && playTime > 0) {
			handleRecord(playTime);
			followTime.value = 0;
		}
	}

	if (!storeData.isApp) {
		const openState = await audioRecorder?.toggleRecord(open);
		// 开启录音失败
		if (!openState && followData.start) {
			followData.earphone = true;
			followData.start = false;
			followData.practiceStart = false;
		}
	}
};

// 清除音符状态
const onClear = () => {
	state.times.forEach((item: any) => {
		const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)!;
		if (note) {
			note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
		}
		const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
		const stemEl = document.getElementById(`vf-${item.id}-stem`);
		if (_note) {
			_note.classList.remove("follow-up", "follow-down", "follow-success");
			stemEl?.classList.remove("follow-up", "follow-down", "follow-success");
		}
	});
};

/** 开始跟练 */
export const handleFollowStart = async () => {
	followData.isBeginMask = true
	checking = false;
	const res = await api_cloudToggleFollow("start");
	// 用户没有授权，需要重置状态
	if (res?.content?.reson) {
		followData.isBeginMask = false
		followData.start = false;
		followData.practiceStart = false;
	} else {
		followData.dontAccredit = false;
		state.hasFollowResult = true;
		// 从头开始跟练，跟练模式开始前，增加播放系统节拍器
		if (state.activeNoteIndex === 0) {
			const tickend = await handleStartTick();
			// console.log("🚀 ~ tickend:", tickend)
			// 节拍器返回false, 取消播放
			if (!tickend) {
				followData.isBeginMask = false
				followData.start = false;
				followData.practiceStart = false;
				return false;
			}
		}
		onClear();
		followData.isBeginMask = false
		followData.start = true;
		followData.practiceStart = true;
		// followData.index = 0;
		followData.index = state.activeNoteIndex;
		followData.list = [];
		initSetPlayRate();
		// resetPlaybackToStart();
		openToggleRecord(true);
		getNoteIndex();
		const duration: any = getDuration(state.osmd as unknown as OpenSheetMusicDisplay);
		metronomeData.totalNumerator = duration.numerator || 2
		metronomeData.followAudioIndex = 1
		state.beatStartTime = 0
		followBeatPaly();		
	}
};
/** 结束跟练 */
export const handleFollowEnd = (handleType?: string) => {
	onClear();
	followData.start = false;
	followData.practiceStart = false;
	state.hasFollowResult = false
	openToggleRecord(false);
	followData.index = 0;
	console.log("结束");
	// 如果开启了循环播放，需要再次跟练
	if (state.setting.repeatAutoPlay && handleType !== 'self') {
		setTimeout(() => {
			followData.practiceStart = true;
			handleFollowStart();
		}, 0);
	}
};

// 清除当前音符右侧的音符的颜色状态
const clearRightNoteColor = () => {
	const noteId = state.times[state.activeNoteIndex]?.id;
	const leftVal = document.getElementById(`vf-${noteId}`)?.getBoundingClientRect()?.left || 0;
	state.times.forEach((item: any) => {
		const note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
		if (note?.getBoundingClientRect()?.left >= leftVal) {
			note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
		}
	});
}

/**
 * 2024.6.17 新增自动结束跟练模式功能
 * 如果跟练模式，唱完了最后一个有频率的音符，需要自动结束掉跟练模式
 * 需要判断当前音符的后面是否都是休止音符（休止音符的频率都是-1），或者是否是最后一个音符了
 */
const autoEndFollow = () => {
	if (followData.index >= state.times.length) {
		setTimeout(() => {
			handleFollowEnd()
		}, 1500);
		
		return
	}
	let nextIndex = followData.index + 1;
	const rightTimes = state.times.slice(followData.index,state.times.length)
	// 后面的音符是否都是休止音符
	const isAllRest = !rightTimes.some((item: any) => item.frequency > 1);
	if (isAllRest && state.times[followData.index].frequency < 1) {
		setTimeout(() => {
			handleFollowEnd()
		}, 1500);
		return
	}
	clearRightNoteColor();
}

// 下一个
const next = () => {
	if (followData.index < state.times.length) {
		gotoNext(state.times[followData.index]);
	}
	autoEndFollow();	
};

// 获取当前音符
const getNoteIndex = (): any => {
	const item = state.times[followData.index];
	if (item.frequency <= 0) {
		followData.index = followData.index + 1;
		next();
		return getNoteIndex();
	}
	noteFrequency.value = item.frequency;
	// state.fixedKey = item.realKey;
	return {
		id: item.id,
		min: item.frequency - (item.frequency - item.prevFrequency) * 0.5,
		max: item.frequency + (item.nextFrequency - item.frequency) * 0.5,
		duration: item.duration,
		baseFrequency: item.frequency,
	};
};
let checking = false;
/** 录音回调 */
const onFollowTime = (evt?: IPostMessage) => {
	const frequency: number = evt?.content?.frequency;
	// 没有开始, 不处理
	if (!followData.start) return;
	// console.log('频率', frequency)
	if (frequency > 0) {
		audioFrequency.value = frequency;
		// data.list.push(frequency)
		checked();
	}
};

let startTime = 0;
const checked = () => {
	if (checking) return;
	checking = true;
	const item = getNoteIndex();
	// 降噪处理, 频率低于 当前音的50% 时, 不处理
	if (audioFrequency.value < item.baseFrequency * 0.5) {
		checking = false;
		return;
	}
	if (audioFrequency.value >= item.min && audioFrequency.value <= item.max) {
		if (startTime === 0) {
			startTime = Date.now();
		} else {
			const playTime = (Date.now() - startTime) / 1000;
			// console.log('时长', playTime, item.duration / 2)
			if (playTime >= item.duration * 0.6) {
				startTime = 0;
				followData.index = followData.index + 1;
				setColor(item, "", true);
				setTimeout(() => {
					next();
					checking = false;
				}, 3000);
				return;
			}
		}
		// console.log("频率对了", item.min, audioFrequency.value, item.max, item.duration);
	}
	// console.log("频率不对", item.min, audioFrequency.value, item.max, item.baseFrequency);
	setColor(item, audioFrequency.value > item.baseFrequency ? "follow-up" : "follow-down");
	checking = false;
};
const setColor = (item: any, state: "follow-up" | "follow-down" | "", isRight = false) => {
	const note: HTMLElement = document.querySelector(`div[data-vf=vf${item.id}]`)!;
	if (note) {
		note.classList.remove("follow-up", "follow-down", "follow-error", "follow-success");
		if (isRight) {
			note.classList.add("follow-success");
		} else {
			note.classList.add("follow-error", state);
		}
	}
	const _note: HTMLElement = document.getElementById(`vf-${item.id}`)!;
	if (_note) {
		const stemEl = document.getElementById(`vf-${item.id}-stem`)
		_note.classList.remove("follow-up", "follow-down");
		stemEl?.classList.remove("follow-up", "follow-down","follow-success");
		if (state) {
			_note.classList.add(state);
			stemEl?.classList.add(state)
		}
		if (isRight) {
			_note.classList.add("follow-success");
			stemEl?.classList.add("follow-success")
		}
	}
};

// 进度跟练，点击某个音符开始跟练
export const skipNotePractice = () => {
	followData.index = state.activeNoteIndex
	// 清除其它音符的错误提示
	const noteFollows: HTMLElement[] = Array.from(document.querySelectorAll(".follow-error"));
	noteFollows.forEach((noteFollow) => {
		noteFollow?.classList.remove("follow-up", "follow-down", "follow-error");
	})
	clearRightNoteColor();
}

// 移动到对应音符的位置
watch(
	() => followData.index,
	() => {
		skipNotePlay(followData.index);
	}
);

export default defineComponent({
	name: "follow",
	setup() {
		onMounted(async () => {
			/** 如果是PC端 */
			if (!storeData.isApp) {
				const canRecorder = await audioRecorder.checkSupport();
				if (canRecorder) {
					audioRecorder.init();
					audioRecorder.progress = (frequency: number) => {
						onFollowTime({ api: "", content: { frequency } });
					};
				} else {
					followData.earphone = true;
				}
			} else {
				api_cloudFollowTime(onFollowTime);
			}
			console.log("进入跟练模式");
		});
		onUnmounted(() => {
			// api_cloudFollowTime(onFollowTime, false);
			resetPlaybackToStart();
			onClear();
			// 开启了麦克风授权，才需要调用结束收音
			if (storeData.isApp && !followData.dontAccredit) {
				openToggleRecord(false);
			}
			console.log("退出跟练模式");
		});
		return () => <div></div>;
	},
});
