import { asyncDelay, asyncTweenTo, onHomeworkFinish } from "../script/util";
import { defaultData } from "../script/defaultData";

cc.Class({

	extends: cc.Component,

	properties: {

	},

	// 生命周期 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;
	},

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

		getData((data, aspect) => {
			console.log('data:', data);
			if (window['air']?.airClassInfo?.user?.classRole == 'tea') {
				this.isTeacher = true;
			}
			this.data = data || this.getDefaultData();
			this.data = JSON.parse(JSON.stringify(this.data))

			console.log('aspect = ', aspect);
			let aspectData = null;
			if (aspect) {
				for (const userData of aspect.all_user) {
					if (userData.aspect) {
						aspectData = JSON.parse(userData.aspect);
						break;
					}
				}
				if (aspectData) {
					this.aspectStatus = aspectData.status;
				}
			}

			this.preloadItem();
		})
	},

	getData(func) {
		if (window && window.courseware) {
			window.courseware.getData(func, 'AK09');
			return;
		}

		const middleLayer = cc.find('middleLayer');
		if (middleLayer) {
			const middleLayerComponent = middleLayer.getComponent('middleLayer');
			middleLayerComponent.getData(func);
			return;
		}

		func(this.getDefaultData());
	},

	getDefaultData() {
		return defaultData;
	},

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

	addPreloadImage() {
		const arr = this.data.options;
		if (arr) {
			for (let i = 0; i < arr.length; i++) {
				this._imageResList.push({ url: arr[i].image });
			}
		}
		// this._imageResList.push({ url: this.data.pic_url });
	},

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

	addPreloadAnima() {

	},


	addServerListener() {
		window.air.onCourseInScreen = (next) => {
			cc.find('Canvas').opacity = 255;
			this.showTemplateStartAnima();
			this.loadEnd();
			next();
		}
	},

	showTemplateStartAnima() {
		const resDragonBone = cc.find("Canvas/res/anima/pageturn")
		const pageturn = cc.instantiate(resDragonBone)
		const canvas = cc.find('Canvas');
		canvas.addChild(pageturn, 100);

		const dragonDisplay = pageturn.getComponent(dragonBones.ArmatureDisplay);
		dragonDisplay.on(dragonBones.EventObject.COMPLETE, () => {

			pageturn.removeFromParent();
		})
		dragonDisplay.playAnimation('pageturn2', 1);
	},

	showTemplateEndAnima() {
		const resDragonBone = cc.find("Canvas/res/anima/pageturn")
		const pageturn = cc.instantiate(resDragonBone)
		const canvas = cc.find('Canvas');
		canvas.addChild(pageturn, 100);
		const dragonDisplay = pageturn.getComponent(dragonBones.ArmatureDisplay);
		dragonDisplay.on(dragonBones.EventObject.COMPLETE, () => {
			cc.tween({})
				.delay(1)
				.call(() => {
					if (window && window.courseware && this.isTeacher) {
						window.courseware.nextPage();
					}
				})
				.start();
		})
		dragonDisplay.playAnimation('pageturn', 1);
	},


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

			console.log('this.loadEnd();');
			this.addServerListener();
			if (window && window["air"]) {
				window["air"].hideAirClassLoading();
			}

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

	sendServerEvent(key, data) {
		console.log('send event: ', key, JSON.stringify(data));
		if (!window.courseware) {
			return;
		}
		window.courseware.sendEvent(key, data, 'AK09');
	},

	loadEnd() {
		this.initData();
		this.initView();
		this.initListener();
	},

	teachFlag: null,
	_status: null,
	initData() {
		if (window.air && window.air.airClassInfo.user.classRole === 'tea') {
			this.teachFlag = true;
		}

		if (this.aspectStatus) {
			this._status = this.aspectStatus;
		} else {
			this._status = {
				options: [{
					selected: false,
				}, {
					selected: false,
				}, {
					selected: false,
				}],
				quesion: {
					selected: false,
				}
			}
		}
	},


	clickedBtn: false,
	initListener() {
		this.initNetworkListener();

		this._status.options.forEach((_, idx) => {
			const btnStarOn = cc.find(`Canvas/bg/book/option/option_${idx}/ImageStarOn`);
			btnStarOn.on('click', () => {
				if (!this.teachFlag) {
					return;
				}
				if(this.clickedBtn){
					return;
				}
				if(this.gameEnd){
					return;
				}
				this.clickedBtn = true;
				this._status.options[idx].selected = true;
				this.sendServerEvent('clickOption', { data: { idx: idx }, status: this._status });
			});
		});

		const questionBtn = cc.find('Canvas/bg/book/question/questionNode/questionLayout/starNode/ImageStarOn');
		questionBtn.on('click', () => {
			if (!this.teachFlag) {
				return;
			}
			if(this.clickedBtn){
				return;
			}
			if(this.gameEnd){
				return;
			}
			this.clickedBtn = true;
			this._status.quesion.selected = true;
			this.sendServerEvent('clickQuestion', { data: null, status: this._status });
		});
	},

	initTestBtns() {
		const testBtn = cc.find('Canvas/testNode/testBtn');

		if (window.courseware) {
			testBtn.active = false;
			return;
		}

		let num = 0;
		testBtn.on('click', () => {
			if (num % 4 == 0) {
				this.showQuestion();
			}
			if (num % 4 == 1) {
				this.hideQuestion();
			}
			if (num % 4 == 2) {
				this.showOption(0);
			}
			if (num % 4 == 3) {
				this.hideOption(0);
			}
			num++;
		});
	},

	initNetworkListener() {
		if (!window.courseware) {
			return;
		}
		window.courseware.onEvent('clickOption', async (data, next) => {
			await this.showOption(data.data.idx);
			await this.hideOption();
			this.updateStatus(data.status);
			this.clickedBtn = false;
			next();
		});
		window.courseware.onEvent('clickQuestion', async (data, next) => {
			await this.showQuestion();
			await this.hideQuestion();
			this.updateStatus(data.status);
			this.clickedBtn = false;
			next();
		});
	},

	initView() {
		this.initBg();
		this.initTips();
		this.initOptions();
		this.initQuesion();
		this.initTestBtns();
	},

	initBg() {

	},

	initTips() {
		const tipNode = cc.find('Canvas/bg/tips');
		tipNode.active = this.teachFlag;
	},

	gameEnd: false,
	isShowTemplateEndAnima: false,
	updateStatus(status) {
		this._status = status;
		this._status.options.forEach((optionData, idx) => {
			const optionNode = cc.find(`Canvas/bg/book/option/option_${idx}`);
			if (!optionNode) {
				return;
			}
			const starOn = cc.find(`ImageStarOn`, optionNode);
			const starOff = cc.find(`ImageStarOff`, optionNode);
			if (optionData.selected) {
				starOn.opacity = 255;
				starOff.opacity = 0;
			} else {
				starOn.opacity = 0;
				starOff.opacity = 255;
			}
		});

		const allOptionSelected = this._status.options.every(optionData => optionData.selected);
		this.gameEnd = this._status.quesion.selected && allOptionSelected;

		if (this.gameEnd && !this.isShowTemplateEndAnima) {
			this.isShowTemplateEndAnima = true;
			cc.tween({}).delay(2).call(() => {
				this.showTemplateEndAnima();
			}).start();
		}


		const questionLayout = cc.find('Canvas/bg/book/question/questionNode/questionLayout');
		if (questionLayout) {
			const starOn = cc.find('starNode/ImageStarOn', questionLayout);
			const starOff = cc.find('starNode/ImageStarOff', questionLayout);
			if (this._status.quesion.selected) {
				starOn.opacity = 255;
				starOff.opacity = 0;
			} else {
				starOn.opacity = 0;
				starOff.opacity = 255;
			}
		}
	},

	initOptions() {
		this.data.options.forEach((optionData, idx) => {
			const imgNode = cc.find(`Canvas/bg/book/option/option_${idx}/image`);
			if (!imgNode) {
				return;
			}
			const labelNode = cc.find(`Canvas/bg/book/option/option_${idx}/label`);
			labelNode.getComponent(cc.Label).string = optionData.word;
			this.getSpriteFrimeByUrl(optionData.image, (sf) => {
				imgNode.getComponent(cc.Sprite).spriteFrame = sf;
			});
		});

		this._status.options.forEach((optionData, idx) => {

			const starOn = cc.find(`Canvas/bg/book/option/option_${idx}/ImageStarOn`);
			const starOff = cc.find(`Canvas/bg/book/option/option_${idx}/ImageStarOff`);

			if (optionData.selected) {
				starOn.opacity = 255;
				starOff.opacity = 0;
			} else {
				starOn.opacity = 0;
				starOff.opacity = 255;
			}
		});
	},

	questionLabelList: null,
	initQuesion() {
		const questionLayout = cc.find('Canvas/bg/book/question/questionNode/questionLayout');

		const starOn = cc.find('starNode/ImageStarOn', questionLayout);
		const starOff = cc.find('starNode/ImageStarOff', questionLayout);
		if (this._status.quesion.selected) {
			starOn.opacity = 255;
			starOff.opacity = 0;
		} else {
			starOn.opacity = 0;
			starOff.opacity = 255;
		}

		this.questionLabelList = [];

		this.data.question.labelLeft.split(' ').forEach((word) => {
			const label = cc.instantiate(cc.find('label'));
			label.getComponent(cc.Label).string = word;
			label.y = 0;
			label.parent = questionLayout;
			this.questionLabelList.push(label);
		});

		const lineNode = cc.instantiate(cc.find('lineNode'));
		lineNode.parent = questionLayout;
		lineNode.y = -20;

		this.data.question.labelRight.split(' ').forEach((word) => {
			const label = cc.instantiate(cc.find('label'));
			label.getComponent(cc.Label).string = word;
			label.y = 0;
			label.parent = questionLayout;
			this.questionLabelList.push(label);
		});
	},

	currentShowOptionIdx: null,
	async showOption(idx) {
		console.log("idx:", idx);
		const optionNode = cc.find(`Canvas/bg/book/option/option_${idx}`);

		if (!optionNode) {
			console.log("!optionNode:");
			return;
		}

		this.currentShowOptionIdx = idx;

		const maskBase = cc.find('Canvas/bg/maskBase');
		const oldPosition = optionNode.getPosition();
		const newPos = maskBase.convertToNodeSpaceAR(
			optionNode.parent.convertToWorldSpaceAR(oldPosition)
		);
		optionNode.parent = maskBase;
		optionNode.setPosition(newPos);
		optionNode.oldPosition = cc.v2(oldPosition.x, oldPosition.y);

		const mask = cc.find('Canvas/bg/maskBase/mask');
		await Promise.all([
			asyncTweenTo(mask, 0.5, { opacity: 255 }),
			asyncTweenTo(optionNode, 0.6, { x: 0, y: 0, scale: 1.7 }, { easing: 'sineInOut' })
		]);

		const imageStarOn = optionNode.getChildByName('ImageStarOn');
		const imageStarOff = optionNode.getChildByName('ImageStarOff');
		
		await Promise.all([
			asyncTweenTo(imageStarOn, 0.2, { opacity: 255 }),
			asyncTweenTo(imageStarOff, 0.2, { opacity: 0 })
		]);
		this.playAudioByNodeName('right');

		const image = optionNode.getChildByName('image');
		await asyncTweenTo(image, 0.1, { angle: 15 }, { easing: 'sineInOut' });
		await asyncTweenTo(image, 0.2, { angle: -15 }, { easing: 'sineInOut' });
		await asyncTweenTo(image, 0.2, { angle: 15 }, { easing: 'sineInOut' });
		await asyncTweenTo(image, 0.2, { angle: -15 }, { easing: 'sineInOut' });
		await asyncTweenTo(image, 0.1, { angle: 0 }, { easing: 'sineInOut' });

		const label = optionNode.getChildByName('label');
		await asyncTweenTo(label, 0.15, { scale: 1.1 }, { easing: 'sineIn' });
		await asyncTweenTo(label, 0.1, { scale: 1 }, { easing: 'sineOut' });
		await asyncDelay(2);
	},

	async hideOption() {
		const idx = this.currentShowOptionIdx;
		if (idx === null) {
			return;
		}
		
		const optionNode = cc.find(`Canvas/bg/maskBase/option_${idx}`);
		if (!optionNode) {
			console.log('optionNode is null');
			return;
		}
		const optionBase = cc.find(`Canvas/bg/book/option`);
		const maskBase = cc.find('Canvas/bg/maskBase');

		const movePos = maskBase.convertToNodeSpaceAR(
			optionBase.convertToWorldSpaceAR(optionNode.oldPosition)
		);
		const mask = cc.find('Canvas/bg/maskBase/mask');
		await Promise.all([
			asyncTweenTo(mask, 0.5, { opacity: 0 }),
			asyncTweenTo(optionNode, 0.6, { x: movePos.x, y: movePos.y, scale: 1 }, { easing: 'sineInOut' })
		]);
		
		optionNode.parent = optionBase;
		optionNode.setPosition(optionNode.oldPosition);
	},

	async showQuestion() {
		const questionNode = cc.find('Canvas/bg/book/question/questionNode');
		if (!questionNode) {
			return;
		}

		const mask = cc.find('Canvas/bg/maskBase/mask');
		const questionBg = questionNode.getChildByName('bg');

		const oldPosition = questionNode.getPosition();
		questionNode.oldPosition = oldPosition;

		const maskBase = cc.find('Canvas/bg/maskBase');
		const newPos = mask.convertToNodeSpaceAR(
			questionNode.parent.convertToWorldSpaceAR(questionNode.getPosition())
		);
		questionNode.parent = maskBase;
		questionNode.setPosition(newPos);
		await Promise.all([
			asyncTweenTo(mask, 0.5, { opacity: 255 }),
			asyncTweenTo(questionBg, 0.5, { opacity: 255 }),
			asyncTweenTo(questionNode, 0.6, { x: 0, y: 0, scale: 1.4 }, { easing: 'sineInOut' })
		]);

		this.playAudioByNodeName('right');
		const starOn = cc.find('questionLayout/starNode/ImageStarOn', questionNode);
		const starOff = cc.find('questionLayout/starNode/ImageStarOff', questionNode);

		await Promise.all([
			asyncTweenTo(starOn, 0.2, { opacity: 255 }),
			asyncTweenTo(starOff, 0.2, { opacity: 0 })
		]);

		for (const label of this.questionLabelList) {
			await asyncTweenTo(label, 0.2, { scale: 1.3 }, { easing: 'sineInOut' });
			await asyncTweenTo(label, 0.2, { scale: 1.0 }, { easing: 'sineInOut' });
		}
		await asyncDelay(2);
	},

	async hideQuestion() {
		const questionNode = cc.find('Canvas/bg/maskBase/questionNode');
		if (!questionNode) {
			return;
		}

		const mask = cc.find('Canvas/bg/maskBase/mask');
		const questionBg = questionNode.getChildByName('bg');
		const questionBase = cc.find('Canvas/bg/book/question');

		const newPos = questionNode.parent.convertToNodeSpaceAR(
			questionBase.convertToWorldSpaceAR(questionNode.oldPosition)
		);

		await Promise.all([
			asyncTweenTo(mask, 0.5, { opacity: 0 }),
			asyncTweenTo(questionBg, 0.5, { opacity: 0 }),
			asyncTweenTo(questionNode, 0.6, { x: newPos.x, y: newPos.y, scale: 1 }, { easing: 'sineInOut' })
		]);
		questionNode.parent = questionBase;
		questionNode.x = questionNode.oldPosition.x;
		questionNode.y = questionNode.oldPosition.y;
	},

	playAudioByNodeName(name) {
		const audioSource = cc.find(name).getComponent(cc.AudioSource);
		cc.audioEngine.play(audioSource.clip, false, 0.8);
	},

	// ------------------------------------------------
	getSprNode(resName) {
		const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
		const node = new cc.Node();
		node.addComponent(cc.Sprite).spriteFrame = sf;
		return node;
	},

	getSpriteFrimeByUrl(url, cb) {
		cc.loader.load({ url }, (err, img) => {
			const spriteFrame = new cc.SpriteFrame(img)
			if (cb) {
				cb(spriteFrame);
			}
		})
	},

	getSprNodeByUrl(url, cb) {
		const node = new cc.Node();
		const spr = node.addComponent(cc.Sprite);
		this.getSpriteFrimeByUrl(url, (sf) => {
			spr.spriteFrame = sf;
			if (cb) {
				cb(node);
			}
		})
	},

	playAudioByUrl(audio_url, cb = null) {
		if (audio_url) {
			cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
				const audioId = cc.audioEngine.play(audioClip, false, 0.8);
				if (cb) {
					cc.audioEngine.setFinishCallback(audioId, () => {
						cb();
					});
				}
			});
		}
	},

	// ------------------------------------------

});
