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

import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import java.util.stream.Stream;
import com.mojang.datafixers.types.DynamicOps;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.LevelAccessor;
import java.util.Iterator;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import java.util.Random;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.util.Deserializer;
import net.minecraft.core.Registry;
import com.mojang.datafixers.Dynamic;
import java.util.List;

public class ListPoolElement extends StructurePoolElement {
    private final List<StructurePoolElement> elements;
    
    @Deprecated
    public ListPoolElement(final List<StructurePoolElement> list) {
        this(list, StructureTemplatePool.Projection.RIGID);
    }
    
    public ListPoolElement(final List<StructurePoolElement> list, final StructureTemplatePool.Projection a) {
        super(a);
        if (list.isEmpty()) {
            throw new IllegalArgumentException("Elements are empty");
        }
        this.elements = list;
        this.setProjectionOnEachElement(a);
    }
    
    public ListPoolElement(final Dynamic<?> dynamic) {
        super(dynamic);
        final List<StructurePoolElement> list3 = (List<StructurePoolElement>)dynamic.get("elements").asList(dynamic -> Deserializer.<Object, EmptyPoolElement, StructurePoolElementType>deserialize(dynamic, Registry.STRUCTURE_POOL_ELEMENT, "element_type", EmptyPoolElement.INSTANCE));
        if (list3.isEmpty()) {
            throw new IllegalArgumentException("Elements are empty");
        }
        this.elements = list3;
    }
    
    @Override
    public List<StructureTemplate.StructureBlockInfo> getShuffledJigsawBlocks(final StructureManager cmo, final BlockPos fk, final Rotation btu, final Random random) {
        return this.elements.get(0).getShuffledJigsawBlocks(cmo, fk, btu, random);
    }
    
    @Override
    public BoundingBox getBoundingBox(final StructureManager cmo, final BlockPos fk, final Rotation btu) {
        final BoundingBox clb5 = BoundingBox.getUnknownBox();
        for (final StructurePoolElement cik7 : this.elements) {
            final BoundingBox clb6 = cik7.getBoundingBox(cmo, fk, btu);
            clb5.expand(clb6);
        }
        return clb5;
    }
    
    @Override
    public boolean place(final StructureManager cmo, final LevelAccessor bjx, final ChunkGenerator<?> caa, final BlockPos fk, final Rotation btu, final BoundingBox clb, final Random random) {
        for (final StructurePoolElement cik10 : this.elements) {
            if (!cik10.place(cmo, bjx, caa, fk, btu, clb, random)) {
                return false;
            }
        }
        return true;
    }
    
    @Override
    public StructurePoolElementType getType() {
        return StructurePoolElementType.LIST;
    }
    
    @Override
    public StructurePoolElement setProjection(final StructureTemplatePool.Projection a) {
        super.setProjection(a);
        this.setProjectionOnEachElement(a);
        return this;
    }
    
    public <T> Dynamic<T> getDynamic(final DynamicOps<T> dynamicOps) {
        final T object3 = (T)dynamicOps.createList((Stream)this.elements.stream().map(cik -> cik.<T>serialize(dynamicOps).getValue()));
        return (Dynamic<T>)new Dynamic((DynamicOps)dynamicOps, dynamicOps.createMap((Map)ImmutableMap.<Object, T>of(dynamicOps.createString("elements"), object3)));
    }
    
    @Override
    public String toString() {
        return "List[" + this.elements.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]";
    }
    
    private void setProjectionOnEachElement(final StructureTemplatePool.Projection a) {
        this.elements.forEach(cik -> cik.setProjection(a));
    }
}
