import { Container, Sprite, Texture } from 'pixi.js';
import { Rng, createRng } from '../math/rng';

/**
 * Простая система частиц: эмиттер спавнит точки (Texture.WHITE, подкрашенные)
 * с заданной скоростью, временем жизни и затуханием.
 * Используется для атмосферы: пепел, мотыльки, пыль, искры.
 */
export interface EmitterOptions {
    /** Цвет частиц (0xRRGGBB). */
    color: number;
    /** Частиц в секунду. */
    rate: number;
    /** Время жизни частицы, секунды (min..max). */
    lifetime: [number, number];
    /** Начальная скорость, виртуальных пикселей/сек: (minX..maxX, minY..maxY). */
    velocity: { x: [number, number]; y: [number, number] };
    /** Ускорение (гравитация/ветер), пикселей/сек². */
    acceleration?: { x?: number; y?: number };
    /** Размер частицы в пикселях (1..4). */
    size?: number;
    /** Спавн в прямоугольнике вокруг позиции эмиттера (по умолчанию точка). */
    spawnArea?: { width: number; height: number };
    /** Затухание альфы к концу жизни (по умолчанию true). */
    fadeOut?: boolean;
    /** Seed для повторяемого движения. */
    seed?: number;
}

interface Particle {
    sprite: Sprite;
    vx: number;
    vy: number;
    age: number;
    lifetime: number;
}

export class ParticleEmitter extends Container {
    private particles: Particle[] = [];
    private spawnTimer = 0;
    private rng: Rng;

    constructor(private options: EmitterOptions) {
        super();
        this.rng = createRng(options.seed ?? 0x9e3779b9);
    }

    update(dt: number): void {
        // Спавн
        this.spawnTimer += dt * this.options.rate;
        while (this.spawnTimer >= 1) {
            this.spawnTimer -= 1;
            this.spawn();
        }

        // Обновление
        const accX = this.options.acceleration?.x ?? 0;
        const accY = this.options.acceleration?.y ?? 0;
        for (const p of this.particles) {
            p.age += dt;
            p.vx += accX * dt;
            p.vy += accY * dt;
            p.sprite.x += p.vx * dt;
            p.sprite.y += p.vy * dt;
            if (this.options.fadeOut ?? true) {
                p.sprite.alpha = Math.max(0, 1 - p.age / p.lifetime);
            }
        }

        // Сбор «умерших»
        const dead = this.particles.filter((p) => p.age >= p.lifetime);
        for (const p of dead) {
            p.sprite.destroy();
        }
        if (dead.length > 0) {
            this.particles = this.particles.filter((p) => p.age < p.lifetime);
        }
    }

    /** Убрать все частицы (например, при выходе со сцены). */
    clear(): void {
        for (const p of this.particles) p.sprite.destroy();
        this.particles = [];
    }

    get count(): number {
        return this.particles.length;
    }

    private spawn(): void {
        const size = this.options.size ?? 2;
        const sprite = new Sprite(Texture.WHITE);
        sprite.width = size;
        sprite.height = size;
        sprite.tint = this.options.color;

        const area = this.options.spawnArea;
        sprite.x = area ? this.rng.int(0, area.width) - area.width / 2 : 0;
        sprite.y = area ? this.rng.int(0, area.height) - area.height / 2 : 0;
        sprite.alpha = 0; // появится в следующем кадре без «вспышки»

        const v = this.options.velocity;
        this.particles.push({
            sprite,
            vx: v.x[0] + this.rng.next() * (v.x[1] - v.x[0]),
            vy: v.y[0] + this.rng.next() * (v.y[1] - v.y[0]),
            age: 0,
            lifetime: this.options.lifetime[0] + this.rng.next() * (this.options.lifetime[1] - this.options.lifetime[0])
        });
        this.addChild(sprite);
    }
}