/**
 * Created by rockyl on 2019-05-16.
 *
 * 飞行序列
 */

import ScillaComponent from "components/base/ScillaComponent";
import {createTween, ease, Entity, instantiate, resource, ScillaEvent, Vector2D} from "scilla";
import Transform from "components/base/Transform";

export default class FlySequence extends ScillaComponent {
	ToEntity: Entity;

	itemPrefab: resource;
	count = 10;
	fromPos = new Vector2D();
	toPos = new Vector2D();
	toScale = new Vector2D(0.3, 0.3);
	duration = 3000;
	delay = 500;
	itemInterval = 100;
	hideWhenComplete = true;
	offset = 1;

	onComplete: ScillaEvent = new ScillaEvent();

	private _items: Transform[] = [];
	private _itemDuration;
	private _counting;
	private _timerDelay;
	private _timer;

	onCreate() {
		super.onCreate();

		this._itemDuration = this.duration - this.count * this.itemInterval - this.delay;

		for (let i = 0; i < this.count; i++) {
			let itemEntity = instantiate(this.itemPrefab);
			itemEntity.enabled = false;
			this.entity.addChild(itemEntity);

			let transform = itemEntity.getComponent(Transform);
			this._items.push(transform);
		}
	}

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

	play() {
		this.stop();

		if (this.ToEntity) {
			this.toPos = this.transform.globalPositionToLocal(this.ToEntity.getComponent(Transform).globalPosition);
		}

		let first = this._items[0];
		first.entity.enabled = true;
		first.position.copyFrom(this.fromPos);
		first.scale.setXY(1, 1);
		this._counting = 1;

		this._timerDelay = setTimeout(this.onDelay, this.delay);
	}

	stop(hidden = true) {
		if (this._timer) {
			clearInterval(this._timer);
			this._timer = null;
		}
		if (this._timerDelay) {
			clearTimeout(this._timerDelay);
			this._timerDelay = null;
		}
		if (hidden) {
			for (let item of this._items) {
				item.entity.enabled = false;
			}
		}
	}

	private onDelay = () => {
		this._timer = setInterval(() => {
			if (this._counting > this.count - 1) {
				this.stop(false);
				this._flyItem(this._items[0], this.onEnd);
				return;
			}

			this._playItem(this._counting);
			this._counting++;
		}, this.itemInterval)
	}

	private onEnd = () => {
		this.onComplete.invoke();
	}

	private _playItem(index) {
		let item = this._items[index];
		item.entity.enabled = true;
		item.position.copyFrom(this.fromPos);
		item.scale.setXY(0, 0);

		this._flyItem(item);
	}

	private _flyItem(item, callback?) {
		const itemDuration = this._itemDuration;

		createTween(this, item.scale, false)
			.to({x: 1, y: 1}, itemDuration * 0.1)
			.wait(itemDuration * 0.4)
			.to(this.toScale.toObj(), itemDuration * 0.5);

		createTween(this, item.position)
			.to({x: this.toPos.x}, itemDuration);

		let easeFuncCreator = Math.random() > 0.5 ? ease.getPowOut : ease.getPowIn;
		let easeFunc = easeFuncCreator(Math.random() + this.offset);
		createTween(this, item.position)
			.to({y: this.toPos.y}, itemDuration, easeFunc)
			.call(() => {
				if (this.hideWhenComplete) {
					item.entity.enabled = false;
				}
				callback && callback();
			});
	}
}
