import { onHomeworkFinish, randomSortByArr, playDragonBoneAnimation } from "../script/util";
import { defaultData } from "../script/defaultData";

cc.Class({

	extends: cc.Component,

	properties: {
	},

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

	// 生命周期
	onDestroy() {
		if (this.timeA !== undefined) {
			clearTimeout(this.timeA);
		}
	},

	_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:' + JSON.stringify(data));
			this.data = data || this.getDefaultData();
			this.data = JSON.parse(JSON.stringify(this.data));
			this.preloadItem();
		})
	},

	getData(func) {
		if (window && window.courseware) {
			window.courseware.getData(func, 'scene');
			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() {
		this._imageResList.push(...this.data.question_arr.map(question => {
			return question.option_arr.map(option => {
				return { url: option.pic_url }
			});
		}).flat());
	},

	addPreloadAudio() {
		this._audioResList.push(this.data.startAudio);
		this._audioResList.push(this.data.endAudio);
		this._audioResList.push(...this.data.question_arr.map(question => {
			return question.option_arr.map(option => {
				return { url: option.audio_url };
			});
		}).flat());
		this._audioResList.push(...this.data.question_arr.map(question => {
			return { url: question.question_audio_url };
		}));
	},

	addPreloadAnima() {

	},

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

			if (window && window["air"]) {
				cc.find('Canvas').opacity = 0;
				window.air.onCourseInScreen = (next) => {
					cc.find('Canvas').opacity = 255;
					this.loadEnd();
					next();
				}
				window.air.hideAirClassLoading();
			} else {
				this.loadEnd();
			}

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

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

	initData() {
		this.status = {
			currentQuestionIdx: 0,
			wrongTime: 0
		}
	},

	initView() {
		this.refreshCoolCatPosition();
		this.coolCatSpeakStart(() => {
			this.jumpToQuestion(this.status.currentQuestionIdx);
		});
	},

	refreshCoolCatPosition() {

	},

	jumpToQuestion(questionIdx) {
		const questionAudioUrl = this.data.question_arr[questionIdx].question_audio_url;
		this.playAudioByUrl(questionAudioUrl);

		const box = cc.find('Canvas/bg/box');
		box.removeAllChildren();

		const canvasWidth = cc.find('Canvas').width;
		const canvasHeight = cc.find('Canvas').height;
		const optionNum = this.data.question_arr[questionIdx].option_arr.length;
		const maxOptionHeight = 500;
		const maxOptionWidth = (canvasWidth * 0.95) / optionNum;

		const arr = randomSortByArr(this.data.question_arr[questionIdx].option_arr);
		arr.forEach(async (option, idx) => {
			const optionNode = await this.createOption(option);
			optionNode.name = `option_${idx}`;
			optionNode.x = (idx - (arr.length - 1) / 2) * maxOptionWidth - box.x;
			optionNode.y = canvasHeight / 2 - box.y - 300;
			optionNode.scale = 0;
			optionNode.parent = box;

			cc.tween(optionNode)
				.to(0.1, { scale: Math.min((maxOptionWidth * 0.80) / optionNode.width, maxOptionHeight / optionNode.height) })
				.start();
		});
	},

	createOption(optionData) {
		return new Promise((resolve, reject) => {
			const optionNode = cc.instantiate(cc.find('option'));
			this.loadSpriteByUrl(optionNode, optionData.pic_url, () => {
				resolve(optionNode);
			});
			optionNode.optionData = optionData;
			optionNode.optionData.selected = false;

			const box = cc.find('Canvas/bg/box');
			optionNode.on(cc.Node.EventType.TOUCH_START, (event) => {
				if (optionNode.optionData.selected) {
					return;
				}
				const location = event.getLocation();
				optionNode.startLocation = location;
				optionNode.startPos = {
					x: optionNode.x,
					y: optionNode.y
				}

				const selectedNum = box.children.filter(child => child.optionData.selected == true).length;
				optionNode.zIndex = selectedNum;

				this.optionJump(optionNode);
				this.playAudioByUrl(optionNode.optionData.audio_url);
			});
			optionNode.on(cc.Node.EventType.TOUCH_MOVE, (event) => {
				if (optionNode.optionData.selected) {
					return;
				}
				const location = event.getLocation();
				optionNode.x = optionNode.startPos.x + (location.x - optionNode.startLocation.x);
				optionNode.y = optionNode.startPos.y + (location.y - optionNode.startLocation.y);
			});
			optionNode.on(cc.Node.EventType.TOUCH_END, (event) => {
				if (optionNode.optionData.selected) {
					return;
				}
				const rectOption = optionNode.getBoundingBox();
				if (!cc.Intersection.rectRect(box, rectOption)) {

					cc.tween(optionNode)
						.to(0.05, {
							x: optionNode.startPos.x,
							y: optionNode.startPos.y
						}, cc.easing.quadOut)
						.start();

					this.playEffect('flyBack');
					return;
				}

				cc.tween(optionNode)
					.to(0.2, { x: 0, y: 100 }, cc.easing.quadOut)
					.start();

				this.boxJump();

				optionNode.optionData.selected = true;
			});

			return optionNode;
		});
	},

	optionJump(node, time = 0.1) {
		if (node.baseScale) {
			return;
		}
		node.baseScale = node.scaleX;

		cc.tween(node)
			.to(time, { scaleX: node.baseScale * 1.1, scaleY: node.baseScale * 1.1 })
			.to(time, { scaleX: node.baseScale * 1, scaleY: node.baseScale * 1 })
			.call(() => {
				node.baseScale = null;
			})
			.start();
	},

	initListener() {
		const btnSubmit = cc.find('Canvas/bg/btnSubmit');
		btnSubmit.on('click', () => {
			this.optionJump(btnSubmit, 0.05);
			this.playEffect('submit');
			const box = cc.find('Canvas/bg/box');
			if (box.children.every(child => child.optionData.selected == child.optionData.is_right)) {
				this.onAnswerRight();
			} else {
				this.coolCatSpeakWrong(() => {
					this.status.wrongTime++;
					if (this.status.wrongTime < this.data.maxWrongNumber) {
						this.onAnswerWrong();
					} else {
						this.onAnswerWrongTwice();
					}
				});
			}
		});

		const btnNext = cc.find('Canvas/bg/btnNext');
		btnNext.on('click', () => {
			this.optionJump(btnNext, 0.05);
		});
	},

	onAnswerRight() {
		this.coolCatSpeakRight(() => {
			this.nextQuestion();
		});
	},

	onAnswerWrong() {
		const box = cc.find('Canvas/bg/box');
		box.children
			.filter(child => child.optionData.selected)
			.forEach(child => {
				child.optionData.selected = false;
				cc.tween(child)
					.to(0.2, { x: child.startPos.x, y: child.startPos.y })
					.start();
			});

		this.playEffect('flyBackAll');
	},

	onAnswerWrongTwice() {
		this.status.currentQuestionIdx = this.data.question_arr.length;
		this.nextQuestion();
		this.playEffect('jumpAll');
	},

	timeA: null,
	nextQuestion() {
		const box = cc.find('Canvas/bg/box');
		box.children.forEach(child => {
			cc.tween(child)
				.to(0.1, { scaleX: 0, scaleY: 0 })
				.removeSelf()
				.start();
		});
		this.status.currentQuestionIdx++;

		if (this.status.currentQuestionIdx < this.data.question_arr.length) {
			this.timeA = setTimeout(() => {
				this.jumpToQuestion(this.status.currentQuestionIdx);
			}, 0.1 * 1000);
		} else {
			this.coolCatSpeakEnd(() => {
				this.submitBtnMoveOut();
				this.showNextBtn();
			});
		}
	},

	boxJump() {
		const boxBehind = cc.find('Canvas/bg/box_behind');
		const boxFront = cc.find('Canvas/bg/box_front');

		this.playEffect('boxJump');

		cc.tween(boxFront)
			.to(0.1, { scaleX: 1.02, scaleY: 1.02 })
			.to(0.1, { scaleX: 1.0, scaleY: 1.0 })
			.start();
		cc.tween(boxBehind)
			.to(0.1, { scaleX: 1.02, scaleY: 1.02 })
			.to(0.1, { scaleX: 1.0, scaleY: 1.0 })
			.start();
	},

	submitBtnMoveOut() {
		const submitBtn = cc.find('Canvas/bg/btnSubmit');
		cc.tween(submitBtn)
			.by(1, { y: -submitBtn.height })
			.start();
	},

	showNextBtn() {
		onHomeworkFinish();

		const btnNext = cc.find('Canvas/bg/btnNext');
		btnNext.active = true;
	},

	coolCatSpeakStart(cb) {
		const cat = cc.find('Canvas/bg/catFrame/CoolCat');
		playDragonBoneAnimation(cat, 'begin', -1);
		this.playAudioByUrl(this.data.startAudio, () => {
			playDragonBoneAnimation(cat, 'normal', -1);
			cb();
		});
	},

	coolCatSpeakRight(cb) {
		const cat = cc.find('Canvas/bg/catFrame/CoolCat');
		playDragonBoneAnimation(cat, 'right', -1);
		this.playEffect('CoolCatRight', () => {
			playDragonBoneAnimation(cat, 'normal', -1);
			cb();
		});
	},

	coolCatSpeakWrong(cb) {
		const cat = cc.find('Canvas/bg/catFrame/CoolCat');
		playDragonBoneAnimation(cat, 'wrong', -1);
		this.playEffect('CoolCatWrong', () => {
			playDragonBoneAnimation(cat, 'normal', -1);
			cb();
		});
	},

	coolCatSpeakEnd(cb) {
		const cat = cc.find('Canvas/bg/catFrame/CoolCat');
		playDragonBoneAnimation(cat, 'finish', -1);
		this.playAudioByUrl(this.data.endAudio, () => {
			playDragonBoneAnimation(cat, 'normal', -1);
			cb();
		});
	},

















	// ------------------------------------------------
	loadSpriteByUrl(node, url, cb) {
		cc.loader.load({ url }, (err, img) => {
			if (!node) {
				cb && cb();
			}
			const spriteFrame = new cc.SpriteFrame(img)
			const spr = node.getComponent(cc.Sprite);
			spr.spriteFrame = spriteFrame;
			if (cb) {
				cb();
			}
		});
	},

	currentPlayedAudioId: null,
	stopCurrentPlayedAudio() {
		if (this.currentPlayedAudioId !== null) {
			cc.audioEngine.stop(this.currentPlayedAudioId);
			this.currentPlayedAudioId = null;
		}
	},
	playEffect(name, cb) {
		this.stopCurrentPlayedAudio();
		const audioNode = cc.find(`audios/${name}`);
		const audioClip = audioNode.getComponent(cc.AudioSource).clip;
		const audioId = cc.audioEngine.play(audioClip, false, 0.8);
		this.currentPlayedAudioId = audioId;
		if (cb) {
			cc.audioEngine.setFinishCallback(audioId, cb);
		}
	},
	playAudioByUrl(audio_url, cb = null) {
		if (!audio_url) {
			if (cb) {
				cb();
			}
			return;
		}
		this.stopCurrentPlayedAudio();
		cc.assetManager.loadRemote(audio_url.toLowerCase(), (err, audioClip) => {
			const audioId = cc.audioEngine.play(audioClip, false, 0.8);
			this.currentPlayedAudioId = audioId;
			if (cb) {
				cc.audioEngine.setFinishCallback(audioId, cb);
			}
		});
	},
});
