package net.minecraft.world.level.material;

import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.Iterator;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.resources.ResourceLocation;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.mojang.datafixers.util.Pair;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.Registry;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.core.Direction;
import net.minecraft.tags.Tag;
import javax.annotation.Nullable;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import java.util.Random;
import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.StateHolder;

public interface FluidState extends StateHolder<FluidState> {
    Fluid getType();
    
    default boolean isSource() {
        return this.getType().isSource(this);
    }
    
    default boolean isEmpty() {
        return this.getType().isEmpty();
    }
    
    default float getHeight(final BlockGetter bjg, final BlockPos fk) {
        return this.getType().getHeight(this, bjg, fk);
    }
    
    default float getOwnHeight() {
        return this.getType().getOwnHeight(this);
    }
    
    default int getAmount() {
        return this.getType().getAmount(this);
    }
    
    default boolean shouldRenderBackwardUpFace(final BlockGetter bjg, final BlockPos fk) {
        for (int integer4 = -1; integer4 <= 1; ++integer4) {
            for (int integer5 = -1; integer5 <= 1; ++integer5) {
                final BlockPos fk2 = fk.offset(integer4, 0, integer5);
                final FluidState coj7 = bjg.getFluidState(fk2);
                if (!coj7.getType().isSame(this.getType()) && !bjg.getBlockState(fk2).isSolidRender(bjg, fk2)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    default void tick(final Level bjw, final BlockPos fk) {
        this.getType().tick(bjw, fk, this);
    }
    
    default void animateTick(final Level bjw, final BlockPos fk, final Random random) {
        this.getType().animateTick(bjw, fk, this, random);
    }
    
    default boolean isRandomlyTicking() {
        return this.getType().isRandomlyTicking();
    }
    
    default void randomTick(final Level bjw, final BlockPos fk, final Random random) {
        this.getType().randomTick(bjw, fk, this, random);
    }
    
    default Vec3 getFlow(final BlockGetter bjg, final BlockPos fk) {
        return this.getType().getFlow(bjg, fk, this);
    }
    
    default BlockState createLegacyBlock() {
        return this.getType().createLegacyBlock(this);
    }
    
    @Nullable
    default ParticleOptions getDripParticle() {
        return this.getType().getDripParticle();
    }
    
    default boolean is(final Tag<Fluid> aaz) {
        return this.getType().is(aaz);
    }
    
    default float getExplosionResistance() {
        return this.getType().getExplosionResistance();
    }
    
    default boolean canBeReplacedWith(final BlockGetter bjg, final BlockPos fk, final Fluid coi, final Direction fp) {
        return this.getType().canBeReplacedWith(this, bjg, fk, coi, fp);
    }
    
    default <T> Dynamic<T> serialize(final DynamicOps<T> dynamicOps, final FluidState coj) {
        final ImmutableMap<Property<?>, Comparable<?>> immutableMap3 = coj.getValues();
        T object4;
        if (immutableMap3.isEmpty()) {
            object4 = (T)dynamicOps.createMap((Map)ImmutableMap.of(dynamicOps.createString("Name"), dynamicOps.createString(Registry.FLUID.getKey(coj.getType()).toString())));
        }
        else {
            object4 = (T)dynamicOps.createMap((Map)ImmutableMap.of(dynamicOps.createString("Name"), dynamicOps.createString(Registry.FLUID.getKey(coj.getType()).toString()), dynamicOps.createString("Properties"), dynamicOps.createMap((Map)immutableMap3.entrySet().stream().map(entry -> Pair.of(dynamicOps.createString(entry.getKey().getName()), dynamicOps.createString(StateHolder.<Comparable>getName((Property<Comparable>)entry.getKey(), entry.getValue())))).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)))));
        }
        return (Dynamic<T>)new Dynamic((DynamicOps)dynamicOps, object4);
    }
    
    default <T> FluidState deserialize(final Dynamic<T> dynamic) {
        final Fluid coi2 = Registry.FLUID.get(new ResourceLocation(dynamic.getElement("Name").<String>flatMap(dynamic.getOps()::getStringValue).orElse("minecraft:empty")));
        final Map<String, String> map3 = (Map<String, String>)dynamic.get("Properties").asMap(dynamic -> dynamic.asString(""), dynamic -> dynamic.asString(""));
        FluidState coj4 = coi2.defaultFluidState();
        final StateDefinition<Fluid, FluidState> byk5 = coi2.getStateDefinition();
        for (final Map.Entry<String, String> entry7 : map3.entrySet()) {
            final String string8 = entry7.getKey();
            final Property<?> bzm9 = byk5.getProperty(string8);
            if (bzm9 != null) {
                coj4 = StateHolder.setValueHelper(coj4, bzm9, string8, dynamic.toString(), entry7.getValue());
            }
        }
        return coj4;
    }
    
    default VoxelShape getShape(final BlockGetter bjg, final BlockPos fk) {
        return this.getType().getShape(this, bjg, fk);
    }
}
