package electroblob.wizardry.client.particle;

import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import org.lwjgl.opengl.GL11;

//@SideOnly(Side.CLIENT)
@Mod.EventBusSubscriber(Side.CLIENT)
public class ParticleVine extends ParticleTargeted {

	/** Half the width of the vine. */
	private static final float THICKNESS = 0.02f;
	private static final float LEAF_SPACING = 0.5f;
	private static final float SEGMENT_LENGTH = 1;

	private static final ResourceLocation STEM_TEXTURE = new ResourceLocation(Wizardry.MODID, "particle/vine");
	private static final ResourceLocation[] LEAF_TEXTURES = generateTextures("vine_leaf", 5);

	public ParticleVine(World world, double x, double y, double z){
		super(world, x, y, z, STEM_TEXTURE);
		//this.setRBGColorF(1, 1, 1);
		this.setMaxAge(0);
		this.particleScale = 1;
		this.setRBGColorF(0.2f, 0.65f, 0f);
	}

	@Override
	public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ){
		// When using FX layer 1 the BufferBuilder is already drawing... but in the wrong mode :/
		Tessellator.getInstance().draw();
		super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
		buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);
	}

	@Override
	protected void draw(Tessellator tessellator, double length, float partialTicks){

		random.setSeed(seed); // Reset the random so we get the same sequence of numbers each frame
		
		float scale = this.particleScale;

		BufferBuilder buffer = tessellator.getBuffer();

		GlStateManager.disableLighting();
		OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);

		// Hmmmm we can't get the texture to tile using OpenGL texture space because it's on a sprite sheet...
		// Solution: Draw loads of boxes. Simple!
		// (Since there aren't going to be that many of these particles around we could have not used sprite sheets
		// and done the OpenGL texture space thing, but this is kinda easier)
		// Everything is drawn back-to-front so it looks like the vine is growing from the origin, not the endpoint
		int i = 0;
		while(i + SEGMENT_LENGTH < length){
			drawShearedBox(tessellator, 0, 0, length-i, 0, 0, length-i-SEGMENT_LENGTH, THICKNESS * scale,
					particleRed, particleGreen, particleBlue, particleAlpha);
			i += SEGMENT_LENGTH;
		}

		drawShearedBox(tessellator, 0, 0, length-i, 0, 0, 0, THICKNESS * scale,
				particleRed, particleGreen, particleBlue, particleAlpha);

		for(double l=length; l>0; l-=LEAF_SPACING){

			GlStateManager.pushMatrix();

			GlStateManager.rotate(random.nextInt(4) * 90, 0, 0, 1);

			buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);

			TextureAtlasSprite leaf = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(
					LEAF_TEXTURES[random.nextInt(LEAF_TEXTURES.length)].toString());

			float w = 16 * THICKNESS * scale;
			float u1 = leaf.getMinU();
			float u2 = leaf.getMaxU();
			float v1 = leaf.getMinV();
			float v2 = leaf.getMaxV();

			float colourVariation = 0.3f;

			float r = MathHelper.clamp(particleRed + (random.nextFloat() - 0.5f) * colourVariation, 0, 1);
			float g = MathHelper.clamp(particleGreen + (random.nextFloat() - 0.5f) * colourVariation, 0, 1);
			float b = MathHelper.clamp(particleBlue + (random.nextFloat() - 0.5f) * colourVariation, 0, 1);

			buffer.pos(0, 0, l).tex(u1, v1).color(r, g, b, particleAlpha).endVertex();
			buffer.pos(w, 0, l).tex(u2, v1).color(r, g, b, particleAlpha).endVertex();
			buffer.pos(w, w, l).tex(u2, v2).color(r, g, b, particleAlpha).endVertex();
			buffer.pos(0, w, l).tex(u1, v2).color(r, g, b, particleAlpha).endVertex();

			tessellator.draw();

			GlStateManager.popMatrix();
		}

		// Makes the rain go weird
		//GlStateManager.enableLighting();
	}
	
	/** Draws a single box for one segment of the arc, from the point (x1, y1, z1) to the point (x2, y2, z2), with given width and colour. */
	private void drawShearedBox(Tessellator tessellator, double x1, double y1, double z1, double x2, double y2, double z2, float width, float r, float g, float b, float a){

		float u1 = particleTexture.getMinU();
		float u2 = u1 + (particleTexture.getMaxU() - u1) * (float)(z1-z2)/SEGMENT_LENGTH;
		float v1 = particleTexture.getMinV();
		float dv = particleTexture.getMaxV() - v1;
		// width * 8 gives the total 'circumference' of the box
		float v2 = v1 + dv * 0.0625f;
		float v3 = v1 + dv * 0.125f;
		float v4 = v1 + dv * 0.1875f;
		float v5 = v1 + dv * 0.25f;

		BufferBuilder buffer = tessellator.getBuffer();

		buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR);

		buffer.pos(x1-width, y1-width, z1).tex(u1, v1).color(r, g, b, a).endVertex();
		buffer.pos(x2-width, y2-width, z2).tex(u2, v1).color(r, g, b, a).endVertex();
		buffer.pos(x1-width, y1+width, z1).tex(u1, v2).color(r, g, b, a).endVertex();
		buffer.pos(x2-width, y2+width, z2).tex(u2, v2).color(r, g, b, a).endVertex();
		buffer.pos(x1+width, y1+width, z1).tex(u1, v3).color(r, g, b, a).endVertex();
		buffer.pos(x2+width, y2+width, z2).tex(u2, v3).color(r, g, b, a).endVertex();
		buffer.pos(x1+width, y1-width, z1).tex(u1, v4).color(r, g, b, a).endVertex();
		buffer.pos(x2+width, y2-width, z2).tex(u2, v4).color(r, g, b, a).endVertex();
		buffer.pos(x1-width, y1-width, z1).tex(u1, v5).color(r, g, b, a).endVertex();
		buffer.pos(x2-width, y2-width, z2).tex(u2, v5).color(r, g, b, a).endVertex();

		tessellator.draw();
	}

	@SubscribeEvent
	public static void onTextureStitchEvent(TextureStitchEvent.Pre event){

		event.getMap().registerSprite(STEM_TEXTURE);

		for(ResourceLocation texture : LEAF_TEXTURES){
			event.getMap().registerSprite(texture);
		}
	}

}
