import {
	MySprite,
	Label,
	removeItemFromArr,
	hideItem,
	showItem,
	moveItem,
	tweenChange,
} from './../Unit';

import TWEEN from '@tweenjs/tween.js';

export class Game {
	_parent = null;
	_z = 0;
	children: any = [this];

	constructor(parent) {
		this._parent = parent;
	}

	initData(data) {

	}

	initView() {

	}

	_currentPlayingAudioName;
	playAudio(key, now = true, callback = null) {

		if (this._currentPlayingAudioName != '') {
			const audio = this._parent.audioObj[this._currentPlayingAudioName];
			if (audio) {
				if (now) {
					if (!audio.paused) {
						audio.pause();
						// audio.currentTime = 0;
					}
				}
			}
		}

		this._currentPlayingAudioName = key;
		this._parent.playAudio(key, now, () => {
			this._currentPlayingAudioName = '';
			if (callback) {
				callback();
			}
		});
	}

	getAudioObj(key) {
		return this._parent.audioObj[key];
	}

	_editMode = false;
	setEditMode(flg) {
		this._editMode = flg;
	}
	isEditMode() {
		return this._editMode;
	}
	_save;
	setSaveFunc(save) {
		this._save = save;
	}

	addChild(node, z = 1) {
		this._parent.renderArr.push(node);

		if (this.children.indexOf(node) === -1) {
			this.children.push(node);
			node._z = z;
		}

		this.children.sort((a, b) => {
			return a._z - b._z;
		});
	}

	removeChildren() {
		for (let i = 0; i < this.children.length; i++) {
			if (this.children[i]) {
				if (this.children[i] !== this) {
					let child = this.children.splice(i, 1);
					removeItemFromArr(this._parent.renderArr, child);
					i--;
				}
			}
		}
	}
	removeChild(child) {
		const index = this.children.indexOf(child);
		if (index !== -1) {
			this.children.splice(index, 1);
		}
		removeItemFromArr(this._parent.renderArr, child);
	}

	_checkHitPosition(node, pos) {
		let rightNode = null;
		if (node.visible && node.alpha > 0 && node._touchEnabled && node._checkHitPosition(pos)) {
			rightNode = node;
		}
		if (node.children.length > 1) {
			for (var i = 1; i < node.children.length; ++i) {
				if (node.children[i] != node) {
					let result = this._checkHitPosition(node.children[i], pos);
					if (result != null) {
						rightNode = result;
					}
				}
			}
		}
		return rightNode;
	}

	_currentTouchSprite = null;
	_onTouchBegan(pos) {
		let result = this._checkHitPosition(this, pos);
		if (result == null) {
			return;
		}
		if (result._onTouchBeganListener &&
			typeof (result._onTouchBeganListener) == 'function') {
			result._onTouchBeganListener(pos);
		}
		this._currentTouchSprite = result;
	}
	_onTouchMove(pos) {
		if (this._currentTouchSprite == null) {
			return;
		}
		if (this._currentTouchSprite._onTouchMoveListener &&
			typeof (this._currentTouchSprite._onTouchMoveListener) == 'function') {
			this._currentTouchSprite._onTouchMoveListener(pos);
		}
	}
	_onTouchEnd(pos) {
		if (this._currentTouchSprite == null) {
			return;
		}
		if (this._currentTouchSprite._checkHitPosition(pos)) {
			if (this._currentTouchSprite._onTouchEndListener &&
				typeof (this._currentTouchSprite._onTouchEndListener) == 'function') {
				this._currentTouchSprite._onTouchEndListener(pos);
			}
			this._currentTouchSprite = null;
		} else {
			if (this._currentTouchSprite._onTouchCancelListener &&
				typeof (this._currentTouchSprite._onTouchCancelListener) == 'function') {
				this._currentTouchSprite._onTouchCancelListener(pos);
			}
			this._currentTouchSprite = null;
		}
	}

	getChildByName(name) {
		for (var i = 1; i < this.children.length; ++i) {
			let node = this.children[i];
			if (node.getName() == name) {
				return node;
			}
		}
		return null;
	}
	seekChildByName(name) {
		let result = this.getChildByName(name);
		if (result == null) {
			for (var i = 1; i < this.children.length; ++i) {
				let node = this.children[i];
				if (typeof (node.seekChildByName) == 'function') {
					result = node.seekChildByName(name);
					if (result != null) {
						return result;
					}
				}
			}
		}
		return result;
	}

	getScreenSize() {
		return {
			width: this._parent.canvasWidth,
			height: this._parent.canvasHeight
		};
	}

	getDefaultScreenSize() {
		return {
			width: this._parent.canvasBaseW,
			height: this._parent.canvasBaseH
		};
	}

	getFullScaleXY() {
		let screenSize = this.getScreenSize();
		let defaultSize = this.getDefaultScreenSize();

		return Math.max(screenSize.height / defaultSize.height, screenSize.width / defaultSize.width);
	}

	_showMode = false;
	showModeOn() {
		this._showMode = true;
	}
	showModeOff() {
		this._showMode = false;
	}
	isShowMode() {
		return this._showMode;
	}
}

// 节点名
class Nameable {
	_parent = null;
	constructor(parent) {
		this._parent = parent;
	}

	_name = 'name';
	setName(name) {
		this._name = name;
	}
	getName() {
		return this._name;
	}
	getChildByName(name) {
		for (var i = 1; i < this._parent.children.length; ++i) {
			let node = this._parent.children[i];
			if (node.getName() == name) {
				return node;
			}
		}
		return null;
	}
	seekChildByName(name) {
		let result = this.getChildByName(name);
		if (result == null) {
			for (var i = 1; i < this._parent.children.length; ++i) {
				let node = this._parent.children[i];
				if (typeof (node.seekChildByName) == 'function') {
					result = node.seekChildByName(name);
					if (result != null) {
						return result;
					}
				}
			}
		}
		return result;
	}
}

class UserData {
	// 用户自定义数据
	userData = {};
	get(key) {
		return this.userData[key];
	}
	set(key, value) {
		this.userData[key] = value;
	}
}

export class MyLabel extends Label {
	_nameable = new Nameable(this);
	setName(name) {
		this._nameable.setName(name);
	}
	getName() {
		return this._nameable.getName();
	}
	getChildByName(name) {
		return this._nameable.getChildByName(name);
	}
	seekChildByName(name) {
		return this._nameable.seekChildByName(name);
	}

	// 位置
	setPosition(x: any = 0, y = undefined) {
		if (y !== undefined) {
			this.x = x;
			this.y = y;
		} else {
			this.x = x.x;
			this.y = x.y;
		}
	}
	setPositionX(x = 0) {
		this.x = x;
	}
	setPositionY(y = 0) {
		this.y = y;
	}

	_userData = new UserData();
	get(key) {
		return this._userData.get(key);
	}
	set(key, value) {
		this._userData.set(key, value);
	}

	_touchEnabled = false;
	// _swallowTouches = false;		// TODO:多重触摸以后用到了再说

	_onTouchBeganListener = null;
	_onTouchMoveListener = null;
	_onTouchEndListener = null;
	_onTouchCancelListener = null;

	addTouchBeganListener(func) {
		this._touchEnabled = true;
		this._onTouchBeganListener = func;
	}
	addTouchMoveListener(func) {
		this._touchEnabled = true;
		this._onTouchMoveListener = func;
	}
	addTouchEndListener(func) {
		this._touchEnabled = true;
		this._onTouchEndListener = func;
	}
	addTouchCancelListener(func) {
		this._touchEnabled = true;
		this._onTouchCancelListener = func;
	}

	_checkHitPosition(pos) {
		const rect = this.getBoundingBox();

		if (this._checkPointInRect(pos.x, pos.y, rect)) {
			return true;
		}
		return false;
	}
	_checkPointInRect(x, y, rect) {
		if (x >= rect.x && x <= rect.x + rect.width) {
			if (y >= rect.y && y <= rect.y + rect.height) {
				return true;
			}
		}
		return false;
	}

	drawText() {
		if (!this.text) {
			return;
		}

		this.ctx.font = `${this.fontSize}px ${this.fontName}`;
		this.ctx.textAlign = this.textAlign;
		this.ctx.textBaseline = 'middle';
		this.ctx.fontWeight = this.fontWeight;

		let x = -(this.anchorX) * this._width;
		let y = 0;

		if (this._outlineFlag) {
			this.ctx.lineWidth = this._outLineWidth;
			this.ctx.strokeStyle = this._outLineColor;
			this.ctx.strokeText(this.text, x, y);
		}

		this.ctx.fillStyle = this.fontColor;

		if (this.outline > 0) {
			this.ctx.lineWidth = this.outline;
			this.ctx.strokeStyle = this.outlineColor;
			this.ctx.strokeText(this.text, x, y);
		}

		this.ctx.fillText(this.text, x, y);
		// console.log('汪汪汪: ' + this.scaleX * this.anchorX);
		// console.log('汪汪汪: ' + this._width);
	}
}

export class TouchSprite extends MySprite {
	_nameable = new Nameable(this);
	setName(name) {
		this._nameable.setName(name);
	}
	getName() {
		return this._nameable.getName();
	}
	getChildByName(name) {
		return this._nameable.getChildByName(name);
	}
	seekChildByName(name) {
		return this._nameable.seekChildByName(name);
	}

	_touchEnabled = false;
	// _swallowTouches = false;		// TODO:多重触摸以后用到了再说

	_onTouchBeganListener = null;
	_onTouchMoveListener = null;
	_onTouchEndListener = null;
	_onTouchCancelListener = null;

	addTouchBeganListener(func) {
		this._touchEnabled = true;
		this._onTouchBeganListener = func;
	}
	addTouchMoveListener(func) {
		this._touchEnabled = true;
		this._onTouchMoveListener = func;
	}
	addTouchEndListener(func) {
		this._touchEnabled = true;
		this._onTouchEndListener = func;
	}
	addTouchCancelListener(func) {
		this._touchEnabled = true;
		this._onTouchCancelListener = func;
	}

	_checkHitPosition(pos) {
		const rect = this.getBoundingBox();

		if (this._checkPointInRect(pos.x, pos.y, rect)) {
			return true;
		}
		return false;
	}
	_checkPointInRect(x, y, rect) {
		if (x >= rect.x && x <= rect.x + rect.width) {
			if (y >= rect.y && y <= rect.y + rect.height) {
				return true;
			}
		}
		return false;
	}

	// 位置
	setPosition(x: any = 0, y = undefined) {
		if (y !== undefined) {
			this.x = x;
			this.y = y;
		} else {
			this.x = x.x;
			this.y = x.y;
		}
	}
	setPositionX(x = 0) {
		this.x = x;
	}
	setPositionY(y = 0) {
		this.y = y;
	}

	// 用户自定义数据
	_userData = new UserData();
	get(key) {
		return this._userData.get(key);
	}
	set(key, value) {
		this._userData.set(key, value);
	}
}

export function blinkItem(item: TouchSprite, time = 0.7) {
	let interval = item.get('_blinkInterval');
	if (interval) {
		clearInterval(interval);
	}
	interval = setInterval(() => {
		showItem(item, time, () => {
			hideItem(item, time);
		});
	}, time * 2 * 1000);
	item.set('_blinkInterval', interval);
}

export function stopBlinkItem(item: TouchSprite) {
	let interval = item.get('_blinkInterval');
	if (interval) {
		clearInterval(interval);
	}
	item.set('_blinkInterval', null);
	item.alpha = 0;
}

export function RandomInt(a, b = 0) {
	let max = Math.max(a, b);
	let min = Math.min(a, b);
	return Math.floor(Math.random() * (max - min) + min);
}

export function shake(item, time = 0.5, rate = 1) {
	let shakeSelf = function(item, time, callback, rate) {
		const offX = 15 * item.scaleX * rate;
		const offY = 15 * item.scaleX * rate;
		const baseX = item.x;
		const baseY = item.y;
		const easing = TWEEN.Easing.Sinusoidal.InOut;

		const move2 = () => {
			moveItem(item, baseX, baseY, time * 9 / 16, () => {
				if (callback) {
					callback();
				}
			}, easing);
		};

		const move1 = () => {
			moveItem(item, baseX + offX, baseY + offY, time * 7 / 16, () => {
				move2();
			}, easing);
		};

		move1();
	}

	shakeSelf(item, time, shake.bind(this, item, time, rate), rate);
}

export async function asyncDelayTime(time) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve(123);
		}, time * 1000);
	})
}

export async function asyncTweenChange(node, obj, time, easing) {
	return new Promise((resolve, reject) => {
		tweenChange(node, obj, time, () => {
			resolve();
		}, easing);
	});
}