package projectzombie.entity;

import bdf.types.BdfNamedList;
import bdf.types.BdfObject;
import gl_engine.MathHelpers;
import gl_engine.vec.Vec2d;
import gl_engine.vec.Vec2i;
import gl_engine.vec.Vec3d;
import projectzombie.Main;
import projectzombie.entity.particle.ParticleBlood;
import projectzombie.entity.particle.ParticleSmoke;
import projectzombie.init.Models;
import projectzombie.init.Sounds;
import projectzombie.init.Tiles;
import projectzombie.model.Model;
import projectzombie.util.TileState;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;

public class EntityExplosion extends Entity
{
	private double damage;
	private int radius;
	
	public EntityExplosion(BdfObject bdf) {
		BdfClassLoad(bdf);
	}
	
	public EntityExplosion(Vec3d pos, int radius, double damage) {
		super(pos, new Vec3d(0, 0, 0));
		this.damage = damage;
		this.radius = radius;
	}
	
	@Override
	public void BdfClassLoad(BdfObject bdf) {
		super.BdfClassLoad(bdf);
		
		BdfNamedList nl = bdf.getNamedList();
		damage = nl.get("damage").getDouble();
		radius = nl.get("radius").getInteger();
	}
	
	@Override
	public void BdfClassSave(BdfObject bdf) {
		super.BdfClassSave(bdf);
		
		BdfNamedList nl = bdf.getNamedList();
		nl.set("damage", bdf.newObject().setDouble(damage));
		nl.set("radius", bdf.newObject().setInteger(radius));
	}
	
	@Override
	public void tick(Chunk chunk, Layer layer) {
		super.tick(chunk, layer);
		
		boolean killed_entities = false;
		Vec2d pos = getPos().xz();
		
		// Kill all the nearby entities
		for(Entity e : layer.getNearbyEntities(pos, radius))
		{
			// Is this entity alive
			if(e instanceof EntityAlive)
			{
				EntityAlive ea = (EntityAlive)e;
				
				// Remove some health from the entity based on were the entity is
				killed_entities = true;
				double distance = e.getPos().distance(getPos());
				
				if(distance == 0) {
					ea.addBlastDamage(damage);
				}
				
				else {
					ea.addBlastDamage(damage / distance);
				}
			}
		}
		
		int multiplier = killed_entities ? 2 : 1;
		Entity[] entities = new Entity[(int)(Math.PI * radius * radius) * multiplier];
		int upto = 0;
		
		// Loop over the tiles around the tnt
		for(int ex=-radius;ex<radius;ex++) {
			for(int ey=-radius;ey<radius;ey++)
			{
				// Calculate the distance from the explosion centre
				double distance = Math.sqrt(ex*ex + ey*ey);
				
				// Is the point within the distance from the explosion centre
				if(distance < radius)
				{
					// Get the actual tile position
					double px = ex + pos.x;
					double py = ey + pos.y;
					
					// Get the layer
					Layer l = Main.world.getLayer();
					
					// Get the front and back tile
					Vec2i tpos = new Vec2i(MathHelpers.floor(px), MathHelpers.floor(py));
					TileState bts = l.getBackTile(tpos);
					TileState fts = l.getFrontTile(tpos);
					
					// Is this tile the same as the "empty" tile
					TileState ets = l.layergen.getTileDestroyed(layer, tpos);
					
					// Set the tiles
					if(!bts.tile.unbreakable) {
						l.setBackTile(ets, tpos);
						//if(fts.tile instanceof IHasTexture)
						//l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), bts, 1));
					}
					
					if(!fts.tile.unbreakable) {
						l.setFrontTile(Tiles.VOID.getDefaultState(), tpos);
						//if(fts.tile instanceof IHasTexture)
						//l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), fts, 1));
					}
					
					if(upto + multiplier > entities.length) {
						continue;
					}
					
					Vec3d spos = new Vec3d(px, 0, py);
					Vec3d svel;
					
					if(distance == 0) {
						svel = MathHelpers.moveTowards2(0.01, Math.random() * MathHelpers.TWO_PI).xny();
					} else {
						svel = spos.xz().subtract(pos).divide(distance * 100).xny();
					}
					
					// Spawn some blood if entities were killed
					if(killed_entities)
						entities[upto + 1] = new ParticleBlood(new Vec3d(px, 0, py), new Vec3d(0, 0, 0), 1);
					
					// Spawn some smoke
					entities[upto] = new ParticleSmoke(spos, svel);
	
					upto += multiplier;
				}
			}
		}
		
		layer.spawnEntity(new EntityContainer(getPos(), getVelocity(), entities));
		
		// Play the explosion sound
		Sounds.EXPLOSION.play(new Vec3d(pos.x, 0, pos.y), 1);
		
		// Kill the explosion entity
		kill();
	}

	@Override
	public Model getModel() {
		return null;
	}
}
