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

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

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import com.hypixel.hytale.server.core.asset.type.gameplay.RespawnConfig;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerRespawnPointData;
import com.hypixel.hytale.server.core.entity.entities.player.pages.PageManager;
import com.hypixel.hytale.component.Holder;
import java.util.UUID;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.builtin.beds.respawn.SetNameRespawnPointPage;
import com.hypixel.hytale.builtin.beds.respawn.SelectOverrideRespawnPointPage;
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
import com.hypixel.hytale.builtin.beds.respawn.OverrideNearbyRespawnPointPage;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSleep;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSomnolence;
import com.hypixel.hytale.builtin.mounts.BlockMountAPI;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.protocol.BlockPosition;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.server.core.universe.world.meta.state.RespawnBlock;
import com.hypixel.hytale.server.core.modules.block.BlockModule;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockComponentChunk;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.math.vector.Vector3i;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.SimpleBlockInteraction;

public class BedInteraction extends SimpleBlockInteraction
{
    @Nonnull
    private static final Message MESSAGE_SERVER_CUSTOM_UI_RESPAWN_POINT_CLAIMED;
    @Nonnull
    public static final BuilderCodec<BedInteraction> CODEC;
    
    @Override
    protected void interactWithBlock(@Nonnull final World world, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final InteractionType type, @Nonnull final InteractionContext context, @Nullable final ItemStack itemInHand, @Nonnull final Vector3i pos, @Nonnull final CooldownHandler cooldownHandler) {
        final Ref<EntityStore> ref = context.getEntity();
        final Player player = commandBuffer.getComponent(ref, Player.getComponentType());
        if (player == null) {
            return;
        }
        final Store<EntityStore> store = commandBuffer.getStore();
        final PlayerRef playerRefComponent = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
        assert playerRefComponent != null;
        final UUIDComponent playerUuidComponent = commandBuffer.getComponent(ref, UUIDComponent.getComponentType());
        assert playerUuidComponent != null;
        final UUID playerUuid = playerUuidComponent.getUuid();
        final Ref<ChunkStore> chunkReference = world.getChunkStore().getChunkReference(ChunkUtil.indexChunkFromBlock(pos.x, pos.z));
        if (chunkReference == null) {
            return;
        }
        final Store<ChunkStore> chunkStore = chunkReference.getStore();
        final BlockComponentChunk blockComponentChunk = chunkStore.getComponent(chunkReference, BlockComponentChunk.getComponentType());
        assert blockComponentChunk != null;
        final int blockIndex = ChunkUtil.indexBlockInColumn(pos.x, pos.y, pos.z);
        Ref<ChunkStore> blockRef = blockComponentChunk.getEntityReference(blockIndex);
        if (blockRef == null) {
            final Holder<ChunkStore> holder = ChunkStore.REGISTRY.newHolder();
            holder.putComponent(BlockModule.BlockStateInfo.getComponentType(), new BlockModule.BlockStateInfo(blockIndex, chunkReference));
            holder.ensureComponent(RespawnBlock.getComponentType());
            blockRef = chunkStore.addEntity(holder, AddReason.SPAWN);
        }
        final RespawnBlock respawnBlockComponent = chunkStore.getComponent(blockRef, RespawnBlock.getComponentType());
        if (respawnBlockComponent == null) {
            return;
        }
        final UUID ownerUUID = respawnBlockComponent.getOwnerUUID();
        final PageManager pageManager = player.getPageManager();
        final boolean isOwner = playerUuid.equals(ownerUUID);
        if (isOwner) {
            final BlockPosition rawTarget = context.getMetaStore().getMetaObject(BedInteraction.TARGET_BLOCK_RAW);
            final Vector3f whereWasHit = new Vector3f(rawTarget.x + 0.5f, rawTarget.y + 0.5f, rawTarget.z + 0.5f);
            final BlockMountAPI.BlockMountResult result = BlockMountAPI.mountOnBlock(ref, commandBuffer, pos, whereWasHit);
            if (result instanceof BlockMountAPI.DidNotMount) {
                player.sendMessage(Message.translation("server.interactions.didNotMount").param("state", result.toString()));
            }
            else if (result instanceof BlockMountAPI.Mounted) {
                commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.NoddingOff.createComponent());
            }
            return;
        }
        if (ownerUUID != null) {
            player.sendMessage(BedInteraction.MESSAGE_SERVER_CUSTOM_UI_RESPAWN_POINT_CLAIMED);
            return;
        }
        final PlayerRespawnPointData[] respawnPoints = player.getPlayerConfigData().getPerWorldData(world.getName()).getRespawnPoints();
        final RespawnConfig respawnConfig = world.getGameplayConfig().getRespawnConfig();
        final int radiusLimitRespawnPoint = respawnConfig.getRadiusLimitRespawnPoint();
        final PlayerRespawnPointData[] nearbyRespawnPoints = this.getNearbySavedRespawnPoints(pos, respawnBlockComponent, respawnPoints, radiusLimitRespawnPoint);
        if (nearbyRespawnPoints != null) {
            pageManager.openCustomPage(ref, store, new OverrideNearbyRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent, nearbyRespawnPoints, radiusLimitRespawnPoint));
            return;
        }
        if (respawnPoints != null && respawnPoints.length >= respawnConfig.getMaxRespawnPointsPerPlayer()) {
            pageManager.openCustomPage(ref, store, new SelectOverrideRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent, respawnPoints));
            return;
        }
        pageManager.openCustomPage(ref, store, new SetNameRespawnPointPage(playerRefComponent, type, pos, respawnBlockComponent));
    }
    
    @Override
    protected void simulateInteractWithBlock(@Nonnull final InteractionType type, @Nonnull final InteractionContext context, @Nullable final ItemStack itemInHand, @Nonnull final World world, @Nonnull final Vector3i targetBlock) {
    }
    
    @Nullable
    private PlayerRespawnPointData[] getNearbySavedRespawnPoints(@Nonnull final Vector3i currentRespawnPointPosition, @Nonnull final RespawnBlock respawnBlock, @Nullable final PlayerRespawnPointData[] respawnPoints, final int radiusLimitRespawnPoint) {
        if (respawnPoints == null || respawnPoints.length == 0) {
            return null;
        }
        final ObjectArrayList<PlayerRespawnPointData> nearbyRespawnPointList = new ObjectArrayList<PlayerRespawnPointData>();
        for (int i = 0; i < respawnPoints.length; ++i) {
            final PlayerRespawnPointData respawnPoint = respawnPoints[i];
            final Vector3i respawnPointPosition = respawnPoint.getBlockPosition();
            if (respawnPointPosition.distanceTo(currentRespawnPointPosition.x, respawnPointPosition.y, currentRespawnPointPosition.z) < radiusLimitRespawnPoint) {
                nearbyRespawnPointList.add(respawnPoint);
            }
        }
        return (PlayerRespawnPointData[])(nearbyRespawnPointList.isEmpty() ? null : ((PlayerRespawnPointData[])nearbyRespawnPointList.toArray(PlayerRespawnPointData[]::new)));
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "BedInteraction{} " + super.toString();
    }
    
    static {
        MESSAGE_SERVER_CUSTOM_UI_RESPAWN_POINT_CLAIMED = Message.translation("server.customUI.respawnPointClaimed");
        CODEC = BuilderCodec.builder(BedInteraction.class, BedInteraction::new, SimpleBlockInteraction.CODEC).documentation("Interact with a bed block, ostensibly to sleep in it.").build();
    }
}
