package net.minecraft.client.renderer.blockentity;

import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import com.mojang.blaze3d.vertex.PoseStack;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.entity.CampfireBlockEntity;
import net.minecraft.world.level.block.entity.BellBlockEntity;
import net.minecraft.world.level.block.entity.ConduitBlockEntity;
import net.minecraft.world.level.block.entity.BedBlockEntity;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.client.model.ShulkerModel;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
import net.minecraft.world.level.block.entity.EnchantmentTableBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import com.google.common.collect.Maps;
import net.minecraft.world.phys.HitResult;
import net.minecraft.client.Camera;
import net.minecraft.world.level.Level;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.gui.Font;
import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.world.level.block.entity.BlockEntityType;
import java.util.Map;

public class BlockEntityRenderDispatcher {
    private final Map<BlockEntityType<?>, BlockEntityRenderer<?>> renderers;
    public static final BlockEntityRenderDispatcher instance;
    private final BufferBuilder singleRenderBuffer;
    private Font font;
    public TextureManager textureManager;
    public Level level;
    public Camera camera;
    public HitResult cameraHitResult;
    
    private BlockEntityRenderDispatcher() {
        this.renderers = Maps.newHashMap();
        this.singleRenderBuffer = new BufferBuilder(256);
        this.<SignBlockEntity>register(BlockEntityType.SIGN, new SignRenderer(this));
        this.<SpawnerBlockEntity>register(BlockEntityType.MOB_SPAWNER, new SpawnerRenderer(this));
        this.<PistonMovingBlockEntity>register(BlockEntityType.PISTON, new PistonHeadRenderer(this));
        this.<BlockEntity>register((BlockEntityType<BlockEntity>)BlockEntityType.CHEST, new ChestRenderer<BlockEntity>(this));
        this.<BlockEntity>register((BlockEntityType<BlockEntity>)BlockEntityType.ENDER_CHEST, new ChestRenderer<BlockEntity>(this));
        this.<BlockEntity>register((BlockEntityType<BlockEntity>)BlockEntityType.TRAPPED_CHEST, new ChestRenderer<BlockEntity>(this));
        this.<EnchantmentTableBlockEntity>register(BlockEntityType.ENCHANTING_TABLE, new EnchantTableRenderer(this));
        this.<LecternBlockEntity>register(BlockEntityType.LECTERN, new LecternRenderer(this));
        this.<BlockEntity>register((BlockEntityType<BlockEntity>)BlockEntityType.END_PORTAL, new TheEndPortalRenderer<BlockEntity>(this));
        this.<TheEndGatewayBlockEntity>register(BlockEntityType.END_GATEWAY, new TheEndGatewayRenderer(this));
        this.<BeaconBlockEntity>register(BlockEntityType.BEACON, new BeaconRenderer(this));
        this.<SkullBlockEntity>register(BlockEntityType.SKULL, new SkullBlockRenderer(this));
        this.<BannerBlockEntity>register(BlockEntityType.BANNER, new BannerRenderer(this));
        this.<StructureBlockEntity>register(BlockEntityType.STRUCTURE_BLOCK, new StructureBlockRenderer(this));
        this.<ShulkerBoxBlockEntity>register(BlockEntityType.SHULKER_BOX, new ShulkerBoxRenderer(new ShulkerModel<>(), this));
        this.<BedBlockEntity>register(BlockEntityType.BED, new BedRenderer(this));
        this.<ConduitBlockEntity>register(BlockEntityType.CONDUIT, new ConduitRenderer(this));
        this.<BellBlockEntity>register(BlockEntityType.BELL, new BellRenderer(this));
        this.<CampfireBlockEntity>register(BlockEntityType.CAMPFIRE, new CampfireRenderer(this));
    }
    
    private <E extends BlockEntity> void register(final BlockEntityType<E> bwm, final BlockEntityRenderer<E> dsr) {
        this.renderers.put(bwm, dsr);
    }
    
    @Nullable
    public <E extends BlockEntity> BlockEntityRenderer<E> getRenderer(final E bwl) {
        return (BlockEntityRenderer<E>)this.renderers.get(bwl.getType());
    }
    
    public void prepare(final Level bjw, final TextureManager eak, final Font dch, final Camera dbb, final HitResult cvi) {
        if (this.level != bjw) {
            this.setLevel(bjw);
        }
        this.textureManager = eak;
        this.camera = dbb;
        this.font = dch;
        this.cameraHitResult = cvi;
    }
    
    public <E extends BlockEntity> void render(final E bwl, final float float2, final PoseStack cyl, final MultiBufferSource dqt) {
        if (bwl.distanceToSqr(this.camera.getPosition().x, this.camera.getPosition().y, this.camera.getPosition().z) >= bwl.getViewDistance()) {
            return;
        }
        final BlockEntityRenderer<E> dsr6 = this.<E>getRenderer(bwl);
        if (dsr6 == null) {
            return;
        }
        if (!bwl.hasLevel() || !bwl.getType().isValid(bwl.getBlockState().getBlock())) {
            return;
        }
        tryRender(bwl, () -> BlockEntityRenderDispatcher.<E>setupAndRender(dsr6, bwl, float2, cyl, dqt));
    }
    
    private static <T extends BlockEntity> void setupAndRender(final BlockEntityRenderer<T> dsr, final T bwl, final float float3, final PoseStack cyl, final MultiBufferSource dqt) {
        final Level bjw7 = bwl.getLevel();
        int integer6;
        if (bjw7 != null) {
            integer6 = LevelRenderer.getLightColor(bjw7, bwl.getBlockPos());
        }
        else {
            integer6 = 15728880;
        }
        dsr.render(bwl, float3, cyl, dqt, integer6, OverlayTexture.NO_OVERLAY);
    }
    
    public <E extends BlockEntity> boolean renderItem(final E bwl, final PoseStack cyl, final MultiBufferSource dqt, final int integer4, final int integer5) {
        final BlockEntityRenderer<E> dsr7 = this.<E>getRenderer(bwl);
        if (dsr7 == null) {
            return true;
        }
        tryRender(bwl, () -> dsr7.render(bwl, 0.0f, cyl, dqt, integer4, integer5));
        return false;
    }
    
    private static void tryRender(final BlockEntity bwl, final Runnable runnable) {
        try {
            runnable.run();
        }
        catch (Throwable throwable3) {
            final CrashReport h4 = CrashReport.forThrowable(throwable3, "Rendering Block Entity");
            final CrashReportCategory i5 = h4.addCategory("Block Entity Details");
            bwl.fillCrashReportCategory(i5);
            throw new ReportedException(h4);
        }
    }
    
    public void setLevel(@Nullable final Level bjw) {
        this.level = bjw;
        if (bjw == null) {
            this.camera = null;
        }
    }
    
    public Font getFont() {
        return this.font;
    }
    
    static {
        instance = new BlockEntityRenderDispatcher();
    }
}
