// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.builtin.beds.respawn;

import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import java.util.UUID;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerWorldData;
import com.hypixel.hytale.math.shape.Box;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.protocol.packets.interface_.Page;
import com.hypixel.hytale.common.util.ArrayUtil;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.Message;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerRespawnPointData;
import com.hypixel.hytale.server.core.universe.world.meta.state.RespawnBlock;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
import com.hypixel.hytale.protocol.InteractionType;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage;

public abstract class RespawnPointPage extends InteractiveCustomUIPage<RespawnPointEventData>
{
    private final int RESPAWN_NAME_MAX_LENGTH = 32;
    
    public RespawnPointPage(@Nonnull final PlayerRef playerRef, final InteractionType interactionType) {
        super(playerRef, (interactionType == InteractionType.Use) ? CustomPageLifetime.CanDismissOrCloseThroughInteraction : CustomPageLifetime.CanDismiss, RespawnPointEventData.CODEC);
    }
    
    @Override
    public abstract void build(@Nonnull final Ref<EntityStore> p0, @Nonnull final UICommandBuilder p1, @Nonnull final UIEventBuilder p2, @Nonnull final Store<EntityStore> p3);
    
    protected void setRespawnPointForPlayer(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final Vector3i blockPosition, @Nonnull final RespawnBlock respawnBlock, @Nonnull String respawnPointName, @Nullable final PlayerRespawnPointData... respawnPointsToRemove) {
        respawnPointName = respawnPointName.trim();
        if (respawnPointName.isEmpty()) {
            this.displayError(Message.translation("server.customUI.needToSetName"));
            return;
        }
        if (respawnPointName.length() > 32) {
            this.displayError(Message.translation("server.customUI.respawnNameTooLong").param("maxLength", 32));
            return;
        }
        respawnBlock.setOwnerUUID(this.playerRef.getUuid());
        final World world = store.getExternalData().getWorld();
        final Player playerComponent = store.getComponent(ref, Player.getComponentType());
        assert playerComponent != null;
        final WorldChunk chunk = world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(blockPosition.x, blockPosition.z));
        if (chunk == null) {
            return;
        }
        chunk.markNeedsSaving();
        final BlockType blockType = chunk.getBlockType(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
        final int rotationIndex = chunk.getRotationIndex(blockPosition.x, blockPosition.y, blockPosition.z);
        final Box hitbox = BlockBoundingBoxes.getAssetMap().getAsset(blockType.getHitboxTypeIndex()).get(rotationIndex).getBoundingBox();
        final double blockCenterWidthOffset = hitbox.min.x + hitbox.width() / 2.0;
        final double blockCenterDepthOffset = hitbox.min.z + hitbox.depth() / 2.0;
        final Vector3d respawnPosition = new Vector3d(blockPosition.getX() + blockCenterWidthOffset, blockPosition.getY() + hitbox.height(), blockPosition.getZ() + blockCenterDepthOffset);
        final PlayerRespawnPointData respawnPointData = new PlayerRespawnPointData(blockPosition, respawnPosition, respawnPointName);
        final PlayerWorldData perWorldData = playerComponent.getPlayerConfigData().getPerWorldData(world.getName());
        final PlayerRespawnPointData[] respawnPoints = this.handleRespawnPointsToRemove(perWorldData.getRespawnPoints(), respawnPointsToRemove, world);
        if (respawnPoints != null) {
            if (ArrayUtil.contains(respawnPoints, respawnPointData)) {
                return;
            }
            if (respawnPointsToRemove == null || respawnPointsToRemove.length == 0) {
                for (int i = 0; i < respawnPoints.length; ++i) {
                    final PlayerRespawnPointData savedRespawnPointData = respawnPoints[i];
                    if (savedRespawnPointData.getBlockPosition().equals(blockPosition)) {
                        savedRespawnPointData.setName(respawnPointName);
                        this.playerRef.sendMessage(Message.translation("server.customUI.updatedRespawnPointName").param("name", respawnPointName));
                        playerComponent.getPageManager().setPage(ref, store, Page.None);
                        return;
                    }
                }
            }
        }
        perWorldData.setRespawnPoints(ArrayUtil.append(respawnPoints, respawnPointData));
        this.playerRef.sendMessage(Message.translation("server.customUI.respawnPointSet").param("name", respawnPointName));
        playerComponent.getPageManager().setPage(ref, store, Page.None);
    }
    
    @Nonnull
    private PlayerRespawnPointData[] handleRespawnPointsToRemove(@Nonnull PlayerRespawnPointData[] respawnPoints, @Nullable final PlayerRespawnPointData[] respawnPointsToRemove, @Nonnull final World world) {
        if (respawnPointsToRemove == null) {
            return respawnPoints;
        }
        final ChunkStore chunkStore = world.getChunkStore();
        for (int i = 0; i < respawnPointsToRemove.length; ++i) {
            final PlayerRespawnPointData respawnPointToRemove = respawnPointsToRemove[i];
            for (int j = 0; j < respawnPoints.length; ++j) {
                final PlayerRespawnPointData respawnPoint = respawnPoints[j];
                if (respawnPoint.getBlockPosition().equals(respawnPointToRemove.getBlockPosition())) {
                    respawnPoints = ArrayUtil.remove(respawnPoints, j);
                    break;
                }
            }
            final Vector3i position = respawnPointToRemove.getBlockPosition();
            final Ref<ChunkStore> chunkReference = chunkStore.getChunkReference(ChunkUtil.indexChunkFromBlock(position.x, position.z));
            if (chunkReference != null) {
                final BlockComponentChunk blockComponentChunk = chunkStore.getStore().getComponent(chunkReference, BlockComponentChunk.getComponentType());
                final Ref<ChunkStore> blockRef = blockComponentChunk.getEntityReference(ChunkUtil.indexBlockInColumn(position.x, position.y, position.z));
                if (blockRef != null) {
                    final RespawnBlock respawnBlock = chunkStore.getStore().getComponent(blockRef, RespawnBlock.getComponentType());
                    if (respawnBlock != null) {
                        respawnBlock.setOwnerUUID(null);
                        final WorldChunk worldChunk = chunkStore.getStore().getComponent(chunkReference, WorldChunk.getComponentType());
                        if (worldChunk != null) {
                            worldChunk.markNeedsSaving();
                        }
                    }
                }
            }
        }
        return respawnPoints;
    }
    
    protected void displayError(@Nonnull final Message errorMessage) {
        final UICommandBuilder commandBuilder = new UICommandBuilder();
        commandBuilder.set("#Error.Visible", true);
        commandBuilder.set("#Error.Text", errorMessage);
        this.sendUpdate(commandBuilder);
    }
    
    public static class RespawnPointEventData
    {
        static final String KEY_ACTION = "Action";
        static final String ACTION_CANCEL = "Cancel";
        static final String KEY_INDEX = "Index";
        static final String KEY_RESPAWN_POINT_NAME = "@RespawnPointName";
        public static final BuilderCodec<RespawnPointEventData> CODEC;
        private String action;
        private String indexStr;
        private int index;
        private String respawnPointName;
        
        public RespawnPointEventData() {
            this.index = -1;
        }
        
        public String getAction() {
            return this.action;
        }
        
        public int getIndex() {
            return this.index;
        }
        
        public String getRespawnPointName() {
            return this.respawnPointName;
        }
        
        static {
            // 
            // This method could not be decompiled.
            // 
            // Original Bytecode:
            // 
            //     2: invokedynamic   BootstrapMethod #0, get:()Ljava/util/function/Supplier;
            //     7: invokestatic    com/hypixel/hytale/codec/builder/BuilderCodec.builder:(Ljava/lang/Class;Ljava/util/function/Supplier;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    10: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    13: dup            
            //    14: ldc             "Action"
            //    16: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    19: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    22: invokedynamic   BootstrapMethod #1, accept:()Ljava/util/function/BiConsumer;
            //    27: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/Function;
            //    32: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    35: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    38: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    41: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    44: dup            
            //    45: ldc             "Index"
            //    47: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    50: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    53: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
            //    58: invokedynamic   BootstrapMethod #4, apply:()Ljava/util/function/Function;
            //    63: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    66: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    69: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    72: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    75: dup            
            //    76: ldc             "@RespawnPointName"
            //    78: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    81: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    84: invokedynamic   BootstrapMethod #5, accept:()Ljava/util/function/BiConsumer;
            //    89: invokedynamic   BootstrapMethod #6, apply:()Ljava/util/function/Function;
            //    94: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    97: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   100: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   103: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   106: putstatic       com/hypixel/hytale/builtin/beds/respawn/RespawnPointPage$RespawnPointEventData.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   109: return         
            // 
            // The error that occurred was:
            // 
            // java.lang.UnsupportedOperationException: The requested operation is not supported.
            //     at com.strobel.util.ContractUtils.unsupported(ContractUtils.java:27)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:284)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:279)
            //     at com.strobel.assembler.metadata.TypeReference.makeGenericType(TypeReference.java:154)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:225)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:211)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:314)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2611)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1083)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:684)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:667)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:373)
            //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
            //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:344)
            //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:42)
            //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:206)
            //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:662)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
            //     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
            //     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
            //     at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
            //     at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
            //     at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:129)
            // 
            throw new IllegalStateException("An error occurred while decompiling this method.");
        }
    }
}
