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;
    }
}

