package zero1hd.polyjet.entity;

import java.util.Arrays;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pool;

import zero1hd.polyjet.audio.map.EntitySpawnInfo;
import zero1hd.polyjet.entity.ally.Laser;
import zero1hd.polyjet.entity.enemies.Bar;
import zero1hd.polyjet.entity.enemies.Flake;
import zero1hd.polyjet.entity.enemies.Pellet;
import zero1hd.polyjet.entity.enemies.Shard;
import zero1hd.polyjet.entity.enemies.VoidCircle;

public class EntityController {
	AssetManager assets;
	
	public Array<Entity> activeAllies;
	public Array<Entity> activeEnemies;
	
	//Enemy pool declaration;
	private Pool<VoidCircle> voidCirclePool;
	private Pool<Pellet> pelletPool;
	private Pool<Shard> shardPool;
	private Pool<Bar> barPool;
	private Pool<Flake> flakePool;
	
	//Ally pool declaration;
	private Pool<Laser> laserPool;
	
	public EntityController(AssetManager assetManager) {
		activeAllies = new Array<Entity>();
		activeEnemies = new Array<Entity>();
		this.assets = assetManager;
		
		//Enemy pool initialization;
		voidCirclePool = new Pool<VoidCircle>() {
			@Override
			protected VoidCircle newObject() {
				return new VoidCircle(assets.get("void_circle.png", Texture.class));
			}
		};
		pelletPool = new Pool<Pellet>() {
			@Override
			protected Pellet newObject() {
				return new Pellet(assets.get("pellet.png", Texture.class));
			}
		};
		shardPool = new Pool<Shard>() {
			@Override
			protected Shard newObject() {
				return new Shard(assets.get("shard.png", Texture.class));
			}
		};
		barPool = new Pool<Bar>() {
			@Override
			protected Bar newObject() {
				return new Bar(assets.get("bar.png", Texture.class));
			}
		};
		flakePool = new Pool<Flake>() {
			@Override
			protected Flake newObject() {
				return new Flake(assets.get("flake.png", Texture.class));
			}
		};
		
		//Ally pool initialization;
		laserPool = new Pool<Laser>() {
			@Override
			protected Laser newObject() {
				return new Laser(assets.get("laser.png", Texture.class));
			}
		};
		
	}
	
	public Entity retrieveEntity(Entities entity) {
		switch (entity) {
		case VOID_CIRCLE:
			VoidCircle voidCircle = voidCirclePool.obtain();
			activeEnemies.add(voidCircle);
			return voidCircle;
		case LASER:
			Laser laser = laserPool.obtain();
			activeAllies.add(laser);
			return laser;
		case PELLET:
			Pellet pellet = pelletPool.obtain();
			activeEnemies.add(pellet);
			return pellet;
		case SHARD:
			Shard shard = shardPool.obtain();
			activeEnemies.add(shard);
			return shard;
		case BAR:
			Bar bar = barPool.obtain();
			activeEnemies.add(bar);
			return bar;
		case FLAKE:
			Flake flake = flakePool.obtain();
			activeEnemies.add(flake);
			return flake;
		default:
			return null;
		}
	}
	
	public EntitySpawnInfo spawnEntity(Stage stage, EntitySpawnInfo entitySpawnInfo) {
		if (entitySpawnInfo != null) {
			float[] param = entitySpawnInfo.getParameters();
			Gdx.app.debug("Spawning Entity", entitySpawnInfo.toString() + " parameters: " + Arrays.toString(param) + "Attributed spawn window: " + entitySpawnInfo.getSpawnWindowID());
			switch (entitySpawnInfo.getEntityType()) {
			case VOID_CIRCLE:
				VoidCircle voidCircle = voidCirclePool.obtain();
				voidCircle.init(param[0], param[1], param[2], param[3], param[4]);
				activeEnemies.add(voidCircle);
				stage.addActor(voidCircle);
				break;
			case LASER:
				Laser laser = laserPool.obtain();
				laser.init(param[0], param[1], param[2]);
				activeAllies.add(laser);
				stage.addActor(laser);
				break;
			case PELLET:
				Pellet pellet = pelletPool.obtain();
				pellet.init(param[0], param[1], param[2], param[3]);
				activeEnemies.add(pellet);
				stage.addActor(pellet);
				break;
			case SHARD:
				Shard shard = shardPool.obtain();
				shard.init(param[0], param[1], param[2], param[3], (int) param[4]);
				activeEnemies.add(shard);
				stage.addActor(shard);
				break;
			case BAR:
				Bar bar = barPool.obtain();
				bar.init(param[0], param[1]);
				activeEnemies.add(bar);
				stage.addActor(bar);
				break;
			case FLAKE:
				Flake flake = flakePool.obtain();
				Shard[] shards = new Shard[(int) param[0]];
				for (int i = 0; i < shards.length; i++) {
					shards[i] = (Shard) retrieveEntity(Entities.SHARD);
					shards[i].init(param[6], param[7], param[8], param[9], (int) param[10]);
					stage.addActor(shards[i]);
				}
				flake.init(param[1], param[2], param[3], param[4], param[5], shards);
				activeEnemies.add(flake);
				stage.addActor(flake);
				break;
			}
		}
		return entitySpawnInfo;
	}
	
	public void free(Entity entity) {
		if (entity.getEntityType().isEnemy()) {
			activeEnemies.removeValue(entity, true);
		} else {
			activeAllies.removeValue(entity, true);
		}
		switch (entity.getEntityType()) {
		case VOID_CIRCLE:
			VoidCircle voidCircle = (VoidCircle) entity;
			voidCircle.remove();
			voidCirclePool.free(voidCircle);
			break;
		case LASER:
			Laser laser = (Laser) entity;
			laser.remove();
			laserPool.free(laser);
			break;
		case PELLET:
			Pellet pellet = (Pellet) entity;
			pellet.remove();
			pelletPool.free(pellet);
			break;
		case SHARD:
			Shard shard = (Shard) entity;
			shard.remove();
			shardPool.free(shard);
			break;
		case BAR:
			Bar bar = (Bar) entity;
			bar.remove();
			barPool.free(bar);
			break;
		case FLAKE:
			Flake flake = (Flake) entity;
			flake.remove();
			flakePool.free(flake);
			break;
		default:
			break;
		}
	}
	
	public void deathClean() {
		for (int i = 0; i < activeAllies.size; i ++) {
			if (activeAllies.get(i).isDead()) {
				free(activeAllies.get(i));
			}
		}
		for (int i = 0; i < activeEnemies.size; i++) {
			if (activeEnemies.get(i).isDead()) {
				free(activeEnemies.get(i));
			}
		}
	}
	
}
