package ecs.systems;

import Math.*;
import ecs.components.Emitter;
import ecs.components.Spatial;
import ecs.core.Entity;
import ecs.core.System;
import res.display.FrameBuffer;

using Std;

typedef Particle = {
	x:Int,
	y:Int,
	ttl:Float,
	idx:Int
};

class DrawParticlesSystem extends System {
	final particles:Array<Particle> = [];

	public function new() {
		super(Spatial, Emitter);
	}

	public function spawn(particle:Particle) {
		particles.push(particle);
	}

	override function updateEntity(entity:Entity, dt:Float) {
		final emitter = entity.get(Emitter);
		final spatial = entity.get(Spatial);

		if (emitter.ttl != null && emitter.ttl <= 0) {
			entity.remove(emitter);
			return;
		}

		if (emitter.time <= 0) {
			for (_ in 0...emitter.perEmit) {
				final r = emitter.radius * Math.random();
				final d = emitter.radius > 0 ? 1 - (r / emitter.radius) : 1;
				final a = (PI * 2) * random();

				spawn({
					x: (spatial.x + cos(a) * r).int(),
					y: (spatial.y + sin(a) * r).int(),
					ttl: emitter.maxTtl * d,
					idx: emitter.colors[(random() * emitter.colors.length).int()]
				});
			}

			emitter.time = emitter.interval + emitter.time;
		} else
			emitter.time -= dt;

		if (emitter.ttl != null)
			emitter.ttl -= dt;
	}

	override function update(dt:Float) {
		for (particle in particles) {
			if (particle.ttl <= 0) {
				particles.remove(particle);
			} else {
				particle.ttl -= dt;
			}
		}

		super.update(dt);
	}

	override function render(frameBuffer:FrameBuffer) {
		for (particle in particles) {
			frameBuffer.setIndex(particle.x, particle.y, particle.idx);
		}
	}
}
