import { defaultData } from "../script/defaultData";
import { letterData, letterWidthData } from "../script/letterPointData";
import {
	asyncDelay,
	asyncPlayDragonBoneAnimation,
	asyncPlayEffectByUrl,
	asyncTweenTo,
	jelly,
	onHomeworkFinish,
	RandomInt,
	showFireworks
} from "../script/utils";

cc.Class({
	extends: cc.Component,
	properties: {
		audio_btn: cc.AudioClip,
		audio_cloud: cc.AudioClip,
		audio_income: cc.AudioClip,
		audio_press: cc.AudioClip,
		audio_star: cc.AudioClip,
		audio_write: cc.AudioClip,
		audio_zoom: cc.AudioClip,
		audio_title: cc.AudioClip,

		audio_a: cc.AudioClip,
		audio_b: cc.AudioClip,
		audio_c: cc.AudioClip,
		audio_d: cc.AudioClip,
		audio_e: cc.AudioClip,
		audio_f: cc.AudioClip,
		audio_g: cc.AudioClip,
		audio_h: cc.AudioClip,
		audio_i: cc.AudioClip,
		audio_j: cc.AudioClip,
		audio_k: cc.AudioClip,
		audio_l: cc.AudioClip,
		audio_m: cc.AudioClip,
		audio_n: cc.AudioClip,
		audio_o: cc.AudioClip,
		audio_p: cc.AudioClip,
		audio_q: cc.AudioClip,
		audio_r: cc.AudioClip,
		audio_s: cc.AudioClip,
		audio_t: cc.AudioClip,
		audio_u: cc.AudioClip,
		audio_v: cc.AudioClip,
		audio_w: cc.AudioClip,
		audio_x: cc.AudioClip,
		audio_y: cc.AudioClip,
		audio_z: cc.AudioClip,
	},

	// 生命周期 onLoad
	onLoad() {
		this.initSceneData();
		this.initSize();
	},

	_imageResList: null,
	_audioResList: null,
	_animaResList: null,
	initSceneData() {
		this._imageResList = [];
		this._audioResList = [];
		this._animaResList = [];
	},

	_designSize: null,  // 设计分辨率
	_frameSize: null,  // 屏幕分辨率
	_mapScaleMin: null,  // 场景中常用缩放（取大值）
	_mapScaleMax: null,  // 场景中常用缩放（取小值）
	_cocosScale: null,  // cocos 自缩放 （较少用到）
	initSize() {

		// 注意cc.winSize只有在适配后(修改fitHeight/fitWidth后)才能获取到正确的值,因此使用cc.getFrameSize()来获取初始的屏幕大小
		let screen_size = cc.view.getFrameSize().width / cc.view.getFrameSize().height
		let design_size = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height
		let f = screen_size >= design_size
		cc.Canvas.instance.fitHeight = f
		cc.Canvas.instance.fitWidth = !f

		const frameSize = cc.view.getFrameSize();
		this._frameSize = frameSize;

		this._designSize = cc.view.getDesignResolutionSize();

		let sx = cc.winSize.width / frameSize.width;
		let sy = cc.winSize.height / frameSize.height;
		this._cocosScale = Math.min(sx, sy);

		sx = frameSize.width / this._designSize.width;
		sy = frameSize.height / this._designSize.height;
		this._mapScaleMin = Math.min(sx, sy) * this._cocosScale;
		this._mapScaleMax = Math.max(sx, sy) * this._cocosScale;
	},

	// 生命周期 start
	start() {
		let getData = this.getData.bind(this);
		if (window && window.courseware) {
			getData = window.courseware.getData;
		}

		getData((data) => {
			console.log('data:', data);
			this.data = data || this.getDefaultData();
			this.data = JSON.parse(JSON.stringify(this.data))
			this.preloadItem()
		})
	},

	getData(cb) {
		cb(this.getDefaultData());
	},

	getDefaultData() {
		return defaultData;
	},

	preloadItem() {
		this.addPreloadImage();
		this.addPreloadAudio();
		this.addPreloadAnima();
		this.preload();
	},

	addPreloadImage() {
		// this._imageResList.push({ url: this.data.pic_url });
	},

	addPreloadAudio() {
		this._audioResList.push({ url: this.data.titleAudio });
	},

	addPreloadAnima() {

	},

	preload() {

		const preloadArr = this._imageResList.concat(this._audioResList).concat(this._animaResList);
		cc.assetManager.loadAny(preloadArr, null, null, (err, data) => {

			this.loadEnd();

			cc.debug.setDisplayStats(false);
		});
	},

	loadEnd() {
		this.initData();
		this.initAudio();
		this.initView();
		this.initListener();
		if (window && window["air"]) {
			window["air"].hideAirClassLoading();
		}
	},

	initData() {
		this._status = {
			currentLetterIdx: 0,
			currentLetter: this.data.letterList[0]
		}
	},

	initAudio() {

	},

	initView() {
		this.createLetterPage(this._status.currentLetter);

		this.initTitle();

		cc.find('Canvas').on('size-changed', this.onSizeChanged.bind(this));

		this.refreshBtnStatus();

		cc.audioEngine.play(this.audio_income, false, 1);

		if (this.data.debugMode) {
			this.initDebugMode();
		}
	},

	initTitle() {
		const titleRichText = cc.find('Canvas/UIBase/Title/RichText');
		titleRichText.getComponent(cc.RichText).string = `<outline color=#d55b75 width=2>${this.data.titleTxt}</outline>`;
		if (titleRichText.width > 340) {
			titleRichText.scale = 340 / titleRichText.width;
		}
	},

	onSizeChanged() {
		cc.director.loadScene(cc.director.getScene().name);

		// this.node.getComponent(cc.Widget).updateAlignment();
		// const frameSize = cc.view.getFrameSize();
		// const designSize = cc.view.getDesignResolutionSize();

		// const scale = (designSize.width / designSize.height) / (frameSize.width / frameSize.height);
		// const letterBg = cc.find('Canvas/bg/LetterLayer');
		// letterBg.scale = Math.min(scale, 1);
	},

	async initDebugMode() {
		const debugBase = cc.find('Canvas/UIBase/DebugBase');
		debugBase.active = true;
		const drawBaseComponent = debugBase.getComponent('DebugDrawBase');
		drawBaseComponent.letter = this._status.currentLetter;
		await asyncDelay(0.01);
		drawBaseComponent.setDrawNode(cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode'));
	},

	initListener() {
		const title = cc.find('Canvas/UIBase/Title');
		title.on('click', async () => {
			if (title.cannottClick) {
				return;
			}
			title.cannottClick = true;
			// jelly(title, 0.05);
			await asyncPlayEffectByUrl(this.data.titleAudio);
			title.cannottClick = false;
		});

		const BtnSpeaker = cc.find('Canvas/UIBase/BtnSpeaker');
		BtnSpeaker.on('click', async () => {
			if (BtnSpeaker.cannottClick) {
				return;
			}
			BtnSpeaker.cannottClick = true;
			jelly(BtnSpeaker);
			this.speakerBlink();
			const letterAudio = this[`audio_${this._status.currentLetter.toLowerCase()}`];
			const audioId = cc.audioEngine.play(letterAudio, false, 1);
			cc.audioEngine.setFinishCallback(audioId, () => {
				this.speakerStopBlink();
				BtnSpeaker.cannottClick = false;
			});
		});
		const BtnSwitchUpper = cc.find('Canvas/UIBase/BtnSwitchUpper');
		const BtnSwitchLower = cc.find('Canvas/UIBase/BtnSwitchLower');

		BtnSwitchUpper.on('click', () => {
			const letter = this._status.currentLetter.toUpperCase();
			this._status.currentLetter = letter;
			this.createLetterPage(letter);
			this.refreshBtnStatus();
		});
		BtnSwitchLower.on('click', () => {
			const letter = this._status.currentLetter.toLowerCase();
			this._status.currentLetter = letter;
			this.createLetterPage(letter);
			this.refreshBtnStatus();
		});
		const BtnBefore = cc.find('Canvas/UIBase/BtnBefore');
		const BtnNext = cc.find('Canvas/UIBase/BtnNext');
		BtnBefore.on('click', async () => {
			if (BtnBefore.cannottClick) {
				return;
			}
			BtnBefore.cannottClick = true;
			this._status.currentLetterIdx--;
			const letter = this.data.letterList[this._status.currentLetterIdx];
			this._status.currentLetter = letter;
			this.createLetterPage(letter);
			await jelly(BtnBefore);
			this.refreshBtnStatus();
			BtnBefore.cannottClick = false;
		});
		BtnNext.on('click', async () => {
			if (BtnNext.cannottClick) {
				return;
			}
			BtnNext.cannottClick = true;
			this._status.currentLetterIdx++;
			const letter = this.data.letterList[this._status.currentLetterIdx];
			this._status.currentLetter = letter;
			this.createLetterPage(letter);
			await jelly(BtnNext);
			this.refreshBtnStatus();
			BtnNext.cannottClick = false;
		});
		const BtnRefresh = cc.find('Canvas/UIBase/BtnRefresh');
		BtnRefresh.on('click', () => {
			jelly(BtnRefresh);
			this.createLetterPage(this._status.currentLetter);
		});
	},

	refreshBtnStatus() {
		const BtnBefore = cc.find('Canvas/UIBase/BtnBefore');
		const BtnNext = cc.find('Canvas/UIBase/BtnNext');

		BtnBefore.active = true;
		BtnNext.active = true;

		if (this._status.currentLetterIdx == this.data.letterList.length - 1) {
			BtnNext.active = false;
		}
		if (this._status.currentLetterIdx == 0) {
			BtnBefore.active = false;
		}
		const BtnSwitchUpper = cc.find('Canvas/UIBase/BtnSwitchUpper');
		const BtnSwitchLower = cc.find('Canvas/UIBase/BtnSwitchLower');
		if (this._status.currentLetter == this._status.currentLetter.toUpperCase()) {
			BtnSwitchUpper.active = false;
			BtnSwitchLower.active = true;
		} else {
			BtnSwitchUpper.active = true;
			BtnSwitchLower.active = false;
		}
	},

	createLetterPage(letter) {
		const oldLetterLayer = cc.find('Canvas/bg/LetterLayer');
		if (oldLetterLayer) {
			this.oldLetterPageFlyout(oldLetterLayer);
		}
		const newLetterLayer = cc.instantiate(cc.find(`LetterLayer`));
		newLetterLayer.x = 0;
		newLetterLayer.y = 0;
		newLetterLayer.parent = cc.find('Canvas/bg');

		const bgSpriteFrameList = cc.find('Bgs').children.map(node => {
			return node.getComponent(cc.Sprite).spriteFrame
		});
		const bg = newLetterLayer.getChildByName('bg');
		bg.getComponent(cc.Sprite).spriteFrame = bgSpriteFrameList[RandomInt(bgSpriteFrameList.length)];
		bg.width = bg.parent.width;

		const drawBase = newLetterLayer.getChildByName('DrawBase');
		drawBase.getComponent(cc.Mask).spriteFrame = this.getLetterSpriteFrame(letter);

		cc.find('Canvas/UIBase/BtnSwitchLower/LabelBigShader').getComponent(cc.Label).string = letter.toUpperCase();
		cc.find('Canvas/UIBase/BtnSwitchLower/LabelBigShader/Label').getComponent(cc.Label).string = letter.toUpperCase();
		cc.find('Canvas/UIBase/BtnSwitchLower/LabelSmallShader').getComponent(cc.Label).string = letter.toLowerCase();
		cc.find('Canvas/UIBase/BtnSwitchLower/LabelSmallShader/Label').getComponent(cc.Label).string = letter.toLowerCase();
		cc.find('Canvas/UIBase/BtnSwitchUpper/LabelBigShader').getComponent(cc.Label).string = letter.toUpperCase();
		cc.find('Canvas/UIBase/BtnSwitchUpper/LabelBigShader/Label').getComponent(cc.Label).string = letter.toUpperCase();
		cc.find('Canvas/UIBase/BtnSwitchUpper/LabelSmallShader').getComponent(cc.Label).string = letter.toLowerCase();
		cc.find('Canvas/UIBase/BtnSwitchUpper/LabelSmallShader/Label').getComponent(cc.Label).string = letter.toLowerCase();

		const monkey = cc.find('bg/bg_change', newLetterLayer);
		monkey.scale = monkey.parent.width / monkey.width;
		monkey.x = 0;
		monkey.y = 15 * monkey.scale - monkey.parent.height / 2;

		if (this.data.debugMode) {
			console.log('initDebugMode');
			this.initDebugMode();
		} else {
			this.createShark();
			this.createArrows();
			this.createStar();
		}
	},

	getLetterSpriteFrame(letter) {
		if (letter == letter.toUpperCase()) {
			return cc.find(`Letters/${letter}_big`).getComponent(cc.Sprite).spriteFrame;
		}
		return cc.find(`Letters/${letter.toUpperCase()}_small`).getComponent(cc.Sprite).spriteFrame;
	},

	async oldLetterPageFlyout(oldLetterLayer) {
		oldLetterLayer.zIndex = 1;
		oldLetterLayer.name = 'oldLetterLayer';

		oldLetterLayer.getComponent(cc.Widget).enabled = false;

		await asyncTweenTo(oldLetterLayer, 6, { y: 4000 });
	},

	createShark() {
		const letter = this._status.currentLetter;
		if (!letterData[letter][0]) {
			return;
		}
		let shark = cc.instantiate(cc.find('Icons/shark'));
		if (letter == letter.toLowerCase()) {
			shark = cc.instantiate(cc.find('Icons/monkey'));
		}
		this._status._currentPenIdx = 0;
		this._status._currentPointIdx = 0;

		const sharkData = this.getCurrentSharkData();
		shark.x = sharkData.x;
		shark.y = sharkData.y;
		shark.zIndex = 1;
		shark.angle = sharkData.angle;
		shark.scaleY = sharkData.scaleY;
		shark.parent = cc.find('Canvas/bg/LetterLayer');

		shark.off('touchstart', this.onSharkTouchStart.bind(this));
		shark.off('touchmove', this.onSharkTouchMove.bind(this));
		shark.off('touchend', this.onSharkTouchEnd.bind(this));
		shark.off('touchcancel', this.onSharkTouchEnd.bind(this));

		shark.on('touchstart', this.onSharkTouchStart.bind(this));
		shark.on('touchmove', this.onSharkTouchMove.bind(this));
		shark.on('touchend', this.onSharkTouchEnd.bind(this));
		shark.on('touchcancel', this.onSharkTouchEnd.bind(this));

	},

	onSharkTouchStart(event) {
		const location = event.getLocation();
		const shark = event.target;
		const pos = shark.parent.convertToNodeSpaceAR(location);
		shark.startPos = cc.v2(pos.x - shark.x, pos.y - shark.y);
		shark.lastPos = cc.v2(shark.x, shark.y);
		jelly(shark);

		cc.audioEngine.play(this.audio_press, false, 1);
	},

	onSharkTouchMove(event) {
		const location = event.getLocation();
		const shark = event.target;
		if (!shark.lastPos) {
			return;
		}

		const pos = shark.parent.convertToNodeSpaceAR(location);
		shark.x = pos.x - shark.startPos.x;
		shark.y = pos.y - shark.startPos.y;

		if (this.checkSharkOutRange(shark)) {
			this.onSharkTouchEnd(event);
			return;
		}
		const drawNode = cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode');
		this.drawALine(drawNode, shark.lastPos, cc.v2(shark.x, shark.y), cc.color(253, 227, 148));

		shark.lastPos = cc.v2(shark.x, shark.y);

		this.updateCurrentPointIdx(shark);

		this.updateArrows(shark);

		const sharkData = this.getCurrentSharkData();
		if (!sharkData) {
			return;
		}

		shark.scaleY = sharkData.scaleY;
		if (!shark.angleAction) {

			let angle = sharkData.angle;
			if (sharkData.angle - shark.angle > 180) {
				angle -= 360;
			}
			if (sharkData.angle - shark.angle < - 180) {
				angle += 360;
			}
			shark.angleAction = cc.tween(shark)
				.to(0.1, { angle: angle })
				.call(() => {
					shark.angleAction = null;
				})
				.start();
		}
	},

	onSharkTouchEnd(event) {
		const shark = event.target;
		shark.lastPos = null;
		shark.startPos = null;
		this._status._currentPointIdx = 0;
		this.updateCurrentGraph(true);
		this.moveSharkBack(event.target);
		this.showArrows();
	},

	getCurrentSharkData() {
		let angle = 0;
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		const pointIdx = this._status._currentPointIdx;
		if (!letterData[letter][penIdx]) {
			return;
		}
		const point = letterData[letter][penIdx][pointIdx];
		const nextPoint = letterData[letter][penIdx][pointIdx + 1];

		if (letter == letter.toUpperCase()) {
			if (nextPoint) {
				let line = cc.v2(nextPoint.x - point.x, nextPoint.y - point.y);
				angle = cc.v2(-1, 0).signAngle(line) * (180 / Math.PI);
			}
		}

		let scaleY = 1;
		if (angle > 90 || angle < -90) {
			scaleY = -1;
		}

		return { x: point.x, y: point.y, angle: angle, scaleY: scaleY };
	},

	updateCurrentPointIdx(shark) {
		const pos = cc.v2(shark.x, shark.y);
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		const pointIdx = this._status._currentPointIdx;
		if (!letterData[letter][penIdx]) {
			return;
		}
		const nextPoint = letterData[letter][penIdx][pointIdx + 1];

		if (this.getDistance(shark, nextPoint) < 80) {
			this._status._currentPointIdx++;

			if (this._status._currentPointIdx >= letterData[letter][penIdx].length - 1) {

				this._status._currentPointIdx = 0;
				this._status._currentPenIdx++;

				shark.lastPos = null;
				shark.startPos = null;

				this.showFlower(shark);
				if (this._status._currentPenIdx < letterData[letter].length) {
					this.removeStar();
					this.createArrows();
					this.createStar();
				} else {
					this.showOver(shark);
					this.createClouds();
					this.zoomStar();
					this.playLetterAudio();
					// this.showFireworks();
					onHomeworkFinish();
				}
				this.updateCurrentGraph(true);
				this.moveSharkBack(shark);
			}
		}
	},

	getDistance(pos1, pos2) {
		return cc.v2(pos1.x, pos1.y).sub(cc.v2(pos2.x, pos2.y)).mag();
	},

	checkSharkOutRange(shark) {
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		if (!letterData[letter][penIdx]) {
			return false;
		}

		if (!shark.pointList) {
			shark.pointList = [];
		}
		if (!shark.pointList[penIdx]) {
			const penPointList = letterData[letter][penIdx].map(pos => cc.v2(pos.x, pos.y));
			const debugBase = cc.find('Canvas/UIBase/DebugBase');
			const drawBaseComponent = debugBase.getComponent('DebugDrawBase');
			const pointList = drawBaseComponent.interpolatePos(penPointList, 10);
			shark.pointList[penIdx] = pointList;
		}

		const pointList = shark.pointList[penIdx];

		let result = true;
		pointList.forEach(point => {
			if (result == false) {
				return;
			}
			const distance = this.getDistance(point, shark);
			if (distance < 120) {
				result = false;
			}
		});

		return result;
	},

	showFlower(shark) {
		const flower = cc.instantiate(cc.find('Icons/flower'));
		flower.x = shark.x;
		flower.y = shark.y;
		flower.parent = shark.parent;
		cc.audioEngine.play(this.audio_star, false, 1);
		asyncPlayDragonBoneAnimation(flower, 'newAnimation', 1);
	},

	showOver(shark) {
		this.removeArrows();

		shark.removeFromParent();
	},

	moveSharkBack(shark) {
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		if (!letterData[letter][penIdx]) {
			return;
		}

		const sharkData = this.getCurrentSharkData();

		cc.tween(shark)
			.to(0.1, { x: sharkData.x, y: sharkData.y, angle: sharkData.angle, scaleY: sharkData.scaleY })
			.start();
	},

	updateCurrentGraph(clear = false) {
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;

		const lineList = [];
		for (let i = 0; i < penIdx; i++) {
			const posList = letterData[letter][i];
			for (let idx = 0; idx < posList.length - 1; idx++) {
				lineList.push({ startPos: posList[idx], endPos: posList[idx + 1] });
			}
		}
		const drawNode = cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode');
		if (clear) {
			const graph = drawNode.getComponent(cc.Graphics);
			graph.clear();
		}
		lineList.forEach(line => {
			this.drawALine(drawNode, line.startPos, line.endPos, cc.color(253, 227, 148));
		});
	},

	drawALine(drawNode, fromPos, toPos, color) {
		const letter = this._status.currentLetter;
		const graph = drawNode.getComponent(cc.Graphics);
		if (color) {
			graph.strokeColor = color;
		}
		if (letterWidthData[letter]) {
			graph.lineWidth = letterWidthData[letter];
		} else {
			graph.lineWidth = letterWidthData.defaultWidth;
		}
		graph.moveTo(fromPos.x, fromPos.y);
		graph.lineTo(toPos.x, toPos.y);
		graph.stroke();
	},

	_cloudList: null,
	createClouds() {
		const letter = this._status.currentLetter;

		if (this._cloudList) {
			this._cloudList.forEach(cloud => {
				cloud.removeFromParent();
			});
		}
		this._cloudList = [];

		letterData[letter].forEach(pen => {
			const penPointList = pen.map(pos => cc.v2(pos.x, pos.y));
			const debugBase = cc.find('Canvas/UIBase/DebugBase');
			const drawBaseComponent = debugBase.getComponent('DebugDrawBase');
			const pointList = drawBaseComponent.interpolatePos(penPointList, 10);

			for (let i = 0; i < pointList.length; i++) {
				const point = pointList[i];

				const lastcloud = this._cloudList[this._cloudList.length - 1];
				if (lastcloud && this.getDistance(lastcloud, point) < 60) {
					continue;
				}

				const cloud = this.createCloud(point);
				this._cloudList.push(cloud);
			}
		});
		const cloudLength = this._cloudList.length;
		this._cloudList.forEach((cloud, idx) => {
			cloud.opacity = 0;
			cc.tween(cloud)
				.delay(idx * (3 / cloudLength))
				.call(() => {
					cc.audioEngine.play(this.audio_cloud, false, 1);
				})
				.to(0.5, { opacity: 255, scale: 1.3 })
				.to(0.1, { scale: 1 })
				.start();
		});
	},

	createCloud(pos) {
		const LetterLayer = cc.find('Canvas/bg/LetterLayer');
		const arrow = cc.instantiate(cc.find('Icons/cloud'));
		arrow.x = pos.x;
		arrow.y = pos.y;
		arrow.parent = LetterLayer;
		return arrow;
	},

	_arrowList: null,
	createArrows() {
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		if (!letterData[letter][penIdx]) {
			return;
		}

		const penPointList = letterData[letter][penIdx].map(pos => cc.v2(pos.x, pos.y));
		const debugBase = cc.find('Canvas/UIBase/DebugBase');
		const drawBaseComponent = debugBase.getComponent('DebugDrawBase');
		const pointList = drawBaseComponent.interpolatePos(penPointList, 10);

		this.removeArrows();

		for (let i = 16; i < pointList.length - 12; i++) {
			const point = pointList[i];
			const nextPoint = pointList[i + 1];
			const nextPoint2 = pointList[i + 2];

			const lastArrow = this._arrowList[this._arrowList.length - 1];
			if (lastArrow && this.getDistance(lastArrow, nextPoint) < 80) {
				continue;
			}

			const arrow = this.createArrow(point, nextPoint, nextPoint2);
			this._arrowList.push(arrow);
		}

		const arrowLength = this._arrowList.length;
		this._arrowList.forEach((arrow, idx) => {
			cc.tween(arrow)
				.delay(idx * 0.4)
				.to(0.5, { opacity: 0 })
				.to(0.5, { opacity: 255 })
				.delay(arrowLength * 0.4 - idx * 0.4)
				.union()
				.repeatForever()
				.start();
		});
	},

	showArrows() {
		for (const arrow of this._arrowList) {
			arrow.active = true;
		}
	},

	updateArrows(shark) {
		for (const arrow of this._arrowList) {
			if (arrow.active == false) {
				continue;
			}
			if (this.getDistance(shark, arrow) < 80) {
				arrow.active = false;
				cc.audioEngine.play(this.audio_write, false, 1);
				break;
			}
		}
	},

	removeArrows() {
		if (this._arrowList) {
			this._arrowList.forEach(arrow => {
				arrow.removeFromParent();
			});
		}
		this._arrowList = [];
	},

	createArrow(pos1, centerPos, pos2) {
		let line = cc.v2(pos2.x - pos1.x, pos2.y - pos1.y);
		let angle = cc.v2(1, 0).signAngle(line) * (180 / Math.PI);

		const LetterLayer = cc.find('Canvas/bg/LetterLayer');
		const arrow = cc.instantiate(cc.find('Icons/arrow'));
		arrow.x = centerPos.x;
		arrow.y = centerPos.y;
		arrow.parent = LetterLayer;
		arrow.angle = angle;

		return arrow;
	},

	createStar() {
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		if (!letterData[letter][penIdx]) {
			return;
		}
		const pen = letterData[letter][penIdx];
		const lastPoint = pen[pen.length - 1];

		const LetterLayer = cc.find('Canvas/bg/LetterLayer');
		const star = cc.instantiate(cc.find('Icons/star'));
		star.x = lastPoint.x;
		star.y = lastPoint.y;
		star.parent = LetterLayer;
		this.star = star;
	},

	removeStar() {
		const star = this.star;
		cc.tween(star)
			.to(0.2, { angle: 360, opacity: 0 })
			.call(() => {
				star.removeFromParent();
			})
			.start();
	},

	zoomStar() {
		const star = this.star;
		const LetterLayer = cc.find('Canvas/bg/LetterLayer');
		const starbig = cc.instantiate(cc.find('Icons/starbig'));
		starbig.scale = star.width / starbig.width;
		starbig.x = star.x;
		starbig.y = star.y;
		starbig.parent = LetterLayer;

		star.removeFromParent();

		cc.audioEngine.play(this.audio_zoom, false, 1);

		cc.tween(starbig)
			.to(1, { x: 0, y: 0, scale: 1, angle: 360 * 2 })
			.to(1, { scale: 1.5, angle: 360 * 2, opacity: 0 })
			.call(() => {
				starbig.removeFromParent();
			})
			.start();
	},

	showFireworks() {
		cc.find('Canvas/Main Camera').zIndex = 10;
		showFireworks(
			cc.find('Canvas/Main Camera'),
			cc.find('Icons').children,
			cc.v2(0, -400), cc.v2(0, 1000), 200, 200
		);
		showFireworks(
			cc.find('Canvas/Main Camera'),
			cc.find('Icons').children,
			cc.v2(-600, -400), cc.v2(200, 1000), 200, 200
		);
		showFireworks(
			cc.find('Canvas/Main Camera'),
			cc.find('Icons').children,
			cc.v2(600, -400), cc.v2(-200, 1000), 200, 200
		);
	},

	async playLetterAudio() {
		await asyncDelay(4);

		const letterAudio = this[`audio_${this._status.currentLetter.toLowerCase()}`];
		const audioId = cc.audioEngine.play(letterAudio, false, 1);
		cc.audioEngine.setFinishCallback(audioId, () => { });
	},

	speakerBlink() {
		const speaker0 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_0');
		const speaker1 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_1');
		const speaker2 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_2');

		cc.tween(speaker0)
			.call(() => {
				speaker0.active = true;
			})
			.delay(0.2)
			.union()
			.repeatForever()
			.start();

		cc.tween(speaker1)
			.delay(0.1)
			.call(() => {
				speaker1.active = true;
			})
			.delay(0.1)
			.union()
			.repeatForever()
			.start();

		cc.tween(speaker2)
			.delay(0.2)
			.call(() => {
				speaker2.active = true;
			})
			.union()
			.repeatForever()
			.start();
	},

	speakerStopBlink() {
		const speaker0 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_0');
		const speaker1 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_1');
		const speaker2 = cc.find('Canvas/UIBase/BtnSpeaker/Speaking_2');

		speaker0.stopAllActions();
		speaker1.stopAllActions();
		speaker2.stopAllActions();

		speaker0.active = false;
		speaker1.active = false;
		speaker2.active = false;
	},
});
