package projectzombie.entity.particle;

import java.util.Random;

import gl_engine.MathHelpers;
import gl_engine.texture.TextureRef3D;
import gl_engine.vec.Vec3d;
import projectzombie.Main;
import projectzombie.entity.EntityParticle;
import projectzombie.entity.EntityParticlePart;
import projectzombie.model.IModel;
import projectzombie.model.Model;
import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer;

public class ParticleBreak extends EntityParticle
{
	protected static final Random rand = new Random();
	
	protected class Break extends EntityParticlePart
	{
		public Vec3d velocity;
		public boolean moving;
		
		public Break(TextureRef3D tex, Vec3d pos, Vec3d velocity, boolean moving, double size, int flags) {
			super(tex, pos, size, flags);
			
			this.velocity = velocity;
			this.moving = moving;
		}
		
		@Override
		public boolean isFlat() {
			return isStill(this);
		}
		
		@Override
		public double getFade() {
			return getParticleFade();
		}
	}
	
	protected Break[] particles;
	protected int still, time;
	protected double still_ypos;
	
	protected double getParticleFade() {
		return time / 1000.0;
	}
	
	public double getParticleSize() {
		return 0.1;
	}
	
	protected double getParticleSpeed() {
		return 0.01;
	}
	
	public ParticleBreak(Vec3d pos, Vec3d velocity, IModel model) {
		this(pos, velocity, model, 100, 0.05);
	}
	
	public ParticleBreak(Vec3d pos, Vec3d velocity, IModel model, int count) {
		this(pos, velocity, model, count, 0.05);
	}
	
	protected ParticleBreak(Vec3d pos, Vec3d velocity, IModel model, int count, double velocity_up_multiplier) {
		super(new Vec3d(pos.x, 0, pos.z), new Vec3d(0, 0, 0));
		
		if(pos.squareDistance(Main.player.getPos()) > 32) {
			count = 0;
		}
		
		this.hasGravity = false;
		
		double model_height = getHeight(model);
		float[] verticies = model.getVerticies();
		
		if(model_height > 1) {
			count *= model_height;
		}
		
		if(model.getSize() == 0) {
			count = 0;
		}
		
		particles = new Break[count];
		
		for(int i=0;i<particles.length;i++)
		{
			int[] tex_id = {0};
			TextureRef3D ref = model.getRandomChunk(tex_id);
			
			Break particle = new Break(ref,
					pos.add(new Vec3d(0, rand.nextDouble() * model_height, 0)),
					velocity.multiply(rand.nextDouble()).add(
							MathHelpers.moveTowards2(getParticleSpeed(), rand.nextDouble() * MathHelpers.TWO_PI).xny().add(
							new Vec3d(0, rand.nextDouble() * velocity_up_multiplier, 0))), true, getParticleSize(),
					((int)verticies[tex_id[0] * Model.SIZE + Model.SIZE - 1] & 0b0110) | 0b1000);
			
			particles[i] = particle;
		}
		
		still_ypos = 0.0125;
		time = 1000;
		still = 0;
	}
	
	protected double getHeight(IModel model) {
		return model.getHeight();
	}
	
	protected void onAllStill() {
		if(time < 0) {
			onAllDead();
		}
	}
	
	protected void onAllDead() {
		kill();
	}
	
	protected boolean isStill(Break particle) {
		return particle.pos.y <= still_ypos;
	}
	
	protected void onStill(Break particle) {
		particle.moving = false;
		particle.pos.y = still_ypos;
		particle.flags &= 0b0110;
		still += 1;
	}
	
	@Override
	public void tick(Chunk chunk, Layer layer) {
		super.tick(chunk, layer);
		
		if(isDead()) {
			return;
		}
		
		time -= 1;
		
		if(still == particles.length) {
			onAllStill();
			return;
		}
		
		for(int i=0;i<particles.length;i++)
		{
			Break particle = particles[i];
			
			if(!particle.moving) {
				continue;
			}
			
			if(isStill(particle)) {
				onStill(particle);
				continue;
			}
			
			particle.velocity.y -= MathHelpers.FallSpeed;
			particle.pos = particle.pos.add(particle.velocity);
		}
	}

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

	@Override
	public int getParticleCount() {
		return particles.length;
	}

	@Override
	public EntityParticlePart getParticleAt(int id) {
		return particles[id];
	}

	
	
}
