package thebetweenlands.client.render.entity;

import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import thebetweenlands.client.render.model.entity.ModelJellyfish;
import thebetweenlands.client.render.shader.LightSource;
import thebetweenlands.client.render.shader.ShaderHelper;
import thebetweenlands.common.entity.mobs.EntityJellyfish;
import thebetweenlands.util.LightingUtil;

@SideOnly(Side.CLIENT)
public class RenderJellyfish<T extends EntityJellyfish> extends RenderLiving<T> {
	private static final ResourceLocation[] TEXTURE = new ResourceLocation[] {
			new ResourceLocation("thebetweenlands:textures/entity/jellyfish_1.png"),
			new ResourceLocation("thebetweenlands:textures/entity/jellyfish_2.png"),
			new ResourceLocation("thebetweenlands:textures/entity/jellyfish_3.png"),
			new ResourceLocation("thebetweenlands:textures/entity/jellyfish_4.png"),
			new ResourceLocation("thebetweenlands:textures/entity/jellyfish_5.png")
	};

	private static final float[][] GLOW_COLORS = {
			{238 / 255.0f, 173 / 255.0f, 114 / 255.0f},
			{180 / 255.0f, 42 / 255.0f, 42 / 255.0f},
			{224 / 255.0f, 83 / 255.0f, 108 / 255.0f},
			{90 / 255.0f, 170 / 255.0f, 145 / 255.0f},
			{215 / 255.0f, 176 / 255.0f, 195 / 255.0f},
	};

	private static final ModelJellyfish MODEL = new ModelJellyfish();

	public RenderJellyfish(RenderManager manager) {
		super(manager, MODEL, 0.5F);
	}
	
	public RenderJellyfish(RenderManager manager, ModelBase model) {
		super(manager, model, 0.5F);
	}

	@Override
	protected ResourceLocation getEntityTexture(EntityJellyfish entity) {
		return TEXTURE[entity.getJellyfishColour()];
	}

	@Override
	public void doRender(T jellofooosh, double x, double y, double z, float entityYaw, float partialTicks) {
		super.doRender(jellofooosh, x, y + jellofooosh.height * 0.5f, z, entityYaw, partialTicks);

		this.addLighting(jellofooosh, partialTicks);
	}

	protected void addLighting(T jellofooosh, float partialTicks) {
		if (ShaderHelper.INSTANCE.isWorldShaderActive()) {
			double interpX = jellofooosh.lastTickPosX + (jellofooosh.posX - jellofooosh.lastTickPosX) * partialTicks;
			double interpY = jellofooosh.lastTickPosY + (jellofooosh.posY - jellofooosh.lastTickPosY) * partialTicks;
			double interpZ = jellofooosh.lastTickPosZ + (jellofooosh.posZ - jellofooosh.lastTickPosZ) * partialTicks;

			float str = 5.0f * jellofooosh.getJellyfishSize();

			float[] colors = GLOW_COLORS[jellofooosh.getJellyfishColour()];

			ShaderHelper.INSTANCE.require();
			ShaderHelper.INSTANCE.getWorldShader().addLight(new LightSource(interpX, interpY, interpZ, 3.0f, str * colors[0], str * colors[1], str * colors[2]));
		}
	}

	@Override
	public float prepareScale(T jellofooosh, float partialTicks) {
		float scale = jellofooosh.getJellyfishSize();

		GlStateManager.scale(scale, scale * jellofooosh.getJellyfishLength(), scale);

		float limbSwingAmount = jellofooosh.prevLimbSwingAmount + (jellofooosh.limbSwingAmount - jellofooosh.prevLimbSwingAmount) * partialTicks;
		float limbSwing = jellofooosh.limbSwing - jellofooosh.limbSwingAmount * (1.0F - partialTicks);

		GlStateManager.scale(
				1.0f + MathHelper.sin(limbSwing) * Math.min(limbSwingAmount, 0.2f) * 2.0f,
				1.0f - MathHelper.sin(limbSwing) * Math.min(limbSwingAmount, 0.2f),
				1.0f + MathHelper.sin(limbSwing) * Math.min(limbSwingAmount, 0.2f) * 2.0f
				);

		return super.prepareScale(jellofooosh, partialTicks);
	}

	@Override
	protected void renderModel(T jellofooosh, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor) {
		GlStateManager.enableBlend();
		GlStateManager.enableAlpha();
		GlStateManager.color(1F, 1F, 1F, 1F);
		GlStateManager.enableCull();

		LightingUtil.INSTANCE.setLighting(255);

		GlStateManager.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
		GlStateManager.depthMask(false);
		Minecraft.getMinecraft().entityRenderer.setupFogColor(true);

		super.renderModel(jellofooosh, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor);

		Minecraft.getMinecraft().entityRenderer.setupFogColor(false);
		GlStateManager.depthMask(true);
		GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);

		super.renderModel(jellofooosh, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor);

		LightingUtil.INSTANCE.revert();

		GlStateManager.disableCull();
		GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
		GlStateManager.disableBlend();
	}

	protected static double interpolate(double prev, double now, double partialTicks) {
		return prev + (now - prev) * partialTicks;
	}

	@Override
	protected void applyRotations(T jellofooosh, float ageInTicks, float rotationYaw, float partialTicks) {
		Vec3d weightPos = jellofooosh.getOrientationPos(partialTicks);

		double dx = interpolate(jellofooosh.lastTickPosX, jellofooosh.posX, partialTicks) - weightPos.x;
		double dy = interpolate(jellofooosh.lastTickPosY, jellofooosh.posY, partialTicks) - weightPos.y;
		double dz = interpolate(jellofooosh.lastTickPosZ, jellofooosh.posZ, partialTicks) - weightPos.z;

		float yaw = -(float)Math.toDegrees(MathHelper.atan2(dz, dx));
		float pitch = (float)Math.toDegrees(MathHelper.atan2(Math.sqrt(dx * dx + dz * dz), -dy)) - 180;

		GlStateManager.rotate(yaw, 0, 1, 0);
		GlStateManager.rotate(pitch, 0, 0, 1);
		GlStateManager.rotate(-yaw, 0, 1, 0);
	}
}
