package client.renderer.entity;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;

import client.renderer.DefaultVertexFormats;
import client.renderer.Frustum;
import client.renderer.GlState;
import client.renderer.RenderBuffer;
import client.renderer.Tessellator;
import client.renderer.model.ModelBase;
import common.entity.Entity;
import common.entity.item.EntityLeashKnot;
import common.entity.types.EntityLiving;

public abstract class RenderLiving<T extends EntityLiving> extends RendererLivingEntity<T> {
	public RenderLiving(RenderManager manager, ModelBase model) {
		super(manager, model);
	}

//	protected boolean canRenderName(T entity) {
//		return super.canRenderName(entity)
//				&& (entity.getAlwaysRenderNameTagForRender() || entity.hasCustomName() && entity == this.renderManager.pointedEntity);
//	}

	public boolean shouldRender(T entity, double camX, double camY, double camZ) {
		if(super.shouldRender(entity, camX, camY, camZ)) {
			return true;
		}
		else if(entity.getLeashed() && entity.getLeashedTo() != null) {
			Entity holder = entity.getLeashedTo();
			return Frustum.isInFrustum(holder.getEntityBoundingBox());
		}
		else {
			return false;
		}
	}

	public void doRender(T entity, double x, double y, double z, float partial) {
    	if(entity.isBoss())
    		this.manager.gm.setBossStatus(entity);
		super.doRender(entity, x, y, z, partial);
		this.renderLeash(entity, x, y, z, partial);
	}

	public void setLightmap(T entity, float partial) {
		int l = RenderManager.getBrightnessForRender(entity);
		int a = l % 65536;
		int b = l / 65536;
		GL13.glMultiTexCoord2f(GL13.GL_TEXTURE1, (float)a / 1.0F, (float)b / 1.0F);
	}

	private static double interpolateValue(double start, double end, double pct) {
		return start + (end - start) * pct;
	}

    protected void renderLeash(T leashed, double x, double y, double z, float partial) {
        Entity holder = leashed.getLeashedTo();
        if(holder == null)
        	return;
    	int color = leashed.getLeashColor();
    	float r = ((float)((color >> 16) & 0xff)) / 255.0f;
        float g = ((float)((color >> 8) & 0xff)) / 255.0f;
        float b = ((float)(color & 0xff)) / 255.0f;
        y = y - (1.6D - (double)leashed.height) * 0.5D;
//        y = y - (1.6D - leashed.getNeckHeight()) * 0.5d;
//        Tessellator tessellator = Tessellator.getInstance();
        RenderBuffer renderer = Tessellator.getBuffer();
        double hYaw = interpolateValue((double)holder.prevYaw, (double)holder.rotYaw, (double)(partial * 0.5F)) * 0.01745329238474369D;
        double hPitch = interpolateValue((double)holder.prevPitch, (double)holder.rotPitch, (double)(partial * 0.5F)) * 0.01745329238474369D;
        double off1 = Math.cos(hYaw);
        double off2 = Math.sin(hYaw);
        double offP = Math.sin(hPitch);
        if(holder instanceof EntityLeashKnot) {
            off1 = 0.0D;
            off2 = 0.0D;
            offP = -1.0D;
        }
        double offR = Math.cos(hPitch);
        double hx = interpolateValue(holder.prevX, holder.posX, (double)partial) - off1 * 0.7D - off2 * 0.5D * offR;
        double hy = interpolateValue(holder.prevY + (double)holder.getEyeHeight() * 0.7D, 
        		holder.posY + (double)holder.getEyeHeight() * 0.7D, (double)partial) - offP * 0.5D - 0.25D;
        double hz = interpolateValue(holder.prevZ, holder.posZ, (double)partial) - off2 * 0.7D + off1 * 0.5D * offR;
        double lYaw = interpolateValue((double)leashed.prevYawOffset, (double)leashed.yawOffset, (double)partial) * 0.01745329238474369D + (Math.PI / 2D);
        off1 = Math.cos(lYaw) * (double)leashed.width * 0.4D;
        off2 = Math.sin(lYaw) * (double)leashed.width * 0.4D;
        double lx = interpolateValue(leashed.prevX, leashed.posX, (double)partial) + off1;
        double ly = interpolateValue(leashed.prevY, leashed.posY, (double)partial); // +
        		// (1.6D - (double)leashed.height) * 0.5D;
        double lz = interpolateValue(leashed.prevZ, leashed.posZ, (double)partial) + off2;
        x = x + off1;
        z = z + off2;
        double dx = (double)((float)(hx - lx));
        double dy = (double)((float)(hy - ly));
        double dz = (double)((float)(hz - lz));
        GlState.disableTexture2D();
        GlState.disableLighting();
        GlState.disableCull();
        renderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
        for(int n = 0; n <= 24; ++n) {
            float cr = r;
            float cg = g;
            float cb = b;
            if(n % 2 == 0) {
                cr *= 0.7F;
                cg *= 0.7F;
                cb *= 0.7F;
            }
            float off = (float)n / 24.0F;
            renderer.pos(
            		x + dx * (double)off + 0.0D, 
            		y + dy * (double)(off * off + off) * 0.5D + (double)((24.0F - (float)n) / 18.0F + 0.125F), 
            		z + dz * (double)off
            ).color(cr, cg, cb, 1.0F).endVertex();
            renderer.pos(
            		x + dx * (double)off + 0.025D, 
            		y + dy * (double)(off * off + off) * 0.5D + (double)((24.0F - (float)n) / 18.0F + 0.125F) + 0.025D, 
            		z + dz * (double)off
            ).color(cr, cg, cb, 1.0F).endVertex();
        }
        Tessellator.draw();
        renderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
        for(int n = 0; n <= 24; ++n) {
            float cr = r;
            float cg = g;
            float cb = b;
            if(n % 2 == 0) {
                cr *= 0.7F;
                cg *= 0.7F;
                cb *= 0.7F;
            }
            float off = (float)n / 24.0F;
            renderer.pos(
            		x + dx * (double)off + 0.0D, 
            		y + dy * (double)(off * off + off) * 0.5D + (double)((24.0F - (float)n) / 18.0F + 0.125F) + 0.025D, 
            		z + dz * (double)off
            ).color(cr, cg, cb, 1.0F).endVertex();
            renderer.pos(
            		x + dx * (double)off + 0.025D, 
            		y + dy * (double)(off * off + off) * 0.5D + (double)((24.0F - (float)n) / 18.0F + 0.125F), 
            		z + dz * (double)off + 0.025D
            ).color(cr, cg, cb, 1.0F).endVertex();
        }
        Tessellator.draw();
        GlState.enableLighting();
        GlState.enableTexture2D();
        GlState.enableCull();
    }
}
