package net.minecraft.client.renderer.entity;

import com.google.common.collect.Sets;
import net.minecraft.server.packs.resources.ResourceManager;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.player.LocalPlayer;
import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.util.Mth;
import com.mojang.blaze3d.vertex.Tesselator;
import net.minecraft.client.gui.Font;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.client.renderer.texture.OverlayTexture;
import com.mojang.blaze3d.platform.Lighting;
import net.minecraft.client.Minecraft;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.client.renderer.texture.TextureAtlas;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.world.entity.LivingEntity;
import javax.annotation.Nullable;
import net.minecraft.world.level.Level;
import net.minecraft.client.renderer.block.model.BakedQuad;
import java.util.List;
import com.mojang.blaze3d.vertex.VertexMultiConsumer;
import net.minecraft.client.renderer.RenderType;
import java.util.Objects;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.world.item.Items;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.Direction;
import java.util.Random;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.item.ItemStack;
import net.minecraft.client.resources.model.BakedModel;
import java.util.Iterator;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.Registry;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.ItemModelShaper;
import net.minecraft.world.item.Item;
import java.util.Set;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;

public class ItemRenderer implements ResourceManagerReloadListener {
    public static final ResourceLocation ENCHANT_GLINT_LOCATION;
    private static final Set<Item> IGNORED;
    public float blitOffset;
    private final ItemModelShaper itemModelShaper;
    private final TextureManager textureManager;
    private final ItemColors itemColors;
    
    public ItemRenderer(final TextureManager eak, final ModelManager eca, final ItemColors dcf) {
        this.textureManager = eak;
        this.itemModelShaper = new ItemModelShaper(eca);
        for (final Item bei6 : Registry.ITEM) {
            if (!ItemRenderer.IGNORED.contains(bei6)) {
                this.itemModelShaper.register(bei6, new ModelResourceLocation(Registry.ITEM.getKey(bei6), "inventory"));
            }
        }
        this.itemColors = dcf;
    }
    
    public ItemModelShaper getItemModelShaper() {
        return this.itemModelShaper;
    }
    
    private void renderModelLists(final BakedModel ebv, final ItemStack ben, final int integer3, final int integer4, final PoseStack cyl, final VertexConsumer cyo) {
        final Random random8 = new Random();
        final long long9 = 42L;
        for (final Direction fp14 : Direction.values()) {
            random8.setSeed(42L);
            this.renderQuadList(cyl, cyo, ebv.getQuads(null, fp14, random8), ben, integer3, integer4);
        }
        random8.setSeed(42L);
        this.renderQuadList(cyl, cyo, ebv.getQuads(null, null, random8), ben, integer3, integer4);
    }
    
    public void render(final ItemStack ben, final ItemTransforms.TransformType b, final boolean boolean3, final PoseStack cyl, final MultiBufferSource dqt, final int integer6, final int integer7, BakedModel ebv) {
        if (ben.isEmpty()) {
            return;
        }
        cyl.pushPose();
        final boolean boolean4 = b == ItemTransforms.TransformType.GUI;
        final boolean boolean5 = boolean4 || b == ItemTransforms.TransformType.GROUND || b == ItemTransforms.TransformType.FIXED;
        if (ben.getItem() == Items.TRIDENT && boolean5) {
            ebv = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation("minecraft:trident#inventory"));
        }
        ebv.getTransforms().getTransform(b).apply(boolean3, cyl);
        cyl.translate(-0.5, -0.5, -0.5);
        if (ebv.isCustomRenderer() || (ben.getItem() == Items.TRIDENT && !boolean5)) {
            BlockEntityWithoutLevelRenderer.instance.renderByItem(ben, cyl, dqt, integer6, integer7);
        }
        else {
            final RenderType drb12 = ItemBlockRenderTypes.getRenderType(ben);
            RenderType drb13;
            if (boolean4 && Objects.equals(drb12, Sheets.translucentBlockSheet())) {
                drb13 = Sheets.translucentCullBlockSheet();
            }
            else {
                drb13 = drb12;
            }
            final VertexConsumer cyo14 = getFoilBuffer(dqt, drb13, true, ben.hasFoil());
            this.renderModelLists(ebv, ben, integer6, integer7, cyl, cyo14);
        }
        cyl.popPose();
    }
    
    public static VertexConsumer getFoilBuffer(final MultiBufferSource dqt, final RenderType drb, final boolean boolean3, final boolean boolean4) {
        if (boolean4) {
            return VertexMultiConsumer.create(dqt.getBuffer(boolean3 ? RenderType.glint() : RenderType.entityGlint()), dqt.getBuffer(drb));
        }
        return dqt.getBuffer(drb);
    }
    
    private void renderQuadList(final PoseStack cyl, final VertexConsumer cyo, final List<BakedQuad> list, final ItemStack ben, final int integer5, final int integer6) {
        final boolean boolean8 = !ben.isEmpty();
        final PoseStack.Pose a9 = cyl.last();
        for (final BakedQuad drn11 : list) {
            int integer7 = -1;
            if (boolean8 && drn11.isTinted()) {
                integer7 = this.itemColors.getColor(ben, drn11.getTintIndex());
            }
            final float float13 = (integer7 >> 16 & 0xFF) / 255.0f;
            final float float14 = (integer7 >> 8 & 0xFF) / 255.0f;
            final float float15 = (integer7 & 0xFF) / 255.0f;
            cyo.putBulkData(a9, drn11, float13, float14, float15, integer5, integer6);
        }
    }
    
    public BakedModel getModel(final ItemStack ben, @Nullable final Level bjw, @Nullable final LivingEntity akz) {
        final Item bei6 = ben.getItem();
        BakedModel ebv5;
        if (bei6 == Items.TRIDENT) {
            ebv5 = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation("minecraft:trident_in_hand#inventory"));
        }
        else {
            ebv5 = this.itemModelShaper.getItemModel(ben);
        }
        if (!bei6.hasProperties()) {
            return ebv5;
        }
        return this.resolveOverrides(ebv5, ben, bjw, akz);
    }
    
    private BakedModel resolveOverrides(final BakedModel ebv, final ItemStack ben, @Nullable final Level bjw, @Nullable final LivingEntity akz) {
        final BakedModel ebv2 = ebv.getOverrides().resolve(ebv, ben, bjw, akz);
        return (ebv2 == null) ? this.itemModelShaper.getModelManager().getMissingModel() : ebv2;
    }
    
    public void renderStatic(final ItemStack ben, final ItemTransforms.TransformType b, final int integer3, final int integer4, final PoseStack cyl, final MultiBufferSource dqt) {
        this.renderStatic(null, ben, b, false, cyl, dqt, null, integer3, integer4);
    }
    
    public void renderStatic(@Nullable final LivingEntity akz, final ItemStack ben, final ItemTransforms.TransformType b, final boolean boolean4, final PoseStack cyl, final MultiBufferSource dqt, @Nullable final Level bjw, final int integer8, final int integer9) {
        if (ben.isEmpty()) {
            return;
        }
        final BakedModel ebv11 = this.getModel(ben, bjw, akz);
        this.render(ben, b, boolean4, cyl, dqt, integer8, integer9, ebv11);
    }
    
    public void renderGuiItem(final ItemStack ben, final int integer2, final int integer3) {
        this.renderGuiItem(ben, integer2, integer3, this.getModel(ben, null, null));
    }
    
    protected void renderGuiItem(final ItemStack ben, final int integer2, final int integer3, final BakedModel ebv) {
        RenderSystem.pushMatrix();
        this.textureManager.bind(TextureAtlas.LOCATION_BLOCKS);
        this.textureManager.getTexture(TextureAtlas.LOCATION_BLOCKS).setFilter(false, false);
        RenderSystem.enableRescaleNormal();
        RenderSystem.enableAlphaTest();
        RenderSystem.defaultAlphaFunc();
        RenderSystem.enableBlend();
        RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
        RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
        RenderSystem.translatef((float)integer2, (float)integer3, 100.0f + this.blitOffset);
        RenderSystem.translatef(8.0f, 8.0f, 0.0f);
        RenderSystem.scalef(1.0f, -1.0f, 1.0f);
        RenderSystem.scalef(16.0f, 16.0f, 16.0f);
        final PoseStack cyl6 = new PoseStack();
        final MultiBufferSource.BufferSource a7 = Minecraft.getInstance().renderBuffers().bufferSource();
        final boolean boolean8 = !ebv.usesBlockLight();
        if (boolean8) {
            Lighting.setupForFlatItems();
        }
        this.render(ben, ItemTransforms.TransformType.GUI, false, cyl6, a7, 15728880, OverlayTexture.NO_OVERLAY, ebv);
        a7.endBatch();
        RenderSystem.enableDepthTest();
        if (boolean8) {
            Lighting.setupFor3DItems();
        }
        RenderSystem.disableAlphaTest();
        RenderSystem.disableRescaleNormal();
        RenderSystem.popMatrix();
    }
    
    public void renderAndDecorateItem(final ItemStack ben, final int integer2, final int integer3) {
        this.renderAndDecorateItem(Minecraft.getInstance().player, ben, integer2, integer3);
    }
    
    public void renderAndDecorateItem(@Nullable final LivingEntity akz, final ItemStack ben, final int integer3, final int integer4) {
        if (ben.isEmpty()) {
            return;
        }
        this.blitOffset += 50.0f;
        try {
            this.renderGuiItem(ben, integer3, integer4, this.getModel(ben, null, akz));
        }
        catch (Throwable throwable6) {
            final CrashReport h7 = CrashReport.forThrowable(throwable6, "Rendering item");
            final CrashReportCategory i8 = h7.addCategory("Item being rendered");
            i8.setDetail("Item Type", () -> String.valueOf(ben.getItem()));
            i8.setDetail("Item Damage", () -> String.valueOf(ben.getDamageValue()));
            i8.setDetail("Item NBT", () -> String.valueOf(ben.getTag()));
            i8.setDetail("Item Foil", () -> String.valueOf(ben.hasFoil()));
            throw new ReportedException(h7);
        }
        this.blitOffset -= 50.0f;
    }
    
    public void renderGuiItemDecorations(final Font dch, final ItemStack ben, final int integer3, final int integer4) {
        this.renderGuiItemDecorations(dch, ben, integer3, integer4, null);
    }
    
    public void renderGuiItemDecorations(final Font dch, final ItemStack ben, final int integer3, final int integer4, @Nullable final String string) {
        if (ben.isEmpty()) {
            return;
        }
        final PoseStack cyl7 = new PoseStack();
        if (ben.getCount() != 1 || string != null) {
            final String string2 = (string == null) ? String.valueOf(ben.getCount()) : string;
            cyl7.translate(0.0, 0.0, this.blitOffset + 200.0f);
            final MultiBufferSource.BufferSource a9 = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
            dch.drawInBatch(string2, (float)(integer3 + 19 - 2 - dch.width(string2)), (float)(integer4 + 6 + 3), 16777215, true, cyl7.last().pose(), a9, false, 0, 15728880);
            a9.endBatch();
        }
        if (ben.isDamaged()) {
            RenderSystem.disableDepthTest();
            RenderSystem.disableTexture();
            RenderSystem.disableAlphaTest();
            RenderSystem.disableBlend();
            final Tesselator cym8 = Tesselator.getInstance();
            final BufferBuilder cyg9 = cym8.getBuilder();
            final float float10 = (float)ben.getDamageValue();
            final float float11 = (float)ben.getMaxDamage();
            final float float12 = Math.max(0.0f, (float11 - float10) / float11);
            final int integer5 = Math.round(13.0f - float10 * 13.0f / float11);
            final int integer6 = Mth.hsvToRgb(float12 / 3.0f, 1.0f, 1.0f);
            this.fillRect(cyg9, integer3 + 2, integer4 + 13, 13, 2, 0, 0, 0, 255);
            this.fillRect(cyg9, integer3 + 2, integer4 + 13, integer5, 1, integer6 >> 16 & 0xFF, integer6 >> 8 & 0xFF, integer6 & 0xFF, 255);
            RenderSystem.enableBlend();
            RenderSystem.enableAlphaTest();
            RenderSystem.enableTexture();
            RenderSystem.enableDepthTest();
        }
        final LocalPlayer dqb8 = Minecraft.getInstance().player;
        final float float13 = (dqb8 == null) ? 0.0f : dqb8.getCooldowns().getCooldownPercent(ben.getItem(), Minecraft.getInstance().getFrameTime());
        if (float13 > 0.0f) {
            RenderSystem.disableDepthTest();
            RenderSystem.disableTexture();
            RenderSystem.enableBlend();
            RenderSystem.defaultBlendFunc();
            final Tesselator cym9 = Tesselator.getInstance();
            final BufferBuilder cyg10 = cym9.getBuilder();
            this.fillRect(cyg10, integer3, integer4 + Mth.floor(16.0f * (1.0f - float13)), 16, Mth.ceil(16.0f * float13), 255, 255, 255, 127);
            RenderSystem.enableTexture();
            RenderSystem.enableDepthTest();
        }
    }
    
    private void fillRect(final BufferBuilder cyg, final int integer2, final int integer3, final int integer4, final int integer5, final int integer6, final int integer7, final int integer8, final int integer9) {
        cyg.begin(7, DefaultVertexFormat.POSITION_COLOR);
        cyg.vertex(integer2 + 0, integer3 + 0, 0.0).color(integer6, integer7, integer8, integer9).endVertex();
        cyg.vertex(integer2 + 0, integer3 + integer5, 0.0).color(integer6, integer7, integer8, integer9).endVertex();
        cyg.vertex(integer2 + integer4, integer3 + integer5, 0.0).color(integer6, integer7, integer8, integer9).endVertex();
        cyg.vertex(integer2 + integer4, integer3 + 0, 0.0).color(integer6, integer7, integer8, integer9).endVertex();
        Tesselator.getInstance().end();
    }
    
    @Override
    public void onResourceManagerReload(final ResourceManager zb) {
        this.itemModelShaper.rebuildCache();
    }
    
    static {
        ENCHANT_GLINT_LOCATION = new ResourceLocation("textures/misc/enchanted_item_glint.png");
        IGNORED = Sets.<Item>newHashSet(Items.AIR);
    }
}
