package net.minecraft.client.renderer.block;

import net.minecraft.world.level.material.Fluid;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.block.StainedGlassBlock;
import net.minecraft.util.Mth;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.tags.FluidTags;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;

public class LiquidBlockRenderer {
    private final TextureAtlasSprite[] lavaIcons;
    private final TextureAtlasSprite[] waterIcons;
    private TextureAtlasSprite waterOverlay;
    
    public LiquidBlockRenderer() {
        this.lavaIcons = new TextureAtlasSprite[2];
        this.waterIcons = new TextureAtlasSprite[2];
    }
    
    protected void setupSprites() {
        this.lavaIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.LAVA.defaultBlockState()).getParticleIcon();
        this.lavaIcons[1] = ModelBakery.LAVA_FLOW.sprite();
        this.waterIcons[0] = Minecraft.getInstance().getModelManager().getBlockModelShaper().getBlockModel(Blocks.WATER.defaultBlockState()).getParticleIcon();
        this.waterIcons[1] = ModelBakery.WATER_FLOW.sprite();
        this.waterOverlay = ModelBakery.WATER_OVERLAY.sprite();
    }
    
    private static boolean isNeighborSameFluid(final BlockGetter bjg, final BlockPos fk, final Direction fp, final FluidState coj) {
        final BlockPos fk2 = fk.relative(fp);
        final FluidState coj2 = bjg.getFluidState(fk2);
        return coj2.getType().isSame(coj.getType());
    }
    
    private static boolean isFaceOccluded(final BlockGetter bjg, final BlockPos fk, final Direction fp, final float float4) {
        final BlockPos fk2 = fk.relative(fp);
        final BlockState byj6 = bjg.getBlockState(fk2);
        if (byj6.canOcclude()) {
            final VoxelShape cwf7 = Shapes.box(0.0, 0.0, 0.0, 1.0, float4, 1.0);
            final VoxelShape cwf8 = byj6.getOcclusionShape(bjg, fk2);
            return Shapes.blockOccudes(cwf7, cwf8, fp);
        }
        return false;
    }
    
    public boolean tesselate(final BlockAndTintGetter bje, final BlockPos fk, final VertexConsumer cyo, final FluidState coj) {
        final boolean boolean6 = coj.is(FluidTags.LAVA);
        final TextureAtlasSprite[] arr7 = boolean6 ? this.lavaIcons : this.waterIcons;
        final int integer8 = boolean6 ? 16777215 : BiomeColors.getAverageWaterColor(bje, fk);
        final float float9 = (integer8 >> 16 & 0xFF) / 255.0f;
        final float float10 = (integer8 >> 8 & 0xFF) / 255.0f;
        final float float11 = (integer8 & 0xFF) / 255.0f;
        final boolean boolean7 = !isNeighborSameFluid(bje, fk, Direction.UP, coj);
        final boolean boolean8 = !isNeighborSameFluid(bje, fk, Direction.DOWN, coj) && !isFaceOccluded(bje, fk, Direction.DOWN, 0.8888889f);
        final boolean boolean9 = !isNeighborSameFluid(bje, fk, Direction.NORTH, coj);
        final boolean boolean10 = !isNeighborSameFluid(bje, fk, Direction.SOUTH, coj);
        final boolean boolean11 = !isNeighborSameFluid(bje, fk, Direction.WEST, coj);
        final boolean boolean12 = !isNeighborSameFluid(bje, fk, Direction.EAST, coj);
        if (!boolean7 && !boolean8 && !boolean12 && !boolean11 && !boolean9 && !boolean10) {
            return false;
        }
        boolean boolean13 = false;
        final float float12 = 0.5f;
        final float float13 = 1.0f;
        final float float14 = 0.8f;
        final float float15 = 0.6f;
        float float16 = this.getWaterHeight(bje, fk, coj.getType());
        float float17 = this.getWaterHeight(bje, fk.south(), coj.getType());
        float float18 = this.getWaterHeight(bje, fk.east().south(), coj.getType());
        float float19 = this.getWaterHeight(bje, fk.east(), coj.getType());
        final double double27 = fk.getX() & 0xF;
        final double double28 = fk.getY() & 0xF;
        final double double29 = fk.getZ() & 0xF;
        final float float20 = 0.001f;
        final float float21 = boolean8 ? 0.001f : 0.0f;
        if (boolean7 && !isFaceOccluded(bje, fk, Direction.UP, Math.min(Math.min(float16, float17), Math.min(float18, float19)))) {
            boolean13 = true;
            float16 -= 0.001f;
            float17 -= 0.001f;
            float18 -= 0.001f;
            float19 -= 0.001f;
            final Vec3 cvl43 = coj.getFlow(bje, fk);
            float float22;
            float float23;
            float float24;
            float float25;
            float float26;
            float float27;
            float float28;
            float float29;
            if (cvl43.x == 0.0 && cvl43.z == 0.0) {
                final TextureAtlasSprite eaj44 = arr7[0];
                float22 = eaj44.getU(0.0);
                float23 = eaj44.getV(0.0);
                float24 = float22;
                float25 = eaj44.getV(16.0);
                float26 = eaj44.getU(16.0);
                float27 = float25;
                float28 = float26;
                float29 = float23;
            }
            else {
                final TextureAtlasSprite eaj44 = arr7[1];
                final float float30 = (float)Mth.atan2(cvl43.z, cvl43.x) - 1.5707964f;
                final float float31 = Mth.sin(float30) * 0.25f;
                final float float32 = Mth.cos(float30) * 0.25f;
                final float float33 = 8.0f;
                float22 = eaj44.getU(8.0f + (-float32 - float31) * 16.0f);
                float23 = eaj44.getV(8.0f + (-float32 + float31) * 16.0f);
                float24 = eaj44.getU(8.0f + (-float32 + float31) * 16.0f);
                float25 = eaj44.getV(8.0f + (float32 + float31) * 16.0f);
                float26 = eaj44.getU(8.0f + (float32 + float31) * 16.0f);
                float27 = eaj44.getV(8.0f + (float32 - float31) * 16.0f);
                float28 = eaj44.getU(8.0f + (float32 - float31) * 16.0f);
                float29 = eaj44.getV(8.0f + (-float32 - float31) * 16.0f);
            }
            final float float34 = (float22 + float24 + float26 + float28) / 4.0f;
            final float float30 = (float23 + float25 + float27 + float29) / 4.0f;
            final float float31 = arr7[0].getWidth() / (arr7[0].getU1() - arr7[0].getU0());
            final float float32 = arr7[0].getHeight() / (arr7[0].getV1() - arr7[0].getV0());
            final float float33 = 4.0f / Math.max(float32, float31);
            float22 = Mth.lerp(float33, float22, float34);
            float24 = Mth.lerp(float33, float24, float34);
            float26 = Mth.lerp(float33, float26, float34);
            float28 = Mth.lerp(float33, float28, float34);
            float23 = Mth.lerp(float33, float23, float30);
            float25 = Mth.lerp(float33, float25, float30);
            float27 = Mth.lerp(float33, float27, float30);
            float29 = Mth.lerp(float33, float29, float30);
            final int integer9 = this.getLightColor(bje, fk);
            final float float35 = 1.0f * float9;
            final float float36 = 1.0f * float10;
            final float float37 = 1.0f * float11;
            this.vertex(cyo, double27 + 0.0, double28 + float16, double29 + 0.0, float35, float36, float37, float22, float23, integer9);
            this.vertex(cyo, double27 + 0.0, double28 + float17, double29 + 1.0, float35, float36, float37, float24, float25, integer9);
            this.vertex(cyo, double27 + 1.0, double28 + float18, double29 + 1.0, float35, float36, float37, float26, float27, integer9);
            this.vertex(cyo, double27 + 1.0, double28 + float19, double29 + 0.0, float35, float36, float37, float28, float29, integer9);
            if (coj.shouldRenderBackwardUpFace(bje, fk.above())) {
                this.vertex(cyo, double27 + 0.0, double28 + float16, double29 + 0.0, float35, float36, float37, float22, float23, integer9);
                this.vertex(cyo, double27 + 1.0, double28 + float19, double29 + 0.0, float35, float36, float37, float28, float29, integer9);
                this.vertex(cyo, double27 + 1.0, double28 + float18, double29 + 1.0, float35, float36, float37, float26, float27, integer9);
                this.vertex(cyo, double27 + 0.0, double28 + float17, double29 + 1.0, float35, float36, float37, float24, float25, integer9);
            }
        }
        if (boolean8) {
            final float float22 = arr7[0].getU0();
            final float float24 = arr7[0].getU1();
            final float float26 = arr7[0].getV0();
            final float float28 = arr7[0].getV1();
            final int integer10 = this.getLightColor(bje, fk.below());
            final float float25 = 0.5f * float9;
            final float float27 = 0.5f * float10;
            final float float29 = 0.5f * float11;
            this.vertex(cyo, double27, double28 + float21, double29 + 1.0, float25, float27, float29, float22, float28, integer10);
            this.vertex(cyo, double27, double28 + float21, double29, float25, float27, float29, float22, float26, integer10);
            this.vertex(cyo, double27 + 1.0, double28 + float21, double29, float25, float27, float29, float24, float26, integer10);
            this.vertex(cyo, double27 + 1.0, double28 + float21, double29 + 1.0, float25, float27, float29, float24, float28, integer10);
            boolean13 = true;
        }
        for (int integer11 = 0; integer11 < 4; ++integer11) {
            float float24;
            float float26;
            double double30;
            double double31;
            double double32;
            double double33;
            Direction fp46;
            boolean boolean14;
            if (integer11 == 0) {
                float24 = float16;
                float26 = float19;
                double30 = double27;
                double31 = double27 + 1.0;
                double32 = double29 + 0.0010000000474974513;
                double33 = double29 + 0.0010000000474974513;
                fp46 = Direction.NORTH;
                boolean14 = boolean9;
            }
            else if (integer11 == 1) {
                float24 = float18;
                float26 = float17;
                double30 = double27 + 1.0;
                double31 = double27;
                double32 = double29 + 1.0 - 0.0010000000474974513;
                double33 = double29 + 1.0 - 0.0010000000474974513;
                fp46 = Direction.SOUTH;
                boolean14 = boolean10;
            }
            else if (integer11 == 2) {
                float24 = float17;
                float26 = float16;
                double30 = double27 + 0.0010000000474974513;
                double31 = double27 + 0.0010000000474974513;
                double32 = double29 + 1.0;
                double33 = double29;
                fp46 = Direction.WEST;
                boolean14 = boolean11;
            }
            else {
                float24 = float19;
                float26 = float18;
                double30 = double27 + 1.0 - 0.0010000000474974513;
                double31 = double27 + 1.0 - 0.0010000000474974513;
                double32 = double29;
                double33 = double29 + 1.0;
                fp46 = Direction.EAST;
                boolean14 = boolean12;
            }
            if (boolean14 && !isFaceOccluded(bje, fk, fp46, Math.max(float24, float26))) {
                boolean13 = true;
                final BlockPos fk2 = fk.relative(fp46);
                TextureAtlasSprite eaj45 = arr7[1];
                if (!boolean6) {
                    final Block bph50 = bje.getBlockState(fk2).getBlock();
                    if (bph50 == Blocks.GLASS || bph50 instanceof StainedGlassBlock) {
                        eaj45 = this.waterOverlay;
                    }
                }
                final float float35 = eaj45.getU(0.0);
                final float float36 = eaj45.getU(8.0);
                final float float37 = eaj45.getV((1.0f - float24) * 16.0f * 0.5f);
                final float float38 = eaj45.getV((1.0f - float26) * 16.0f * 0.5f);
                final float float39 = eaj45.getV(8.0);
                final int integer12 = this.getLightColor(bje, fk2);
                final float float40 = (integer11 < 2) ? 0.8f : 0.6f;
                final float float41 = 1.0f * float40 * float9;
                final float float42 = 1.0f * float40 * float10;
                final float float43 = 1.0f * float40 * float11;
                this.vertex(cyo, double30, double28 + float24, double32, float41, float42, float43, float35, float37, integer12);
                this.vertex(cyo, double31, double28 + float26, double33, float41, float42, float43, float36, float38, integer12);
                this.vertex(cyo, double31, double28 + float21, double33, float41, float42, float43, float36, float39, integer12);
                this.vertex(cyo, double30, double28 + float21, double32, float41, float42, float43, float35, float39, integer12);
                if (eaj45 != this.waterOverlay) {
                    this.vertex(cyo, double30, double28 + float21, double32, float41, float42, float43, float35, float39, integer12);
                    this.vertex(cyo, double31, double28 + float21, double33, float41, float42, float43, float36, float39, integer12);
                    this.vertex(cyo, double31, double28 + float26, double33, float41, float42, float43, float36, float38, integer12);
                    this.vertex(cyo, double30, double28 + float24, double32, float41, float42, float43, float35, float37, integer12);
                }
            }
        }
        return boolean13;
    }
    
    private void vertex(final VertexConsumer cyo, final double double2, final double double3, final double double4, final float float5, final float float6, final float float7, final float float8, final float float9, final int integer) {
        cyo.vertex(double2, double3, double4).color(float5, float6, float7, 1.0f).uv(float8, float9).uv2(integer).normal(0.0f, 1.0f, 0.0f).endVertex();
    }
    
    private int getLightColor(final BlockAndTintGetter bje, final BlockPos fk) {
        final int integer4 = LevelRenderer.getLightColor(bje, fk);
        final int integer5 = LevelRenderer.getLightColor(bje, fk.above());
        final int integer6 = integer4 & 0xFF;
        final int integer7 = integer5 & 0xFF;
        final int integer8 = integer4 >> 16 & 0xFF;
        final int integer9 = integer5 >> 16 & 0xFF;
        return ((integer6 > integer7) ? integer6 : integer7) | ((integer8 > integer9) ? integer8 : integer9) << 16;
    }
    
    private float getWaterHeight(final BlockGetter bjg, final BlockPos fk, final Fluid coi) {
        int integer5 = 0;
        float float6 = 0.0f;
        for (int integer6 = 0; integer6 < 4; ++integer6) {
            final BlockPos fk2 = fk.offset(-(integer6 & 0x1), 0, -(integer6 >> 1 & 0x1));
            if (bjg.getFluidState(fk2.above()).getType().isSame(coi)) {
                return 1.0f;
            }
            final FluidState coj9 = bjg.getFluidState(fk2);
            if (coj9.getType().isSame(coi)) {
                final float float7 = coj9.getHeight(bjg, fk2);
                if (float7 >= 0.8f) {
                    float6 += float7 * 10.0f;
                    integer5 += 10;
                }
                else {
                    float6 += float7;
                    ++integer5;
                }
            }
            else if (!bjg.getBlockState(fk2).getMaterial().isSolid()) {
                ++integer5;
            }
        }
        return float6 / integer5;
    }
}
