import { defaultData } from '../script/defaultData';
import { asyncDelay, jelly } from '../script/utils';
import { letterData, letterWidthData } from '../script/letterPointData';

cc.Class({
	extends: cc.Component,

	properties: {
		switchAudio: { default: null, type: cc.AudioClip },
		bigA: { default: null, type: cc.AudioClip },
		bigB: { default: null, type: cc.AudioClip },
		bigC: { default: null, type: cc.AudioClip },
		bigD: { default: null, type: cc.AudioClip },
		bigE: { default: null, type: cc.AudioClip },
		bigF: { default: null, type: cc.AudioClip },
		bigG: { default: null, type: cc.AudioClip },
		bigH: { default: null, type: cc.AudioClip },
		bigI: { default: null, type: cc.AudioClip },
		bigJ: { default: null, type: cc.AudioClip },
		bigK: { default: null, type: cc.AudioClip },
		bigL: { default: null, type: cc.AudioClip },
		bigM: { default: null, type: cc.AudioClip },
		bigN: { default: null, type: cc.AudioClip },
		bigO: { default: null, type: cc.AudioClip },
		bigP: { default: null, type: cc.AudioClip },
		bigQ: { default: null, type: cc.AudioClip },
		bigR: { default: null, type: cc.AudioClip },
		bigS: { default: null, type: cc.AudioClip },
		bigT: { default: null, type: cc.AudioClip },
		bigU: { default: null, type: cc.AudioClip },
		bigV: { default: null, type: cc.AudioClip },
		bigW: { default: null, type: cc.AudioClip },
		bigX: { default: null, type: cc.AudioClip },
		bigY: { default: null, type: cc.AudioClip },
		bigZ: { default: null, type: cc.AudioClip },

		smallA: { default: null, type: cc.AudioClip },
		smallB: { default: null, type: cc.AudioClip },
		smallC: { default: null, type: cc.AudioClip },
		smallD: { default: null, type: cc.AudioClip },
		smallE: { default: null, type: cc.AudioClip },
		smallF: { default: null, type: cc.AudioClip },
		smallG: { default: null, type: cc.AudioClip },
		smallH: { default: null, type: cc.AudioClip },
		smallI: { default: null, type: cc.AudioClip },
		smallJ: { default: null, type: cc.AudioClip },
		smallK: { default: null, type: cc.AudioClip },
		smallL: { default: null, type: cc.AudioClip },
		smallM: { default: null, type: cc.AudioClip },
		smallN: { default: null, type: cc.AudioClip },
		smallO: { default: null, type: cc.AudioClip },
		smallP: { default: null, type: cc.AudioClip },
		smallQ: { default: null, type: cc.AudioClip },
		smallR: { default: null, type: cc.AudioClip },
		smallS: { default: null, type: cc.AudioClip },
		smallT: { default: null, type: cc.AudioClip },
		smallU: { default: null, type: cc.AudioClip },
		smallV: { default: null, type: cc.AudioClip },
		smallW: { default: null, type: cc.AudioClip },
		smallX: { default: null, type: cc.AudioClip },
		smallY: { default: null, type: cc.AudioClip },
		smallZ: { default: null, type: cc.AudioClip },
	},

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

	},

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

	// 生命周期 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() {
		console.log('defaultData = ' + defaultData);
		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.audio_url });
	},

	addPreloadAnima() {

	},

	preload() {
		const preloadArr = this._imageResList.concat(this._audioResList).concat(this._animaResList);
		cc.assetManager.loadAny(preloadArr, null, null, (err, data) => {
			this.loadEnd();
			if (window && window["air"]) {
				window["air"].hideAirClassLoading();
			}
			cc.debug.setDisplayStats(false);
		});
	},

	loadEnd() {
		this.initData();
		this.initAudio();
		this.initView();
		this.initListener();

		this.showLetterAnimation();
		this.startEditMode();
	},

	letterPosList: null,
	initData() {
		this.letterPosList = {};
		for (const key in letterData) {
			if (Object.hasOwnProperty.call(letterData, key)) {
				this.letterPosList[key] = letterData[key].map(pen => {
					return pen.map(pos => cc.v2(pos.x, pos.y));
				});
			}
		}
	},

	initAudio() {

	},

	debugMode: false,
	letter: null,
	initView() {
		this.debugMode = this.data.debugMode;
		this.setLetter(this.data.letter);
	},

	setLetter(letter) {
		this.letter = letter;

		this.updateLetterBtnLabel();

		this.addDrawLetter(this.letter);

		cc.find('Canvas').on('size-changed', () => {
			this.onSizeChanged();
		});
		this.onSizeChanged();
	},

	onSizeChanged() {
		this.node.getComponent(cc.Widget).updateAlignment();
		const currentSize = { width: this.node.width, height: this.node.height };
		console.log('currentSize = ' + JSON.stringify(currentSize));
		const frameSize = cc.view.getFrameSize();
		console.log('frameSize = ' + JSON.stringify(frameSize));
		const designSize = cc.view.getDesignResolutionSize();
		console.log('designSize = ' + JSON.stringify(designSize));

		const letterBg = cc.find('Canvas/bg/Img_letter_bg');

		const scale = (designSize.width / designSize.height) / (frameSize.width / frameSize.height);
		letterBg.scale = Math.min(scale, 1);
	},

	updateLetterBtnLabel() {
		const label1 = cc.find('Canvas/bg/BtnSmallLetter/Img_selected/label');
		const label2 = cc.find('Canvas/bg/BtnSmallLetter/Img_normal/label');
		const label3 = cc.find('Canvas/bg/BtnBigLetter/Img_selected/label');
		const label4 = cc.find('Canvas/bg/BtnBigLetter/Img_normal/label');

		label1.getComponent(cc.Label).string = this.letter.toLowerCase();
		label2.getComponent(cc.Label).string = this.letter.toLowerCase();
		label3.getComponent(cc.Label).string = this.letter.toUpperCase();
		label4.getComponent(cc.Label).string = this.letter.toUpperCase();
	},

	interpolateLine(lineList, maxLength) {
		let newposList = [];
		for (const line of lineList) {
			const distance = this.getDistance(line.startPos, line.endPos);
			if (distance > maxLength) {
				const middlePoint = this.getMiddlePoint(line.startPos, line.endPos);
				newposList.push({ type: 'Line', startPos: line.startPos, endPos: middlePoint });
				newposList.push({ type: 'Line', startPos: middlePoint, endPos: line.endPos });
			} else {
				newposList.push(line);
			}
		}
		if (newposList.length > lineList.length) {
			newposList = this.interpolateLine(newposList, maxLength);
		}
		return newposList;
	},

	interpolatePos(posList, maxLength) {
		let newposList = [];
		if (posList.length <= 1) {
			return posList;
		}
		for (let i = 0; i < posList.length - 1; i++) {
			const pos = posList[i];
			const nextPos = posList[i + 1];
			const distance = this.getDistance(pos, nextPos);

			newposList.push(pos);
			if (distance > maxLength) {
				const middlePoint = this.getMiddlePoint(pos, nextPos);
				newposList.push(middlePoint);
			}
		}
		newposList.push(posList[posList.length - 1]);
		if (newposList.length > posList.length) {
			newposList = this.interpolatePos(newposList, maxLength);
		}
		return newposList;
	},

	getMiddlePoint(pos1, pos2) {
		return cc.v2((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2);
	},

	getDistance(pos1, pos2) {
		return pos1.sub(pos2).mag();
	},

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

	drawBigCircle(drawNode, centerPos, color) {
		const graph = drawNode.getComponent(cc.Graphics);
		graph.lineWidth = 5;
		graph.strokeColor = color;
		graph.arc(centerPos.x, centerPos.y, 6, 0, Math.PI * 2, true);
		graph.stroke();
		graph.fillColor = cc.color(255, 255, 255);
		graph.arc(centerPos.x, centerPos.y, 4, 0, Math.PI * 2, true);
		graph.fill();
	},

	drawSmallDot(drawNode, centerPos, color) {
		const graph = drawNode.getComponent(cc.Graphics);
		graph.fillColor = color;
		graph.arc(centerPos.x, centerPos.y, 3, 0, Math.PI * 2, true);
		graph.fill();
	},

	addDrawLetter(letter) {
		const letterBaseNode = cc.find('Canvas/bg/Img_letter_bg');
		letterBaseNode.removeAllChildren();
		const letterBg = cc.instantiate(cc.find(`Img_letter_bg_${letter}`));
		letterBg.x = 0;
		letterBg.y = 0;
		letterBg.parent = letterBaseNode;
		cc.find('LetterMask/bg', letterBg).active = false;
		return letterBg;
	},

	getDrawNodeList() {
		return [];
	},

	initListener() {
		const BtnBigLetter = cc.find('Canvas/bg/BtnBigLetter');
		const BtnSmallLetter = cc.find('Canvas/bg/BtnSmallLetter');

		BtnBigLetter.on('click', () => {
			BtnBigLetter.getChildByName('Img_normal').active = false;
			BtnSmallLetter.getChildByName('Img_normal').active = true;
			BtnBigLetter.getChildByName('Img_selected').active = true;
			BtnSmallLetter.getChildByName('Img_selected').active = false;

			jelly(BtnBigLetter);

			cc.audioEngine.play(this.switchAudio, false, 0.8);

			this.setLetter(this.letter.toUpperCase());
			this.showLetterAnimation();
			this.startEditMode();
		});
		BtnSmallLetter.on('click', () => {
			BtnBigLetter.getChildByName('Img_normal').active = true;
			BtnSmallLetter.getChildByName('Img_normal').active = false;
			BtnBigLetter.getChildByName('Img_selected').active = false;
			BtnSmallLetter.getChildByName('Img_selected').active = true;

			jelly(BtnSmallLetter);

			cc.audioEngine.play(this.switchAudio, false, 0.8);

			this.setLetter(this.letter.toLowerCase());
			this.showLetterAnimation();
			this.startEditMode();
		});

		const btnBack = cc.find('Canvas/EditModeNode/BtnBack');
		btnBack.on('click', () => {
			const posList = this.letterPosList[this.letter];
			const lastPen = posList[posList.length - 1];
			if (lastPen && lastPen.length > 0) {
				lastPen.pop();
			} else {
				if (posList.length > 0) {
					posList.pop();
				}
			}
			this.updateEditMode();
		});
		const btnNext = cc.find('Canvas/EditModeNode/BtnNext');
		btnNext.on('click', () => {
			const posList = this.letterPosList[this.letter];
			posList.push([]);
			this.updateEditMode();
		});

		const btnShow = cc.find('Canvas/EditModeNode/BtnShow');
		btnShow.on('click', () => {
			this.showLetterAnimation();
		});
		const btnSave = cc.find('Canvas/EditModeNode/BtnSave');
		btnSave.on('click', () => {
			const posList = this.letterPosList[this.letter];
			console.log(JSON.stringify(posList));
		});
	},

	_writingIdx: 0,
	async showLetterAnimation() {
		if (!this._writingIdx) {
			this._writingIdx = 0;
		}
		this._writingIdx++;
		const writingIdx = this._writingIdx;
		console.log('set writingIdx = ' + writingIdx);
		// cc.find(`Canvas/bg/Img_letter_bg/Img_letter_bg_${this.letter}/LetterMask/bg`).active = true;
		const drawNode = cc.find(`Canvas/bg/Img_letter_bg/Img_letter_bg_${this.letter}/LetterMask/DrawNode`);
		const graph = drawNode.getComponent(cc.Graphics);
		graph.clear();

		const posList = this.letterPosList[this.letter];
		const lienList = this.getLineList(posList);
		for (const pen of lienList) {
			for (const line of pen) {
				this.drawALine(drawNode, line.startPos, line.endPos, cc.color(181, 39, 48));
				await asyncDelay(0.02);
			}
			await asyncDelay(0.1);
		}
		console.log('writingIdx = ' + writingIdx);
		console.log('this._writingIdx = ' + this._writingIdx);
		if (writingIdx == this._writingIdx) {
			if (this.letter == this.letter.toUpperCase()) {
				const audioClip = this[`big${this.letter.toUpperCase()}`];
				cc.audioEngine.play(audioClip, false, 0.8);
			} else {
				const audioClip = this[`small${this.letter.toUpperCase()}`];
				cc.audioEngine.play(audioClip, false, 0.8);
			}
		}
	},

	editMode: false,
	startEditMode() {
		if (!this.debugMode) {
			return;
		}
		cc.find('Canvas/EditModeNode').active = true;
		this.editMode = true;
		cc.find(`Canvas/bg/Img_letter_bg/Img_letter_bg_${this.letter}/LetterMask/bg`).active = true;
		const drawNode = cc.find(`Canvas/bg/Img_letter_bg/Img_letter_bg_${this.letter}/LetterMask/DrawNode`);
		drawNode.addComponent(cc.Button);
		drawNode.on('touchstart', (event) => {
			const touchLocation = event.getLocation();
			const pos = drawNode.convertToNodeSpaceAR(touchLocation);
			const posList = this.letterPosList[this.letter];
			if (posList.length == 0) {
				posList.push([]);
			}
			posList[posList.length - 1].push(pos);
			this.updateEditMode();
		});
		drawNode.on('touchmove', (event) => {
			const touchLocation = event.getLocation();
			const pos = drawNode.convertToNodeSpaceAR(touchLocation);
			const posList = this.letterPosList[this.letter];
			const lastPen = posList[posList.length - 1];
			lastPen[lastPen.length - 1] = pos;
			this.updateEditMode();
		});
		this.updateEditMode();
	},

	getLineList(posList) {
		const lineList = [];
		for (const pen of posList) {
			const newPen = this.interpolatePos(pen, 10);
			const newLine = [];
			newPen.forEach((pos, idx) => {
				if (idx < newPen.length - 1) {
					newLine.push({
						startPos: pos,
						endPos: newPen[idx + 1]
					});
				}
			});
			if (pen.length == 1) {
				newLine.push({
					startPos: pen[0],
					endPos: cc.v2(pen[0].x, pen[0].y + 0.001)
				});
			}
			lineList.push(newLine);
		}
		return lineList;
	},

	updateEditMode() {
		const drawNode = cc.find(`Canvas/bg/Img_letter_bg/Img_letter_bg_${this.letter}/LetterMask/DrawNode`);
		const graph = drawNode.getComponent(cc.Graphics)
		graph.clear();
		const posList = this.letterPosList[this.letter];

		const lienList = this.getLineList(posList);
		for (const pen of lienList) {
			for (const line of pen) {
				this.drawALine(drawNode, line.startPos, line.endPos, cc.color(0, 0, 255));
			}
		}
		posList.forEach((pen, i) => {
			const newPen = this.interpolatePos(pen, 10);
			for (const pos of newPen) {
				let color = cc.color(50, 50, 50);
				if (i == posList.length - 1) {
					color = cc.color(255, 0, 0);
				}
				const idx = pen.findIndex(penPos => penPos.x == pos.x && penPos.y == pos.y);
				if (idx == -1) {
					this.drawSmallDot(drawNode, pos, color);
				} else {
					this.drawBigCircle(drawNode, pos, color);
				}
			}
		});
	}
});
