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

import com.google.common.collect.Lists;
import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType;
import net.minecraft.resources.ResourceLocation;
import java.util.function.Supplier;
import net.minecraft.core.Registry;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProviderType;
import java.util.Map;
import java.util.stream.Stream;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecorator;
import java.util.List;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;

public class TreeConfiguration implements FeatureConfiguration {
    public final BlockStateProvider trunkProvider;
    public final BlockStateProvider leavesProvider;
    public final List<TreeDecorator> decorators;
    public final int baseHeight;
    public transient boolean fromSapling;
    
    protected TreeConfiguration(final BlockStateProvider chw1, final BlockStateProvider chw2, final List<TreeDecorator> list, final int integer) {
        this.trunkProvider = chw1;
        this.leavesProvider = chw2;
        this.decorators = list;
        this.baseHeight = integer;
    }
    
    public void setFromSapling() {
        this.fromSapling = true;
    }
    
    @Override
    public <T> Dynamic<T> serialize(final DynamicOps<T> dynamicOps) {
        final ImmutableMap.Builder<T, T> builder3 = ImmutableMap.<T, T>builder();
        builder3.put((T)dynamicOps.createString("trunk_provider"), this.trunkProvider.<T>serialize(dynamicOps)).put((T)dynamicOps.createString("leaves_provider"), this.leavesProvider.<T>serialize(dynamicOps)).put((T)dynamicOps.createString("decorators"), (T)dynamicOps.createList((Stream)this.decorators.stream().map(cit -> cit.<T>serialize(dynamicOps)))).put((T)dynamicOps.createString("base_height"), (T)dynamicOps.createInt(this.baseHeight));
        return (Dynamic<T>)new Dynamic((DynamicOps)dynamicOps, dynamicOps.createMap((Map)builder3.build()));
    }
    
    public static <T> TreeConfiguration deserialize(final Dynamic<T> dynamic) {
        final BlockStateProviderType<?> chx2 = Registry.BLOCKSTATE_PROVIDER_TYPES.get(new ResourceLocation(dynamic.get("trunk_provider").get("type").asString().<Throwable>orElseThrow(RuntimeException::new)));
        final BlockStateProviderType<?> chx3 = Registry.BLOCKSTATE_PROVIDER_TYPES.get(new ResourceLocation(dynamic.get("leaves_provider").get("type").asString().<Throwable>orElseThrow(RuntimeException::new)));
        return new TreeConfiguration((BlockStateProvider)chx2.deserialize(dynamic.get("trunk_provider").orElseEmptyMap()), (BlockStateProvider)chx3.deserialize(dynamic.get("leaves_provider").orElseEmptyMap()), dynamic.get("decorators").asList(dynamic -> ((TreeDecoratorType<TreeDecorator>)Registry.TREE_DECORATOR_TYPES.get(new ResourceLocation((String)dynamic.get("type").asString().orElseThrow(RuntimeException::new)))).deserialize(dynamic)), dynamic.get("base_height").asInt(0));
    }
    
    public static class TreeConfigurationBuilder {
        public final BlockStateProvider trunkProvider;
        public final BlockStateProvider leavesProvider;
        private List<TreeDecorator> decorators;
        private int baseHeight;
        
        public TreeConfigurationBuilder(final BlockStateProvider chw1, final BlockStateProvider chw2) {
            this.decorators = Lists.newArrayList();
            this.baseHeight = 0;
            this.trunkProvider = chw1;
            this.leavesProvider = chw2;
        }
        
        public TreeConfigurationBuilder baseHeight(final int integer) {
            this.baseHeight = integer;
            return this;
        }
        
        public TreeConfiguration build() {
            return new TreeConfiguration(this.trunkProvider, this.leavesProvider, this.decorators, this.baseHeight);
        }
    }
}
