import {TextureMgr} from "../Mgr/TextureMgr";
import {MUtils} from "../Global/MUtils";
import MTimer from "../Global/MTimer";
import {Pool, PoolGroup, PoolElement} from "../Component/Pool";
import {DataMgr} from "../Mgr/DataMgr";
import GameMgr from "../Mgr/GameMgr";


const InitSpeedValue: number = 0.08;
const alphaDuration: number = 300;
const alphaPerFrame: number = 1 / (alphaDuration / (1000 / 60));
const InitAcceleration: number = -0.00005;
const noAlphaDuration: number = 200 / (1000 / 60);

class Line {
	public sprite: engine.Sprite = null;
	private direction: engine.Point = null;
	private speedValue: number = InitSpeedValue;

	constructor(parent: engine.Container, type: number, color: number, rotation: number) {
		const sprite = new engine.Sprite(TextureMgr.get(("fireworks_line_" + type) as any, color));
		parent.addChild(sprite);
		sprite.anchorX = sprite.width / 2;
		sprite.rotation = rotation;
		this.sprite = sprite;

		//计算方向
		let dir = MUtils.getVector(rotation + 90)
		this.direction = dir;
	}

	private frameTimer = 0;

	public init() {
		this.sprite.y = -this.sprite.height;
		this.sprite.alpha = 1;
		this.sprite.x = 0;
		this.sprite.y = 0;
		this.frameTimer = 0;
		this.speedValue = InitSpeedValue;
	}

	public onUpdate(dt: number) {
		this.sprite.x += this.direction.x * this.speedValue * dt;
		this.sprite.y += this.direction.y * this.speedValue * dt;
		if (this.frameTimer > noAlphaDuration) {
			this.sprite.alpha -= alphaPerFrame * MTimer.dtFactor;
		}

		this.frameTimer++;
	}
}


export class SpBoomEffectMgr extends GameMgr {
	constructor() {
		super("SpBoomEffectMgr")
	}

	public list: SpBoomEffect[] = [];

	protected onUpdate(dt: number) {
		if (this.pause) return;
		let filter: SpBoomEffect[] = [];
		for (let i of this.list) {
			if (i.onUpdate(dt)) {
				filter.push(i);
			}
		}
		this.list = filter;
	}
}

class SpBoomEffect extends engine.Container implements PoolElement {
	private lines: Line[] = [];

	public onUpdate(dt: number) {
		for (let i of this.lines) {
			i.onUpdate(dt);
		}

		if (this.lines[0].sprite.alpha <= 0) {
			DataMgr.game._pool.boomEffect.recycle(this.poolKey, this);
			return false;
		}
		return true;
	}

	constructor(color: number, size: number) {
		super();
		this.scaleX = this.scaleY = 0.5 * size + 0.5;
		this.rotation = MUtils.random(0, 90);
		for (let i = 0; i < 16; i++) {
			let line = new Line(this, i % 2, color, i * 22.5);
			this.lines.push(line);
		}
		DataMgr.game._boomEffectMgr.list.push(this);
	}

	onElementInit() {
		this.visible = true;
		this.alpha = 1;
		for (let i of this.lines) {
			i.init();
		}
		DataMgr.game._boomEffectMgr.list.push(this);
	}

	onElementRecycle() {
		this.visible = false;
	}

	poolKey: string;
}


class SpBoomEffectPool extends Pool<SpBoomEffect> {
	public spwan(color: number, size: number): SpBoomEffect {
		if (this.data.length > 0) {
			const element = this.data.shift();
			element.onElementInit();
			return element;
		} else {
			const e = new SpBoomEffect(color, size);
			this.layer.addChild(e);
			return e;
		}
	}
}

export default class SpBoomEffectPoolGroup extends PoolGroup<SpBoomEffect> {
	public spwan(color: number, size: number) {
		const key = color.toString() + size;
		if (!this.data[key]) {
			this.data[key] = new SpBoomEffectPool(this.layer)
		}
		const element = this.data[key].spwan(color, size);
		element.poolKey = key;
		return element;
	}
}

