package net.minecraft.world.level.block.entity;

import net.minecraft.world.level.levelgen.feature.StructurePieceType;
import java.util.Arrays;
import java.util.Optional;
import net.minecraft.util.StringRepresentable;
import java.util.Iterator;
import net.minecraft.world.level.levelgen.feature.structures.StructurePoolElement;
import java.util.Random;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
import net.minecraft.world.level.levelgen.feature.structures.JigsawPlacement;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
import java.util.List;
import net.minecraft.world.level.levelgen.feature.structures.SinglePoolElement;
import net.minecraft.world.level.levelgen.feature.structures.StructureTemplatePool;
import com.google.common.collect.ImmutableList;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import com.google.common.collect.Lists;
import net.minecraft.server.level.ServerLevel;
import javax.annotation.Nullable;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.level.block.JigsawBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;

public class JigsawBlockEntity extends BlockEntity {
    private ResourceLocation name;
    private ResourceLocation target;
    private ResourceLocation pool;
    private JointType joint;
    private String finalState;
    
    public JigsawBlockEntity(final BlockEntityType<?> cdm) {
        super(cdm);
        this.name = new ResourceLocation("empty");
        this.target = new ResourceLocation("empty");
        this.pool = new ResourceLocation("empty");
        this.joint = JointType.ROLLABLE;
        this.finalState = "minecraft:air";
    }
    
    public JigsawBlockEntity() {
        this(BlockEntityType.JIGSAW);
    }
    
    public ResourceLocation getName() {
        return this.name;
    }
    
    public ResourceLocation getTarget() {
        return this.target;
    }
    
    public ResourceLocation getPool() {
        return this.pool;
    }
    
    public String getFinalState() {
        return this.finalState;
    }
    
    public JointType getJoint() {
        return this.joint;
    }
    
    public void setName(final ResourceLocation uh) {
        this.name = uh;
    }
    
    public void setTarget(final ResourceLocation uh) {
        this.target = uh;
    }
    
    public void setPool(final ResourceLocation uh) {
        this.pool = uh;
    }
    
    public void setFinalState(final String string) {
        this.finalState = string;
    }
    
    public void setJoint(final JointType a) {
        this.joint = a;
    }
    
    @Override
    public CompoundTag save(final CompoundTag le) {
        super.save(le);
        le.putString("name", this.name.toString());
        le.putString("target", this.target.toString());
        le.putString("pool", this.pool.toString());
        le.putString("final_state", this.finalState);
        le.putString("joint", this.joint.getSerializedName());
        return le;
    }
    
    @Override
    public void load(final BlockState cfj, final CompoundTag le) {
        super.load(cfj, le);
        this.name = new ResourceLocation(le.getString("name"));
        this.target = new ResourceLocation(le.getString("target"));
        this.pool = new ResourceLocation(le.getString("pool"));
        this.finalState = le.getString("final_state");
        this.joint = JointType.byName(le.getString("joint")).orElseGet(() -> JigsawBlock.getFrontFacing(cfj).getAxis().isHorizontal() ? JointType.ALIGNED : JointType.ROLLABLE);
    }
    
    @Nullable
    @Override
    public ClientboundBlockEntityDataPacket getUpdatePacket() {
        return new ClientboundBlockEntityDataPacket(this.worldPosition, 12, this.getUpdateTag());
    }
    
    @Override
    public CompoundTag getUpdateTag() {
        return this.save(new CompoundTag());
    }
    
    public void generate(final ServerLevel zd, final int integer, final boolean boolean3) {
        final ChunkGenerator cha5 = zd.getChunkSource().getGenerator();
        final StructureManager cva6 = zd.getStructureManager();
        final StructureFeatureManager bqq7 = zd.structureFeatureManager();
        final Random random8 = zd.getRandom();
        final BlockPos fu9 = this.getBlockPos();
        final List<PoolElementStructurePiece> list10 = Lists.newArrayList();
        final StructureTemplate cve11 = new StructureTemplate();
        cve11.fillFromWorld(zd, fu9, new BlockPos(1, 1, 1), false, null);
        final StructurePoolElement cqd12 = new SinglePoolElement(cve11, ImmutableList.of(), StructureTemplatePool.Projection.RIGID);
        final RuntimePiece b13 = new RuntimePiece(cva6, cqd12, fu9, 1, Rotation.NONE, new BoundingBox(fu9, fu9));
        JigsawPlacement.addPieces(b13, integer, RuntimePiece::new, cha5, cva6, list10, random8);
        for (final PoolElementStructurePiece cts15 : list10) {
            cts15.place(zd, bqq7, cha5, random8, BoundingBox.infinite(), fu9, boolean3);
        }
    }
    
    public enum JointType implements StringRepresentable {
        ROLLABLE("rollable"), 
        ALIGNED("aligned");
        
        private final String name;
        
        private JointType(final String string3) {
            this.name = string3;
        }
        
        @Override
        public String getSerializedName() {
            return this.name;
        }
        
        public static Optional<JointType> byName(final String string) {
            return Arrays.<JointType>stream(values()).filter(a -> a.getSerializedName().equals(string)).findFirst();
        }
    }
    
    public static final class RuntimePiece extends PoolElementStructurePiece {
        public RuntimePiece(final StructureManager cva, final StructurePoolElement cqd, final BlockPos fu, final int integer, final Rotation cap, final BoundingBox ctd) {
            super(StructurePieceType.RUNTIME, cva, cqd, fu, integer, cap, ctd);
        }
        
        public RuntimePiece(final StructureManager cva, final CompoundTag le) {
            super(cva, le, StructurePieceType.RUNTIME);
        }
    }
}
