package client.renderer.layers;

import java.util.List;

import org.lwjgl.opengl.GL11;

import client.Client;
import client.renderer.GlState;
import client.renderer.entity.RendererLivingEntity;
import client.renderer.model.ModelArmor;
import common.collect.Lists;
import common.enchantment.Enchantment;
import common.enchantment.EnchantmentHelper;
import common.entity.npc.EntityNPC;
import common.entity.types.EntityLiving;
import common.item.ItemStack;
import common.item.material.ItemArmor;
import common.util.Equipment;

public class LayerArmor implements LayerRenderer<EntityNPC>
{
    protected static final String ENCHANTED_ITEM_GLINT_RES = "textures/glint.png";
    private static final Equipment[] SLOTS;
    
    static {
    	List<Equipment> list = Lists.newArrayList();
    	for(Equipment tool : Equipment.values()) {
    		if(tool.isArmor() && tool.isMainArmor() && !tool.isAnimalArmor())
    			list.add(tool);
    	}
    	SLOTS = list.toArray(new Equipment[list.size()]);
    }
    
    protected ModelArmor modelLeggings;
    protected ModelArmor modelArmor;
    private final RendererLivingEntity<?> renderer;
    private float alpha = 1.0F;
    private float colorR = 1.0F;
    private float colorG = 1.0F;
    private float colorB = 1.0F;
//    private boolean skipRenderGlint;
//    private static final Map<String, String> ARMOR_TEXTURE_RES_MAP = Maps.<String, String>newHashMap();

    public LayerArmor(RendererLivingEntity<?> rendererIn, int arms, int legs)
    {
        this.renderer = rendererIn;
//        this.initArmor();
        this.modelLeggings = new ModelArmor(0.5F, arms, legs);
        this.modelArmor = new ModelArmor(1.0F, arms, legs);
    }

    public void doRenderLayer(EntityNPC entity, float limbSwing, float limbSwingAmount, float partial, float yaw, float pitch, float factor, float scale)
    {
    	for(Equipment tool : SLOTS) {
    		this.renderLayer(entity, limbSwing, limbSwingAmount, partial, yaw, pitch, factor, scale, tool);
    	}
    }

    public boolean shouldCombineTextures()
    {
        return false;
    }

    private void renderLayer(EntityNPC entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partial, float yaw, float pitch, float factor, float scale, Equipment slot)
    {
        ItemStack itemstack = this.getCurrentArmor(entitylivingbaseIn, slot);

        if (itemstack != null && itemstack.getItem() instanceof ItemArmor itemarmor && (this.renderer == null || EnchantmentHelper.getEnchantmentLevel(Enchantment.VANITY, itemstack) <= 0))
        {
            ModelArmor t = this.getArmorModel(slot);
            t.setModelAttributes(this.renderer != null ? this.renderer.getMainModel() : null);
            t.setLivingAnimations(entitylivingbaseIn, limbSwing, limbSwingAmount, partial);
            this.setModelPartVisible(t, slot);
            boolean flag = this.isSlotForLeggings(slot);
            String tex = this.getArmorResource(itemarmor, flag, null);
            if(this.renderer != null)
            	this.renderer.bindTexture(tex);
            else
            	Client.CLIENT.getTextureManager().bindTexture(tex);
            if (itemarmor.canBeDyed())
            {
                int i = itemstack.getDyeColor();
                float f = (float)(i >> 16 & 255) / 255.0F;
                float f1 = (float)(i >> 8 & 255) / 255.0F;
                float f2 = (float)(i & 255) / 255.0F;
                GlState.color(this.colorR * f, this.colorG * f1, this.colorB * f2, this.alpha);
                t.render(entitylivingbaseIn, limbSwing, limbSwingAmount, yaw, pitch, factor, scale);
                String overlay = this.getArmorResource(itemarmor, flag, "overlay");
                if(this.renderer != null)
                	this.renderer.bindTexture(overlay);
                else
                	Client.CLIENT.getTextureManager().bindTexture(overlay);
            }
            GlState.color(this.colorR, this.colorG, this.colorB, this.alpha);
            t.render(entitylivingbaseIn, limbSwing, limbSwingAmount, yaw, pitch, factor, scale);
            if (itemstack.isItemEnchanted())
                this.renderGlint(entitylivingbaseIn, t, limbSwing, limbSwingAmount, partial, yaw, pitch, factor, scale);
        }
    }

    public ItemStack getCurrentArmor(EntityNPC entitylivingbaseIn, Equipment armorSlot)
    {
        return entitylivingbaseIn.getArmor(armorSlot);
    }

    public ModelArmor getArmorModel(Equipment armorSlot)
    {
        return this.isSlotForLeggings(armorSlot) ? this.modelLeggings : this.modelArmor;
    }

    private boolean isSlotForLeggings(Equipment armorSlot)
    {
        return armorSlot == Equipment.LEGGINGS;
    }

    private void renderGlint(EntityLiving entitylivingbaseIn, ModelArmor modelbaseIn, float p_177183_3_, float p_177183_4_, float partialTicks, float p_177183_6_, float p_177183_7_, float p_177183_8_, float scale)
    {
        float f = entitylivingbaseIn == null ? (float)(System.currentTimeMillis() % 1000000L) / 50.0f : (float)entitylivingbaseIn.ticksExisted + partialTicks;
        if(this.renderer != null)
        	this.renderer.bindTexture(ENCHANTED_ITEM_GLINT_RES);
        else
        	Client.CLIENT.getTextureManager().bindTexture(ENCHANTED_ITEM_GLINT_RES);
        GlState.enableBlend();
        GlState.depthFunc(GL11.GL_EQUAL);
        GlState.depthMask(false);
        float f1 = 0.5F;
        GlState.color(f1, f1, f1, 1.0F);

        for (int i = 0; i < 2; ++i)
        {
            GlState.disableLighting();
            GlState.blendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
            float f2 = 0.76F;
            GlState.color(0.5F * f2, 0.25F * f2, 0.8F * f2, 1.0F);
            GL11.glMatrixMode(GL11.GL_TEXTURE);
            GL11.glLoadIdentity();
            float f3 = 0.33333334F;
            GL11.glScalef(f3, f3, f3);
            GL11.glRotatef(30.0F - (float)i * 60.0F, 0.0F, 0.0F, 1.0F);
            GL11.glTranslatef(0.0F, f * (0.001F + (float)i * 0.003F) * 20.0F, 0.0F);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);
            modelbaseIn.render(entitylivingbaseIn, p_177183_3_, p_177183_4_, p_177183_6_, p_177183_7_, p_177183_8_, scale);
        }

        GL11.glMatrixMode(GL11.GL_TEXTURE);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GlState.enableLighting();
        GlState.depthMask(true);
        GlState.depthFunc(GL11.GL_LEQUAL);
        GlState.disableBlend();
    }

//    private String getArmorResource(ItemArmor item, boolean legs)
//    {
//        return this.getArmorResource(item, legs, null);
//    }

    private String getArmorResource(ItemArmor item, boolean legs, String layer)
    {
        return String.format("textures/armor/%s_layer_%d%s.png", item.getArmorTexture(), legs ? 2 : 1, 
        		layer == null ? "" : ("_" + layer));
//        ResourceLocation resourcelocation = (ResourceLocation)ARMOR_TEXTURE_RES_MAP.get(s);
//
//        if (resourcelocation == null)
//        {
//            resourcelocation = new ResourceLocation(s);
//            ARMOR_TEXTURE_RES_MAP.put(s, resourcelocation);
//        }
//
//        return s;
    }

//    protected abstract void initArmor();

//    protected abstract void setModelPartVisible(T model, int armorSlot);

//    protected void initArmor()
//    {
//        this.modelLeggings = new ModelBiped(0.5F);
//        this.modelArmor = new ModelBiped(1.0F);
//    }

    protected void setModelPartVisible(ModelArmor model, Equipment slot)
    {
    	model.setVisible(false);

        switch (slot)
        {
            case BOOTS:
                model.bipedRightLeg.showModel = true;
                model.bipedLeftLeg.showModel = true;
                break;

            case LEGGINGS:
                model.bipedBody.showModel = true;
                model.bipedRightLeg.showModel = true;
                model.bipedLeftLeg.showModel = true;
                break;

            case CHESTPLATE:
                model.bipedBody.showModel = true;
                model.bipedRightArm.showModel = true;
                model.bipedLeftArm.showModel = true;
                break;

            case HELMET:
                model.bipedHead.showModel = true;
                model.bipedHeadwear.showModel = true;
                break;
        }
    }

//    protected void setModelVisible(ModelBiped model)
//    {
//        model.setVisible(false);
//    }
}
