package net.minecraft.world.level.levelgen.feature.foliageplacers;

import com.mojang.datafixers.Dynamic;
import java.util.Map;
import net.minecraft.core.Registry;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.world.level.LevelSimulatedReader;
import net.minecraft.world.level.levelgen.feature.AbstractTreeFeature;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.feature.configurations.SmallTreeConfiguration;
import java.util.Random;
import net.minecraft.world.level.LevelSimulatedRW;
import net.minecraft.util.Serializable;

public abstract class FoliagePlacer implements Serializable {
    protected final int radius;
    protected final int radiusRandom;
    protected final FoliagePlacerType<?> type;
    
    public FoliagePlacer(final int integer1, final int integer2, final FoliagePlacerType<?> chr) {
        this.radius = integer1;
        this.radiusRandom = integer2;
        this.type = chr;
    }
    
    public abstract void createFoliage(final LevelSimulatedRW bkb, final Random random, final SmallTreeConfiguration chi, final int integer4, final int integer5, final int integer6, final BlockPos fk, final Set<BlockPos> set);
    
    public abstract int foliageRadius(final Random random, final int integer2, final int integer3, final SmallTreeConfiguration chi);
    
    protected abstract boolean shouldSkipLocation(final Random random, final int integer2, final int integer3, final int integer4, final int integer5, final int integer6);
    
    public abstract int getTreeRadiusForHeight(final int integer1, final int integer2, final int integer3, final int integer4);
    
    protected void placeLeavesRow(final LevelSimulatedRW bkb, final Random random, final SmallTreeConfiguration chi, final int integer4, final BlockPos fk, final int integer6, final int integer7, final Set<BlockPos> set) {
        final BlockPos.MutableBlockPos a10 = new BlockPos.MutableBlockPos();
        for (int integer8 = -integer7; integer8 <= integer7; ++integer8) {
            for (int integer9 = -integer7; integer9 <= integer7; ++integer9) {
                if (!this.shouldSkipLocation(random, integer4, integer8, integer6, integer9, integer7)) {
                    a10.set(integer8 + fk.getX(), integer6 + fk.getY(), integer9 + fk.getZ());
                    this.placeLeaf(bkb, random, a10, chi, set);
                }
            }
        }
    }
    
    protected void placeLeaf(final LevelSimulatedRW bkb, final Random random, final BlockPos fk, final SmallTreeConfiguration chi, final Set<BlockPos> set) {
        if (AbstractTreeFeature.isAirOrLeaves(bkb, fk) || AbstractTreeFeature.isReplaceablePlant(bkb, fk) || AbstractTreeFeature.isBlockWater(bkb, fk)) {
            bkb.setBlock(fk, chi.leavesProvider.getState(random, fk), 19);
            set.add(fk.immutable());
        }
    }
    
    @Override
    public <T> T serialize(final DynamicOps<T> dynamicOps) {
        final ImmutableMap.Builder<T, T> builder3 = ImmutableMap.<T, T>builder();
        builder3.put((T)dynamicOps.createString("type"), (T)dynamicOps.createString(Registry.FOLIAGE_PLACER_TYPES.getKey(this.type).toString())).put((T)dynamicOps.createString("radius"), (T)dynamicOps.createInt(this.radius)).put((T)dynamicOps.createString("radius_random"), (T)dynamicOps.createInt(this.radiusRandom));
        return (T)new Dynamic((DynamicOps)dynamicOps, dynamicOps.createMap((Map)builder3.build())).getValue();
    }
}
