
import { defaultData } from "../script/hy_write_word_defaultData";
import { letterData, letterWidthData } from "../script/hy_write_word_letterPointData";
import {
	appearAnim,
	asyncDelay,
	asyncPlayDragonBoneAnimation,
	asyncPlayEffectByUrl,
	asyncTweenTo,
	disappearAnim,
	jelly,
	RandomInt,
	showFireworks,
	getSprNode,
	playAudio,
	playAudioByUrl,
	exchangeNodePos,
	onHomeworkFinish,
	getSprNodeByUrl,
	setSprNodeMaxLen,
	delayCall,
	getPosByAngle
} from "../script/hy_write_word_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.isGameFirst = true;

		this.checkDis = 80;
		this.canvas = cc.find("Canvas");
		this.colorText = '#f74944';
		this.particleLayer = cc.find("Canvas/particleLayer");

		this.wordArr = this.data.wordArr;
		this.wordArrIndex = 0;

		// console.log('this.wordArr[this.wordArrIndex]' , this.wordArr[this.wordArrIndex]);


	},

	initAudio() {

		const audioNode = cc.find('Canvas/res/audio');

		const getAudioByResName = (resName) => {
			return audioNode.getChildByName(resName).getComponent(cc.AudioSource).clip;
		}

		this.color_click_Clip = getAudioByResName('color_click');
		this.letter_end_Clip = getAudioByResName('letter_end');
		this.line_start_Clip = getAudioByResName('line_start');
		this.line_move_Clip = getAudioByResName('line_move');
		this.line_end_Clip = getAudioByResName('line_end');
		this.finish_Clip = getAudioByResName('finish');

		this.move_Clip = getAudioByResName('move');
		this.word_finish_Clip = getAudioByResName('word_finish');

	},

	initView() {

		this.initBg();
		this.initTopPart();
		this.initCurQues();

	


		this.initColorPen();
		

		// this.createLetterPage(this._status.currentLetter);

		// // this.initTitle();

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

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

		// // if (this.data.debugMode) {
		// // 	this.initDebugMode();
		// // } else {
		// 	this.initGuideHand();
		// // }


	},

	startShow() {
		this.showWord();
		this.showPic();
	},

	initCurQues() {
		this.curQues = this.wordArr[this.wordArrIndex];
		if (!this.curQues) {
			return;
		}

		this.letterList = this.curQues.text.split("");
		this.letterListIndex = 0;

		this._status = {
			currentLetterIdx: 0,
			currentLetter: this.letterList[0]
		}
	},


	showWord() {


		this.setWord();


		console.log("text: ", this.curQues.text);
	},

	setWord() {

		const showTime = 1;

		if (!this.wordLayer) {
			this.wordLayer = new cc.Node();
			this.canvas.addChild(this.wordLayer, 2);
		}
		const wordLayer = this.wordLayer;
		wordLayer.removeAllChildren();

		const normalLayer = new cc.Node();
		wordLayer.addChild(normalLayer , 2);
		const strokeLayer = new cc.Node();
		wordLayer.addChild(strokeLayer , 2);
		strokeLayer.opacity = 0;

		this.wordLayer.normalLayer = normalLayer;
		this.wordLayer.strokeLayer = strokeLayer;
		const strokeArr = [];
		this.wordLayer.strokeArr = strokeArr;


		const aNode = getSprNode("letter/a");
		wordLayer.height = aNode.height;

		const letterOffsetData = {
			"b" : 60,
			"d" : 60,
			"f" : 30,
			"g" : -105,
			"h" : 65,
			"i" : 45,
			"j" : -65,
			"k" : 65,
			"l" : 65,
			"p" : -105,
			"q" : -105,
			"t" : 50,
			"y" : -105,
		}

		let curX = 0;
		const disX = 70;
		const letterList = this.letterList;
		for (let i = 0; i < letterList.length; i++) {

		

			const letter = letterList[i];
			const resName = 'letter/' + letter;
			const letterNode = getSprNode(resName)
			letterNode.x = curX + disX + letterNode.width / 2;
			letterNode.color = cc.Color.fromHEX(new cc.Color(), '#af9549')
			normalLayer.addChild(letterNode);

			const resNameS = 'letter_s/' + letter;
			const letterSNode = getSprNode(resNameS)
			letterSNode.x = letterNode.x;
			strokeLayer.addChild(letterSNode);
			strokeArr.push(letterSNode);


			const offsetY = 0;
			const key = letter.toLowerCase();
			if (letterOffsetData[key]) {
				offsetY = letterOffsetData[key];
			}

			letterNode.y = offsetY;
			letterSNode.y = offsetY;


			curX = letterNode.x + letterNode.width / 2;

			// if (i == 0) {
			// 	wordLayer.height = letterNode.height;
			// }
		}


		wordLayer.width = curX + disX;

		const maxH = 150 * this._mapScaleMin;
		wordLayer.scale = maxH / wordLayer.height;
		wordLayer.baseS = wordLayer.scale;

		wordLayer.x = - wordLayer.width / 2 * wordLayer.scale;
		wordLayer.y = 240 * this._mapScaleMin;
		
		const wordBg = getSprNode("word_bg");
		wordBg.x = wordLayer.width / 2;
		wordLayer.addChild(wordBg);
		wordBg.scaleY = wordLayer.height / wordBg.height;
		wordBg.scaleX = wordLayer.width / wordBg.width;
		wordBg.opacity = 0;
		wordLayer.wordBg = wordBg;

		wordLayer.opacity = 0;
		cc.tween(wordLayer)
			.to(showTime, { opacity: 255 }, { easing: "sineOut" })
			.start();
	},

	showPic() {

		const showTime = 1;

		const picBg = getSprNode("bg_board");
		picBg.scale = this._mapScaleMin;
		this.canvas.addChild(picBg);

		picBg.y = -170 * this._mapScaleMin;

		getSprNodeByUrl(this.curQues.pic_url, (spr) => {

			const sprNode = spr.node;
			sprNode.parent = picBg;
			// sprNode.color = cc.Color.BLACK;
			sprNode.x = -2;
			sprNode.y = 2;


			const edge = 44;
			const maxW = picBg.width - edge;
			const maxH = picBg.height - edge;
			setSprNodeMaxLen(sprNode, maxW, maxH);

			// sprNode.scaleX = maxW / sprNode.width;
			// sprNode.scaleY = maxH / sprNode.height;
		})

		picBg.baseY = picBg.y;
		picBg.y = -this.canvas.height;

		cc.tween(picBg)
			.to(showTime, { y: picBg.baseY }, { easing: "cubicOut" })
			.call(() => {
				this.playPicAudio(picBg);
			})
			.start();
	},

	playPicAudio(picBg) {
		const audioUrl = this.curQues.audio_url;
		playAudioByUrl(audioUrl, () => {
			this.hideAudioWave();
			this.hidePic();
		})

		this.curPicBg = picBg;

		this.isShowWave = true;
		this.showAudioWave();
	},

	wordToTop() {

		const time = 1
		const topY = 400 * this._mapScaleMin;

		const targetS = this.wordLayer.scale * 0.5;
		cc.tween(this.wordLayer)
			.to(time, { x: -this.wordLayer.width / 2 * targetS, y: topY, scale: targetS }, { easing: "cubicInOut" })
			.start();

		const { normalLayer, strokeLayer, wordBg } = this.wordLayer;

		cc.tween(normalLayer)
			.to(time, { opacity: 0 }, { easing: "cubicIn" })
			.call(() => {
				normalLayer.active = false;

				cc.tween(wordBg)
				.to(time / 2, { opacity: 255 }, { easing: "cubicOut" })
				.start();
			})
			.start();
		cc.tween(strokeLayer)
			.to(time, { opacity: 255 }, { easing: "cubicOut" })
			.start();

	
	},

	async hidePic() {

		await asyncDelay(1);
		if (this.isDestroy) {
			return;
		}

		// this.wordToCenter();

		this.wordToTop();
		this.showColorLayer();
		this.showLetter();

		const time = 1;
		const picBg = this.curPicBg;
		cc.tween(picBg)
			.to(time, { y: -this.canvas.height }, { easing: "cubicInOut" })
			.call(() => {
				picBg.removeFromParent();
			})
			.start();
	},

	showLetter() {


		console.log('this._status.currentLetter: ', this._status.currentLetter);

		this.createLetterPage(this._status.currentLetter);

		// this.initTitle();

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

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

		// if (this.data.debugMode) {
		// 	this.initDebugMode();
		// } else {
		// this.initGuideHand();
		// }

	},


	async showColorLayer() {

		await asyncDelay(1)
		if (this.isDestroy) {
			return;
		}

		const colorLayer = this.colorLayer;
		colorLayer.active = true;


		const time = 0.7;
		const targetX = this.canvas.width / 2 - colorLayer.width / 2 * colorLayer.scale + 1;
		cc.tween(colorLayer)
			.to(time, { x: targetX }, { easing: "cubicOut" })
			.start();
	},


	showAudioWave() {

		if (!this.isShowWave) {
			return;
		}

		const waveLeft = this.getWaveLeft();
		const waveRight = this.getWaveRight();


		waveLeft.opacity = 0;
		waveRight.opacity = 0;

		const maxS = waveLeft.scale * 1.5;
		const moveX = 300 * this._mapScaleMin;
		const time = 1.5;
		cc.tween(waveLeft)
			.to(time, { x: waveLeft.x - moveX, scale: maxS })
			.start();
		cc.tween(waveLeft)
			.to(time / 2, { opacity: 255 })
			.to(time / 2, { opacity: 0 })
			.call(() => {
				waveLeft.removeFromParent();
			})
			.start();

		cc.tween(waveRight)
			.to(time, { x: waveRight.x + moveX, scale: -maxS })
			.start();
		cc.tween(waveRight)
			.to(time / 2, { opacity: 255 })
			.to(time / 2, { opacity: 0 })
			.call(() => {
				waveRight.removeFromParent();
			})
			.start();

		delayCall(0.6, () => {
			if (this.isDestroy) {
				return;
			}
			this.showAudioWave();
		})

	},

	hideAudioWave() {
		this.isShowWave = false;
	},

	getWaveLeft() {
		const offX = 80 * this._mapScaleMin;
		const waveLeft = getSprNode("wave");
		this.canvas.addChild(waveLeft);
		waveLeft.scale = this._mapScaleMin;
		waveLeft.x = this.curPicBg.x - this.curPicBg.width / 2 * this.curPicBg.scale - offX;
		waveLeft.y = this.curPicBg.y;
		return waveLeft;
	},

	getWaveRight() {
		const offX = 80 * this._mapScaleMin;
		const waveRight = getSprNode("wave");
		this.canvas.addChild(waveRight);
		waveRight.scale = this._mapScaleMin;
		waveRight.x = this.curPicBg.x + this.curPicBg.width / 2 * this.curPicBg.scale + offX;
		waveRight.y = this.curPicBg.y;
		waveRight.scaleX *= -1;
		return waveRight;
	},



	initGuideHand() {

		const handNode = this.getHand();
		this.canvas.addChild(handNode, 20);

		// const localPos = exchangeNodePos(this.canvas, arrowList[0]);
		const letter = this._status.currentLetter;
		const penIdx = this._status._currentPenIdx;
		const penPointList = letterData[letter][penIdx].map(pos => cc.v2(pos.x, pos.y));
		const debugBase = cc.find('Canvas/UIBase/DebugBase');
		const drawBaseComponent = debugBase.getComponent('hy_write_word_DebugDrawBase');
		const pointList = drawBaseComponent.interpolatePos(penPointList, 100);
		const LetterLayer = cc.find('Canvas/bg/LetterLayer');

		pointList.length = 4;

		this.handPosArr = [];
		pointList.forEach(p => {
			const localpos = this.canvas.convertToNodeSpaceAR(LetterLayer.convertToWorldSpaceAR(cc.v2(p.x, p.y)));
			this.handPosArr.push(localpos);
		})

		// const localpos = this.canvas.convertToNodeSpaceAR(LetterLayer.convertToWorldSpaceAR(cc.v2(pointList[0].x, pointList[0].y)));
		handNode.x = this.handPosArr[0].x;
		handNode.y = this.handPosArr[0].y;
		this.handNode = handNode;

		this.showGuideHand();
	},

	showGuideHand() {

		console.log('this.handPosArr: ', this.handPosArr);
		const duration = 1.5; // 运动持续时间

		const bezierTo = cc.bezierTo(duration, this.handPosArr).easing(cc.easeCubicActionInOut())

		const basePos = this.handNode.position;


		this.handNode.opacity = 0;
		const seq = cc.tween()
			.call(() => {
				this.handNode.position = basePos;

				this.handNode.hand2.active = false;
				this.handNode.hand1.active = true;
			})
			.to(0.5, { opacity: 255 })
			.call(() => {
				this.handNode.hand2.active = true;
				this.handNode.hand1.active = false;
			})
			.delay(0.2)
			.then(bezierTo)
			.to(0.5, { opacity: 0 })
			.union()
			.start();

		this.handTween = cc.tween(this.handNode)
			.then(seq.repeatForever())
			.start();

	},

	cleanHand() {
		if (this.handTween) {
			this.handTween.stop(); // 停止 Tween 动画
			this.handTween = null;

			this.handNode.removeFromParent();
		}
	},

	getHand() {
		const node = new cc.Node();
		const hand1 = getSprNode("icon_hand1");
		const hand2 = getSprNode("icon_hand2");

		hand1.anchorY = 1;
		hand2.anchorY = 1;
		hand1.anchorX = 0.2;
		hand2.anchorX = 0.2;

		node.addChild(hand1);
		node.addChild(hand2);
		hand2.active = false;

		node.hand1 = hand1;
		node.hand2 = hand2;

		return node;
	},

	initTopPart() {


		const layer_back = cc.find("Canvas/layer_back");
		this.btn_back = cc.find('btn_back', layer_back);
		this.label_title = cc.find('label_title', layer_back);
		this.img_npc_voice = cc.find('img_npc_voice', this.label_title);

		this.label_title.active = false;
		setTimeout(() => {
			if (this.isDestroy) {
				return;
			}
			this.label_title.active = true;
		}, 1);

		if (this.data.npcTitle) {
			const label = this.label_title.getComponent(cc.Label);
			label.string = this.data.npcTitle;
		}

		console.log('layer_back: ', layer_back);
		console.log('this.label_title: ', this.label_title);

		const picNode = cc.find('p1', this.img_npc_voice);
		const animNode = cc.find("p2", this.img_npc_voice);
		const anim = animNode.getComponent(cc.Animation);


		if (!this.data.npcAudio) {
			this.img_npc_voice.active = false;
			this.startShow();
		} else {


			this.img_npc_voice.on('touchstart', () => {
				this.npcVoiceClick();
			})

			this.npcVoiceClick(() => {
				this.startShow();
			});
		}


		this.btn_back.on('touchstart', () => {
			global?.middleLayer?.exitGame();
		})

	},

	npcVoiceClick(cb = null) {

		const picNode = cc.find('p1', this.img_npc_voice);
		const animNode = cc.find("p2", this.img_npc_voice);
		const anim = animNode.getComponent(cc.Animation);

		picNode.active = false;
		animNode.active = true;
		anim.play('hy_tip');

		playAudioByUrl(this.data.npcAudio, () => {
			if (this.isDestroy) {
				return;
			}

			cb && cb();
			// picNode.active = true;
			// animNode.active = false;
			// this.maskNode.active = false;
		});
	},


	initColorPen() {

		const colorDataArr = [
			{ res: 'btn_red', colorText: "f74944", chosenRes: "btn_red_chosen" },
			{ res: 'btn_orange', colorText: "fa840a", chosenRes: "btn_orange_chosen" },
			{ res: 'btn_yellow', colorText: "fddb49", chosenRes: "btn_yellow_chosen" },
			{ res: 'btn_green', colorText: "84e330", chosenRes: "btn_green_chosen" },
			{ res: 'btn_blue', colorText: "41c4f8", chosenRes: "btn_blue_chosen" },
			{ res: 'btn_purple', colorText: "b687f4", chosenRes: "btn_purple_chosen" },
			{ res: 'btn_pink', colorText: "f786b0", chosenRes: "btn_pink_chosen" },
			{ res: 'btn_brown', colorText: "d17919", chosenRes: "btn_brown_chosen" },
			{ res: 'btn_colors', colorText: "", chosenRes: "btn_colors_chosen" },
		]
		const layer = cc.find("Canvas/bg_color");
		layer.zIndex = 5;
		layer.x = this.canvas.width / 2 + layer.width / 2;
		this.colorLayer = layer;

		const baseX = -layer.width / 2 + 95;
		const baseY = layer.height / 2 - 95;
		const distance = 140;

		let row = 0;
		let col = 0;

		for (let i = 0; i < colorDataArr.length; i++) {

			if (col >= 2) {
				col = 0
				row++;
			}

			const oneColorData = colorDataArr[i];

			const colorBtn = getSprNode(oneColorData.res);
			colorBtn.x = baseX + col * distance;
			colorBtn.y = baseY - row * distance;
			layer.addChild(colorBtn);

			const chosenBtn = getSprNode(oneColorData.chosenRes);
			colorBtn.parent.addChild(chosenBtn);
			chosenBtn.x = colorBtn.x;
			chosenBtn.y = colorBtn.y;
			chosenBtn.active = false;
			colorBtn.chosenBtn = chosenBtn;

			colorBtn.on('touchstart', () => {
				this.colorText = oneColorData.colorText;
				if (!this.colorText) {
					this.isRainbow = true;
				} else {
					this.isRainbow = false;
				}

				if (this.curChosenBtn) {
					this.curChosenBtn.chosenBtn.active = false;
					this.curChosenBtn.active = true;
				}
				this.curChosenBtn = colorBtn;
				chosenBtn.active = true;
				colorBtn.active = false;

				playAudio(this.color_click_Clip);
			})

			col++;

		}


	},

	initBg() {
		const bg = cc.find("Canvas/bg");
		bg.scale = this._mapScaleMax;

		// const bgBottom = cc.find("Canvas/bg_bottom");
		// bgBottom.scale = bg.scale;

		// const maskNode = cc.find("Canvas/maskNode");
		// maskNode.scale = bg.scale;
		// maskNode.zIndex = 10;
		// maskNode.active = true;
		// this.maskNode = maskNode;

		this.bg = bg;
	},


	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('hy_write_word_DebugDrawBase');
		drawBaseComponent.letter = this._status.currentLetter;
		await asyncDelay(0.01);
		drawBaseComponent.setDrawNode(cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode'));
	},

	initListener() {

		return;

		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) {

		if (this.isGameFirst) {
			const newLetterLayer = cc.instantiate(cc.find(`LetterLayer`));
			newLetterLayer.x = 0;
			newLetterLayer.y = -100 * this._mapScaleMin;
			newLetterLayer.parent = cc.find('Canvas/bg');
			newLetterLayer.scale = 1 / this.bg.scale

			newLetterLayer.opacity = 0;
			cc.tween(newLetterLayer)
				.to(1, { opacity: 255 }, { easing: "cubicIn" })
				.call(() => {
					this.initGuideHand();
				})
				.start();

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

			const letterSmall = newLetterLayer.getChildByName('letterSmall');
			letterSmall.getComponent(cc.Sprite).spriteFrame = this.getLetterSpriteFrame(letter, false);

			this.isGameFirst = false;
		} else {



			const curLetterLayer = cc.find('Canvas/bg/LetterLayer');
			curLetterLayer.name = 'oldLetterLayer';


			const newLetterLayer = cc.instantiate(curLetterLayer);
			newLetterLayer.x = 0;// this.canvas.width;
			newLetterLayer.name = 'LetterLayer';
			newLetterLayer.parent = curLetterLayer.parent;

			newLetterLayer.opacity = 0;
			cc.tween(newLetterLayer)
				.to(1, { opacity: 255 }, { easing: "cubicIn" })
				.call(() => {
					// this.initGuideHand();
				})
				.start();



			this._status.currentLetter = this.letterList[this.letterListIndex]

			// const newLetterLayer = cc.find('Canvas/bg/LetterLayer');
			const drawBase = newLetterLayer.getChildByName('DrawBase');
			drawBase.getComponent(cc.Mask).spriteFrame = this.getLetterSpriteFrame(this._status.currentLetter);

			const letterSmall = newLetterLayer.getChildByName('letterSmall');
			letterSmall.getComponent(cc.Sprite).spriteFrame = this.getLetterSpriteFrame(this._status.currentLetter, false);

		}





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

	getLetterSpriteFrame(letter, isBold = true) {

		let subKey = '';
		if (!isBold) {
			subKey = '_s'
		}


		if (letter == letter.toUpperCase()) {
			// return cc.find(`Letters/${letter}_big` + subKey).getComponent(cc.Sprite).spriteFrame;
			return cc.find(`Letters/big${subKey}/${letter}`).getComponent(cc.Sprite).spriteFrame;
		}
		return cc.find(`Letters/small${subKey}/${letter}`).getComponent(cc.Sprite).spriteFrame;

		// return cc.find(`Letters/${letter.toUpperCase()}_small` + subKey).getComponent(cc.Sprite).spriteFrame;
		// return cc.find(`Letters/small${subKey}/${letter.toUpperCase()}` + subKey).getComponent(cc.Sprite).spriteFrame;
	},

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

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

	createShark() {

		const letter = this._status.currentLetter;
		if (!letterData[letter][0]) {
			return;
		}

		let shark = cc.instantiate(cc.find('Icons/draw_arrow'));
		// 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');

		// console.log('shark.parent.x: '+ shark.parent.x);

		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));

		cc.tween(shark)
			.to(0.7, { opacity: 255 }, { easing: "cubicIn" })
			.start();

	},

	onSharkTouchStart(event) {

		this.cleanHand();

		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);

		playAudio(this.line_start_Clip);

		this.isCheckPlayMoveAudio = true;
		// cc.audioEngine.play(this.audio_press, false, 1);
	},

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

		this.curMoveLocation = location;

		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);

			this._status._currentPointIdx = 0;
			this.updateCurrentGraph(true);
			this.moveSharkBack(event.target);
			this.showArrows();
			return;
		}

		if (this.isRainbow) {

			this.setColorTextForRainbow(cc.v2(shark.x, shark.y));
		}

		const drawNode = cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode');
		this.drawALine(drawNode, shark.lastPos, cc.v2(shark.x, shark.y), cc.Color.fromHEX(new cc.Color(), this.colorText));
		// 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();
		}


		if (!this.moveAudioClipId) {
			this.moveAudioClipId = playAudio(this.line_move_Clip, () => {
				console.log('this.moveAudioClipId = null;')
				this.moveAudioClipId = null;
			})
		}

	},

	setColorTextForRainbow(curPos) {

		const rainbowColors = [
			"f74944",
			"fddb49",
			"41c4f8",
			"84e330",
			"b687f4",
		]

		if (this.rainbowColorsIdx == null) {
			this.rainbowColorsIdx = 0;
		}
		if (this.rainbowLen == null) {
			this.rainbowLen = 0;
			this.rainbowlenTarget = RandomInt(5, 40);
		}


		if (this.rainbowLastPos) {
			this.rainbowLen += cc.Vec2.distance(this.rainbowLastPos, curPos);

			if (this.rainbowLen >= this.rainbowlenTarget) {
				this.colorText = rainbowColors[this.rainbowColorsIdx];
				this.rainbowLen = 0;
				this.rainbowlenTarget = RandomInt(5, 40);

				this.rainbowColorsIdx++;
				if (this.rainbowColorsIdx >= rainbowColors.length) {
					this.rainbowColorsIdx = 0;
				}
			}
		} else {
			this.colorText = rainbowColors[0];
		}

		this.rainbowLastPos = curPos;
	},

	onSharkTouchEnd(event) {

		const shark = event.target;
		// this.checkOnEndPoint(shark);
		this.checkNoPoint(shark);

		this.isCheckPlayMoveAudio = false;
		this.oldMoveLocaltion = false;

		// const shark = event.target;
		shark.lastPos = null;
		shark.startPos = null;

		this.curMoveLocation = null;

		// this._status._currentPointIdx = 0;
		// this.updateCurrentGraph(true);
		// this.moveSharkBack(event.target);
		// this.showArrows();
	},


	checkNoPoint(shark) {

		if (!this.curMoveLocation) {
			return;
		}

		for (let i=0; i<this._arrowList.length; i++) {
			if (this._arrowList[i].active) {
				return;
			}
		}

		const letter = this._status.currentLetter;

		this.changeCurDrawNode();

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

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

		if (this._status._currentPenIdx < letterData[letter].length) {

				
			this.removeStar();
			this.createArrows();
			this.createStar();

			playAudio(this.line_end_Clip);

			this.moveSharkBack(shark);

		} else {

			this.oneLetterEnd(shark);

		}

		return;




		// console.log(" in checkOnEndPoint")
		// 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;
		// }


		
			
		// this._status._currentPointIdx++;

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

		// 	this.changeCurDrawNode();

		// 	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();

		// 		playAudio(this.line_end_Clip);

		// 	} else {

		// 		this.oneLetterEnd(shark);

		// 	}

		// 	this.curMoveLocation = null;



		// 	this.updateCurrentPointIdx(shark);


		// 	this._status._currentPointIdx = 0;
		// 	this.moveSharkBack(shark);

		// }
		

		// this.updateArrows(shark);



	},
	



	checkOnEndPoint(shark) {

		if (!this.curMoveLocation) {
			return;
		}

		console.log(" in checkOnEndPoint")
		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];

		let checkDis = this.checkDis;
		if (this._status._currentPointIdx == letterData[letter][penIdx].length - 2) {
			checkDis *= 1.5;
		} else {
			return;
		}


		const hasStar = this._arrowList.find(it => {
			return it.active;
		})

		console.log('hasStar: ', hasStar);


		if (this.getDistance(shark, nextPoint) < checkDis) {

			this._status._currentPointIdx++;

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

				this.changeCurDrawNode();

				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();

					playAudio(this.line_end_Clip);
					
				} else {

					this.oneLetterEnd(shark);
				}

				this.curMoveLocation = null;

				// this.updateCurrentGraph(true);



				this.updateCurrentPointIdx(shark);


				this._status._currentPointIdx = 0;
				this.moveSharkBack(shark);

			}
		}

		this.updateArrows(shark);
	},


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

		// console.log("penIdx: " + penIdx);
		// console.log("pointIdx: " + pointIdx);
		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);

			// console.log('~angle: ', angle);
		}
		// }

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

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

	updateCurrentPointIdx(shark) {
		// console.log(" in updateCurrentPointIdx")
		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];

		let checkDis = this.checkDis;
		if (this._status._currentPointIdx == letterData[letter][penIdx].length - 2) {
			checkDis /= 2;
		}

		if (this.getDistance(shark, nextPoint) < checkDis) {
			// console.log(" 0000 ");
			this._status._currentPointIdx++;

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

				this.changeCurDrawNode();

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

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

				// this.showFlower(shark);
				if (this._status._currentPenIdx < letterData[letter].length) {

					// console.log('1111');
					this.removeStar();
					this.createArrows();
					this.createStar();

					playAudio(this.line_end_Clip);
					this.curMoveLocation = null;

				} else {

					// console.log('2222');

					this.oneLetterEnd(shark)
					this.curMoveLocation = null;


					this.isCheckPlayMoveAudio = false;
					this.oldMoveLocaltion = false;

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

					return;
				}
				// this.updateCurrentGraph(true);



				this.updateCurrentPointIdx(shark);


				this._status._currentPointIdx = 0;
				this.moveSharkBack(shark);

			}
		}
	},

	oneLetterEnd(shark) {
		this.removeStar();

		this.showOver(shark);

		// setTimeout(() => {
		// 	if (this.isDestroy) {
		// 		return;
		// 	}
		// 	if (this.letter_end_Clip) {
		// 		playAudio(this.letter_end_Clip);
		// 	}
		// }, 260);

		
		this.changeNewLetter();
		
	},

	changeNewLetter() {

		const curLetterLayer = cc.find('Canvas/bg/LetterLayer');
		curLetterLayer.name = 'oldLetterLayer';


		const newLetterLayer = cc.instantiate(curLetterLayer);
		newLetterLayer.x = this.canvas.width;
		newLetterLayer.name = 'LetterLayer';
		newLetterLayer.parent = curLetterLayer.parent;

		// cc.tween(curLetterLayer)
		// 	.to(2.1, {x: -this.canvas.width}, {easing: "sineIn"})
		// 	.call(() => {
		// 		curLetterLayer.removeFromParent();
		// 	})
		// 	.start();


		this.oldLetterToTop(curLetterLayer);


		if (this.letterListIndex < this.letterList.length - 1) {


			cc.tween(newLetterLayer)
				.to(2, { x: 0 }, { easing: "sineOut" })
				.start();
		}


		this.refreshNewLetter();

	},

	oldLetterToTop(newLetter) {

		playAudio(this.move_Clip);


		const targetLetter = this.wordLayer.strokeArr[this.letterListIndex];

		const oldSizeW = newLetter.getBoundingBoxToWorld().width;

		const pos = exchangeNodePos(targetLetter.parent, newLetter)
		newLetter.parent = targetLetter.parent;
		newLetter.x = pos.x;
		newLetter.y = pos.y;


		const curSizeW = newLetter.getBoundingBoxToWorld().width;
		newLetter.scale = oldSizeW / curSizeW;


		const time = 0.9;
		cc.tween(newLetter)
			.to(time, { x: targetLetter.x, y: targetLetter.y, scale: targetLetter.scale }, { easing: "expoOut" })
			.start();


		cc.tween(targetLetter)
			.to(time, { opacity: 0 }, { easing: "cubicIn" })
			.start();
		// baseNode.convertToNodeSpaceAR(targetNode._parent.convertToWorldSpaceAR(cc.v2(targetNode.x, targetNode.y)));
	},

	// copyLetter() {

	// 	// let nodeToCapture = cc.find("Canvas/YourNodeToCapture"); // 替换成你要截图的节点的路径
	// 	// let texture = new cc.RenderTexture();
	// 	// texture.initWithSize(cc.visibleRect.width, cc.visibleRect.height);
	// 	// texture.begin();
	// 	// nodeToCapture._sgNode.visit(); // 将要截图的节点的底层渲染节点进行访问
	// 	// texture.end();

	// 	// let spriteNode = new cc.Node(); // 创建一个新节点来显示截图
	// 	// let sprite = spriteNode.addComponent(cc.Sprite);
	// 	// sprite.spriteFrame = new cc.SpriteFrame(texture);
	// 	// spriteNode.parent = cc.director.getScene(); // 将新节点添加到场景中

	// },

	wordToCenter() {
		const time = 1
		const centerY = 0 * this._mapScaleMin;

		const targetS = this.wordLayer.baseS
		cc.tween(this.wordLayer)
			.to(time, { x: -this.wordLayer.width / 2 * targetS, y: centerY, scale: targetS }, { easing: "cubicOut" })
			.call(() => {
				const particleNode = new cc.Node();
				this.canvas.addChild(particleNode);
				particleNode.scale = 1.5;

				delayCall(0.2, () => {
					if (this.isDestroy) {
						return;
					}
					this.showLightParticle(particleNode);
				})
				playAudio(this.word_finish_Clip);

				delayCall(1, () => {
					if (this.isDestroy) {
						return;
					}

					this.playWordAudio(() => {
						if (this.isDestroy) {
							return;
						}
						this.showGold(() => {
							if (this.isDestroy) {
								return;
							}
							this.hideWordLayer();
						});
					}) 
					
				})
			})
			.start();

		cc.tween(this.wordLayer.wordBg)
			.to(time / 2, {opacity: 0}, {easing: "cubicOut"})
			.start();

	},

	hideWordLayer() {
		cc.tween(this.wordLayer)
			.to(0.7, { opacity: 0 }, { easing: "cubicIn" })
			.call(() => {
				if (this.isDestroy) {
					return;
				}
				this.startNewWord();
			})
			.start();
	},

	startNewWord() {
		this.wordArrIndex++;
		this.initCurQues();

		if (!this.curQues) {
			this.gameEnd();
			return;
		}

		this.showWord();
		this.showPic();
	},

	gameEnd() {
		// await asyncDelay(1);
		this.showFinish();
	},


	async oneWordEnd() {

		await asyncDelay(1.3);
		this.wordToCenter();


		// setTimeout(() => {
		// 	if (this.isDestroy) {
		// 		return;
		// 	}
		// 	if (this.letter_end_Clip) {
		// 		playAudio(this.letter_end_Clip);
		// 	}
		// }, 260);

		// this.showLightParticle();

		// this.showGold(() => {

		// });

		// this.showFinish();

	},

	showLightParticle(showNode) {
		const lightCenter = getSprNode("particle/light_center");
		const lightCircle = getSprNode("particle/light_circle");
		// const lightDot = getSprNode("particle/light_dot");

		const time = 1.5;
		const dotCount = 30;
		const dotMinLen = lightCircle.width / 8;
		const dotMaxLen = lightCircle.width / 1.5;
		const particleCount = 30;
		const particleMinS = 0.5;
		const particleMaxS = 1;

		lightCenter.parent = showNode;
		lightCenter.opacity = 0;
		cc.tween(lightCenter)
			.to(time / 4, { opacity: 255, scale: 1 }, { easing: "expoOut" })
			.to(time / 4, { opacity: 0, scale: 1 }, { easing: "cubicOut" })
			.start();

		lightCircle.parent = showNode;
		lightCircle.opacity = 0;
		lightCircle.scale = 0.5;
		cc.tween(lightCircle)
			.to(time / 3, { opacity: 255 })
			.to(time / 3, { opacity: 0 })
			.start();
		cc.tween(lightCircle)
			.to(time, { scale: 1.5 }, { easing: "expoOut" })
			.start();

		for (let i = 0; i < dotCount; i++) {
			const dot = getSprNode("particle/light_dot");
			dot.parent = showNode;

			const randomDir = Math.random() * 360;
			const randomLen = dotMinLen + (dotMaxLen - dotMinLen) * Math.random();
			const randomPos = getPosByAngle(randomDir, randomLen);
			const targetS = randomLen / dotMaxLen;
			dot.scale = 0;

			const startPos = getPosByAngle(randomDir, randomLen / 3);
			dot.x = startPos.x;
			dot.y = startPos.y;

			cc.tween(dot)
				.to(time * 1.2, { x: randomPos.x, y: randomPos.y, scale: targetS }, { easing: "expoOut" })
				.call(() => {
					showNode.removeFromParent();
				})
				.start();

			const disappearTime = (time / 4 + time / 4 * 3 * Math.random()) * 1.2;
			cc.tween(dot)
				.to(disappearTime, { opacity: 0 }, { easing: "cubicIn" })
				.start();
		}

		for (let i = 0; i < particleCount; i++) {
			const id = Math.ceil(Math.random() * 14);
			const oneParticle = getSprNode("particle/" + id);
			showNode.addChild(oneParticle);

			const randomDir = Math.random() * 360;
			const randomLen = dotMinLen + (dotMaxLen - dotMinLen) * Math.random();
			const randomPos = getPosByAngle(randomDir, randomLen / 3 * 2);

			const startPos = getPosByAngle(randomDir, randomLen / 3 * 2);
			oneParticle.x = startPos.x;
			oneParticle.y = startPos.y;

			const randomS = particleMinS + (particleMaxS - particleMinS) * Math.random();
			oneParticle.scale = randomS;

			cc.tween(oneParticle)
				.to(time, { opacity: 0, angle: -360 + Math.random() * 720 })
				.start();

			const actionBy = cc.jumpBy(time, randomPos.x, randomPos.y, 50, 1);
			oneParticle.runAction(actionBy);
		}


	},


	async refreshNewLetter() {


		this.letterListIndex++;
		if (this.letterListIndex >= this.letterList.length) {

			this.oneWordEnd();
			// await asyncDelay(1);
			// this.showFinish();
			return;
		}


		this._status.currentLetter = this.letterList[this.letterListIndex]

		const newLetterLayer = cc.find('Canvas/bg/LetterLayer');
		const drawBase = newLetterLayer.getChildByName('DrawBase');
		drawBase.getComponent(cc.Mask).spriteFrame = this.getLetterSpriteFrame(this._status.currentLetter);

		const letterSmall = newLetterLayer.getChildByName('letterSmall');
		letterSmall.getComponent(cc.Sprite).spriteFrame = this.getLetterSpriteFrame(this._status.currentLetter, false);


		this.createShark();
		this.createArrows();
		this.createStar();
	},

	changeCurDrawNode() {
		console.log(" in changeCurDrawNode")

		const canvas = cc.find("Canvas");

		// const drawNode = cc.find('Canvas/bg/LetterLayer');
		// const oneLineNode = cc.instantiate(drawNode);
		// oneLineNode.x = 1200
		// oneLineNode.y = 800;


		const drawNodeNew = cc.find('Canvas/bg/LetterLayer/DrawBase/DrawNode');
		drawNodeNew.name = 'oldNode';


		const drawNodeNew2 = cc.instantiate(drawNodeNew);
		drawNodeNew2.name = 'DrawNode';
		drawNodeNew2.parent = cc.find('Canvas/bg/LetterLayer/DrawBase');

		// oneLineNode.y = 0
		// canvas.addChild(oneLineNode, 20);
		// oneLineNode.parent = cc.find('Canvas/bg/LetterLayer/DrawBase');
		// oneLineNode.zIndex = drawNode.zIndex;

		this.updateCurrentGraph(true);
	},

	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('hy_write_word_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;
	},



	playWordAudio(callback) {
		const audio_url = this.curQues.audio_url;
		playAudioByUrl(audio_url, () => {
			callback && callback();
		})
	
	},
	
	async showGold(cb) {


		let showCount = 0;
		// const goldDisTime = 260;
		const showGoldAudio = async () => {

			await asyncDelay(0.16);

			if (this.isDestroy) {
				return;
			}
			if (showCount >= 3) {
				return;
			}
			if (this.letter_end_Clip) {
				playAudio(this.letter_end_Clip);
			}

			showCount++;
			// setTimeout(() => {
				showGoldAudio();
			// }, goldDisTime);
		}
		showGoldAudio();


		console.log(' in showGold')
		const goldAnim = cc.instantiate(cc.find('Canvas/res/anim/gold_anim'));
		goldAnim.active = true;
		goldAnim.parent = this.particleLayer;
		this.particleLayer.active = true;
		this.particleLayer.zIndex = 10;
		appearAnim(this.particleLayer, 0.3);

		console.log('goldAnim: ', goldAnim);

		await asyncPlayDragonBoneAnimation(goldAnim, 'three', 1);

		const disappearTime = 0.7;
		disappearAnim(goldAnim, disappearTime);
		disappearAnim(this.particleLayer, disappearTime, () => {
			this.particleLayer.active = false;
		});

		delayCall(disappearTime, () => {
			if (this.isDestroy) {
				return;
			}
			cb();

		})

		// playAudio(this.letter_end_Clip);



	},

	async showFinish() {


		const { word_count, sentence_count, zi_count } = this.data;
		const finishData = {
			word_count: word_count || 0,
			sentence_count: sentence_count || 0,
			zi_count: zi_count || 0,
			score: this.letterList.length * 3
		}
		onHomeworkFinish(finishData)


		const goldNum = this.wordArr.length * 3;
		global?.middleLayer?.saveGolds(goldNum);
		global?.middleLayer?.goNextPage();


		return;


		console.log(' in showFinish')
		const finishAnim = cc.instantiate(cc.find('Canvas/res/anim/hy_finish'));
		finishAnim.active = true;

		finishAnim.y = -100;

		const bgFinish = getSprNode("bg_finish");
		finishAnim.addChild(bgFinish);

		const labelLayer = new cc.Node();

		const labelNode = new cc.Node();
		const label = labelNode.addComponent(cc.Label);
		label.string = "恭喜你获得";
		labelLayer.addChild(labelNode);
		labelNode.anchorX = 0;

		const labelIcon = getSprNode("icon_coin");
		labelLayer.addChild(labelIcon);
		labelIcon.y = 10;
		labelIcon.anchorX = 0;

		const labelNode2 = new cc.Node();
		const label2 = labelNode2.addComponent(cc.Label);
		label2.string = "x" + this.letterList.length * 3;
		labelLayer.addChild(labelNode2);
		labelNode2.anchorX = 0;

		const distance = 10;
		setTimeout(() => {
			if (this.isDestroy) {
				return;
			}
			labelLayer.width = labelNode.width + labelIcon.width + labelNode2.width + distance * 2;
			labelLayer.x = -labelLayer.width / 2;
			labelIcon.x = distance + labelNode.width;
			labelNode2.x = labelIcon.x + labelIcon.width + distance;

		}, 1);

		bgFinish.addChild(labelLayer);
		appearAnim(labelLayer, 0.3);

		const finishLayer = cc.find("Canvas/finishLayer")
		finishLayer.addChild(finishAnim, 2);

		finishLayer.active = true;
		appearAnim(finishLayer, 0.3, () => {
			playAudio(this.finish_Clip);
		});

		console.log('finishAnim: ', finishAnim);

		const finishLight = getSprNode('bg_finishlight');
		finishLayer.addChild(finishLight);

		const rotateAction = cc.repeatForever(cc.rotateBy(5, 360));
		finishLight.runAction(rotateAction);


		await asyncPlayDragonBoneAnimation(finishAnim, 'finish', 1);

		const replayBtn = getSprNode("btn_replay");
		finishLayer.addChild(replayBtn);
		replayBtn.x = -400;
		replayBtn.y = -270;


		const nextBtn = getSprNode("btn_next");
		finishLayer.addChild(nextBtn);
		nextBtn.x = -replayBtn.x;
		nextBtn.y = replayBtn.y;

		replayBtn.on('touchstart', () => {
			global.middleLayer.reloadBundle();
		})

		nextBtn.on("touchstart", () => {
			const { index, length } = global.middleLayer.getPageInfo();
			if (index >= length - 1) {
				global.middleLayer.goNextCross(); // 跳转到下一关卡
			} else {
				global.middleLayer.goNextPage();
			}
		})

		appearAnim(replayBtn);
		appearAnim(nextBtn);
	},

	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('hy_write_word_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('hy_write_word_DebugDrawBase');
		const pointList = drawBaseComponent.interpolatePos(penPointList, 10);

		this.removeArrows();

		// console.log('pointList: ', pointList);

		setTimeout(() => {
			if (this.isDestroy) {
				return;
			}
			for (let i = 8; i < pointList.length - 2; 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) < 60) {
					continue;
				}

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


		// 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;
			}

			const letter = this._status.currentLetter;
			const penIdx = this._status._currentPenIdx;
			let checkDis = this.checkDis;
			if (this._status._currentPointIdx == letterData[letter][penIdx].length - 2) {
				checkDis /= 2;
			}

			if (this.getDistance(shark, arrow) < checkDis) {
				arrow.active = false;
				// cc.audioEngine.play(this.audio_write, false, 1);
				// playAudio(this.line_move_Clip)
				break;
			}
		}
	},

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

	createArrow(pos1, centerPos, pos2) {

		// console.log('pos1.x: ' + pos1.x + ', y:' + pos1.y);
		// console.log('pos2.x: ' + pos2.x + ', y:' + pos2.y);

		let line = cc.v2(pos2.x - pos1.x, pos2.y - pos1.y);
		let angle = cc.v2(1, 0).signAngle(line) * (180 / Math.PI);
		// console.log('angle: ', angle);

		const LetterLayer = cc.find('Canvas/bg/LetterLayer');
		const arrow = cc.instantiate(cc.find('Icons/icon_star'));
		// 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/icon_star'));
		star.x = lastPoint.x;
		star.y = lastPoint.y;
		star.parent = LetterLayer;
		star.active = false;
		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;
	},



	update() {
		if (this.isCheckPlayMoveAudio) {

			if (!this.curMoveLocation) {
				return;
			}


			if (!this.oldMoveLocaltion) {
				this.oldMoveLocaltion = this.curMoveLocation;
				return;
			}


			if (!this.moveAudioClipId) {
				return;
			}


			this.checkUpdateCount++;
			if (this.checkUpdateCount < 5) {
				return;
			}
			this.checkUpdateCount = 0;


			const distance = cc.Vec2.distance(this.curMoveLocation, this.oldMoveLocaltion);

			if (distance == 0) {
				cc.audioEngine.stopEffect(this.moveAudioClipId);
				this.moveAudioClipId = null;
			}

			this.oldMoveLocaltion = this.curMoveLocation;

		}
	},

	onDestroy() {
		this.isCheckPlayMoveAudio = false;
		this.isDestroy = true;
	},
});
