/**
 * Created by rockyl on 2019-05-07.
 *
 * 矿工
 */

import ScillaComponent from "components/base/ScillaComponent";
import FrameAnimationRenderer from "components/renderer/FrameAnimationRenderer";
import {createTween, ease, Entity, instantiate, resource, Texture, Vector2D} from "scilla";
import Hole from "./Hole";
import Transform from "components/base/Transform";

const speed: Vector2D = new Vector2D(2.5, 2.5);
const walkRange: number = 750 / 2 - 50;

enum STATUS {
	IDLE,
	WALK,
	DIG,
	DIG_IDLE,
}

export default class Miner extends ScillaComponent {
	Hole: Entity;
	Miner: Entity;
	Body: Entity;
	Effect: Entity;
	Items: Entity;
	itemHangPrefab: resource;
	itemGap = new Vector2D(5, -1);
	smallItemScale: Vector2D = new Vector2D(0.3, 0.3);
	animations: resource;
	holeRes: Texture;

	private _minerTransform: Transform;
	private _bodyAnim: FrameAnimationRenderer;
	private _effectAnim: FrameAnimationRenderer;
	private _velocity: Vector2D = new Vector2D();
	private _status: STATUS;
	private _diggingHole = false;
	private _digDelegate;
	private _hole: Hole;
	private _itemCount = 0;
	private _maxDepth;
	private _avoidPosition;

	constructor() {
		super();

		this._status = STATUS.IDLE;
	}

	prepare(digDelegate, maxDepth, resName) {
		this._digDelegate = digDelegate;
		this._maxDepth = maxDepth;

		this._bodyAnim.frameAnimation = this.animations[resName];
	}

	reset() {
		for (let item of this.Items.children) {
			item.enabled = false;
		}
		this._itemCount = 0;
		this._avoidPosition = null;
		this._hole.hide();
		this._minerTransform.position.y = 0;
	}

	onCreate() {
		super.onCreate();

		this._minerTransform = this.Miner.getComponent(Transform);
		this._bodyAnim = this.Body.getComponent(FrameAnimationRenderer);

		this._effectAnim = this.Effect.getComponent(FrameAnimationRenderer);

		this._hole = this.Hole.getComponent(Hole);
		this._hole.hide();
	}

	onUpdate(t) {
		super.onUpdate(t);

		const {_minerTransform: {position: minerPosition}, transform: {position}, _velocity} = this;

		switch (this._status) {
			case STATUS.IDLE:

				break;
			case STATUS.WALK:
				position.x += _velocity.x;

				if (Math.abs(position.x) > walkRange) {
					_velocity.x = -_velocity.x;
					this.dir = _velocity.x >= 0 ? 1 : -1;
				}
				if (this._avoidPosition && Math.abs(position.x - this._avoidPosition.x) > this.holeRes.width) {
					this.playDig();
				}
				break;
			case STATUS.DIG:
				if (this._diggingHole) {
					minerPosition.y += _velocity.y;
					this._hole.setDeep(minerPosition.y - 25);

					let items = this._digDelegate(position.x, minerPosition.y - 50);
					if (items.length > 0) {
						this.playDigIdle();
					}
					for (const item of items) {
						this.playAddItem(item);
					}

					if (minerPosition.y > this._maxDepth) {
						this.playIdle();
						this.bubbling('digEnd');
					}
				}
				break;
			case STATUS.DIG_IDLE:

				break;
		}
	}

	get dir() {
		return this._minerTransform.scale.x;
	}

	set dir(v) {
		this._minerTransform.scale.x = v;
	}

	standSide(dir) {
		this.transform.position.x = walkRange * -dir;
		this.dir = dir;
	}

	playIdle() {
		this._status = STATUS.IDLE;

		this._bodyAnim.play('idle', -1);
	}

	playWalk() {
		this._status = STATUS.WALK;

		this._diggingHole = false;
		this._bodyAnim.play('walk', -1);
		this._velocity.x = speed.x;
		this.dir = 1;
	}

	playDig() {
		this._bodyAnim.play('beginDig', 1);
		this._status = STATUS.DIG;

		this._velocity.setXY(0, speed.y);
	}

	playDigIdle() {
		this._bodyAnim.play('idle', -1);
		this._status = STATUS.DIG_IDLE;

		this._velocity.y = 0;
	}

	playAddItem(item) {
		let target: Entity;
		for (let item of this.Items.children) {
			if (!item.enabled) {
				target = item;
				target.enabled = true;
				break;
			}
		}
		if (!target) {
			target = instantiate(this.itemHangPrefab);
			this.Items.addChild(target);
		}

		item.exclude = true;
		item.entity.enabled = false;
		const pos = item.getComponent(Transform).globalPosition;
		const targetTransform = target.getComponent(Transform);
		let localPos = this.Items.getComponent(Transform).globalPositionToLocal(pos);
		targetTransform.position.copyFrom(localPos);
		targetTransform.scale.setXY(1, 1);

		const position = {x: this._itemCount * this.itemGap.x, y: this._itemCount * this.itemGap.y};
		this._itemCount++;

		createTween(this, targetTransform, false, {fields: ['x', 'y']})
			.to({position, scale: this.smallItemScale.toObj()}, 500, ease.cubicInOut)
			.call(() => {
				this.playDig();
			});
	}

	onAnimationComplete(label) {
		switch (label) {
			case 'beginDig':
				this._bodyAnim.play('dig', -1);
				this._effectAnim.play(0, 1);

				this._hole.show();
				this._diggingHole = true;
				break;
		}
	}

	onAnimationLoopComplete(label) {
		switch (label) {
			case 'dig':
				this._effectAnim.play(0, 1);
				break;
		}
	}

	avoidToDig(position: Vector2D) {
		setTimeout(() => {
			this._avoidPosition = position;
		}, Math.random() * 500 + 500);
	}
}
