package ecs.systems;

import ecs.components.*;
import ecs.core.Entity;
import ecs.core.System;
import res.RES;
import res.collisions.Collider;
import res.display.FrameBuffer;
import res.input.Key;
import res.input.KeyboardEvent;
import res.input.MouseEvent;

using Lambda;
using Math;
using Std;
using res.display.Sprite;
using res.graphics.Painter;

class BuyUISystem extends System {
	static final BTN_RADIUS = 10;
	static final BTN_GAP = 3;

	var res:RES;
	var placementPreview:Entity;

	final allOptions = ['laser', 'fire', 'bomb'];
	final options:Array<String> = [];
	final prices:Array<Int> = [50, 100, 200];

	public function unlockNext() {
		if (allOptions.length > 0) {
			options.push(allOptions.shift());
		}
	}

	function spawnPreview(satEntity:Entity, x:Int, y:Int) {
		var entity = new Entity();

		entity.add(new Spatial(x, y));
		entity.add(satEntity.get(ecs.components.Sprite));
		entity.add(new EntityContainer(satEntity));
		entity.add(new OrbitPreview(0, 0));

		var triggerRadius = satEntity.get(TriggerRadius);
		if (triggerRadius != null)
			entity.add(triggerRadius);

		return entity;
	}

	function spawnSatellite(type:String) {
		final entity = new Entity('satellite');

		entity.add(new Spatial());
		entity.add(new Orbiter());
		entity.add(new ecs.components.Sprite(res.rom.sprites['sat_${type}'], 0.5, 0.5));
		entity.add(new HealthDisplay());
		entity.add(new Emitter(0.1, 1, 0, 5, [16]));
		entity.add(new CollisionCircle(3));
		entity.add(new Aim(Hostile));
		entity.add(new HasOre(prices[options.indexOf(type)]));

		switch type {
			case 'laser':
				entity.add(new LaserGun());
				entity.add(new Health(50));
				entity.add(new TriggerRadius(40));
			case 'fire':
				entity.add(new FireGun());
				entity.add(new Health(75));
				entity.add(new TriggerRadius(30));
			case 'bomb':
				entity.add(new Health(100));
				entity.add(new BombSpawn());
		}

		return entity;
	}

	public function new(res:RES) {
		super();

		this.res = res;
	}

	public function keyEvent(event:KeyboardEvent) {
		switch event {
			case KEY_DOWN(keyCode):
				if (keyCode == Key.ESCAPE) {
					if (placementPreview != null) {
						engine.remove(placementPreview);
						placementPreview = null;
					}
				}
			case _:
		}
	}

	public function mouseEvent(event:MouseEvent) {
		final economicsSystem = engine.getSystem(EconomicsSystem);
		switch (event) {
			case DOWN(button, posX, posY):
				switch (button) {
					case LEFT:
						if (placementPreview != null) {
							if (enabled) {
								final entity = placementPreview.get(EntityContainer).entity;

								final orbiter = entity.get(Orbiter);

								final orbitPreview = placementPreview.get(OrbitPreview);
								final speed = orbitPreview.speed * -orbitPreview.direction;

								orbiter.phase = orbitPreview.phase;
								orbiter.rX = orbitPreview.rX;
								orbiter.rY = orbitPreview.rY;
								orbiter.angularSpeed = speed;

								final hasOre = entity.get(HasOre);

								economicsSystem.spend(hasOre.ore);

								engine.add(entity);
							}

							engine.remove(placementPreview);
							placementPreview = null;
						} else {
							for (n => id in options) {
								final p = buttonCenter(n);

								final price = prices[n];

								if (price <= economicsSystem.ore) {
									final result = Collider.collide(CIRCLE(p.x, p.y, BTN_RADIUS), CIRCLE(posX, posY, 0));

									switch (result) {
										case OFFSET(_):
											placementPreview = spawnPreview(spawnSatellite(id), posX, posY);

											engine.add(placementPreview);

											break;
										case _:
									}
								}
							}
						}
					case RIGHT:
						keyEvent(KEY_DOWN(Key.ESCAPE));

					case _:
				}
			case _:
		}
	}

	function buttonCenter(n:Int):{x:Int, y:Int} {
		final tg = (BTN_RADIUS + BTN_GAP) * 2;

		final tw = tg * (options.count() - 1);

		return {
			x: ((res.width - tw) / 2 + n * tg).int(),
			y: res.height - 20
		};
	}

	override function render(frameBuffer:FrameBuffer) {
		if (placementPreview == null) {
			final economicsSystem = engine.getSystem(EconomicsSystem);

			frameBuffer.scrollX = frameBuffer.scrollY = 0;

			for (n => id in options) {
				final price = prices[n];

				final bc = price <= economicsSystem.ore ? 9 : 16;

				final p = buttonCenter(n);
				frameBuffer.circle(p.x, p.y, BTN_RADIUS, bc, bc);

				final sp = res.rom.sprites['sat_${id}'];

				frameBuffer.drawSprite(sp, (p.x - sp.width / 2).ceil(), (p.y - sp.height / 2).ceil());

				final c = (price <= economicsSystem.ore ? 5 : 16);

				final psp = res.rom.sprites['${price}'];
				frameBuffer.drawSprite(psp, (p.x - psp.width / 2).ceil(), p.y + BTN_RADIUS + 3, null, null, 0, false, false, false, [5 => c]);

				n++;
			}
		}
	}
}
