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

package com.hypixel.hytale.server.core.modules.entity.player;

import com.hypixel.hytale.server.core.entity.InteractionChain;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.server.core.inventory.transaction.ItemStackTransaction;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import it.unimi.dsi.fastutil.objects.ObjectList;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.component.spatial.SpatialStructure;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
import java.util.List;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.modules.entity.DespawnComponent;
import com.hypixel.hytale.server.core.modules.time.TimeResource;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.server.core.modules.entity.item.PreventPickup;
import com.hypixel.hytale.server.core.modules.entity.item.PickupItemComponent;
import com.hypixel.hytale.server.core.modules.entity.component.Interactable;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.dependency.SystemDependency;
import com.hypixel.hytale.component.dependency.OrderPriority;
import com.hypixel.hytale.server.core.modules.entity.system.PlayerSpatialSystem;
import com.hypixel.hytale.component.dependency.Order;
import com.hypixel.hytale.server.core.modules.interaction.InteractionModule;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.dependency.Dependency;
import java.util.Set;
import com.hypixel.hytale.server.core.entity.InteractionManager;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.server.core.entity.entities.Player;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;

public class PlayerItemEntityPickupSystem extends EntityTickingSystem<EntityStore>
{
    @Nonnull
    private final ComponentType<EntityStore, ItemComponent> itemComponentType;
    @Nonnull
    private final ComponentType<EntityStore, Player> playerComponentType;
    @Nonnull
    private final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent;
    @Nonnull
    private final ComponentType<EntityStore, InteractionManager> interactionManagerType;
    @Nonnull
    private final Set<Dependency<EntityStore>> dependencies;
    @Nonnull
    private final Query<EntityStore> query;
    
    public PlayerItemEntityPickupSystem(@Nonnull final ComponentType<EntityStore, ItemComponent> itemComponentType, @Nonnull final ComponentType<EntityStore, Player> playerComponentType, @Nonnull final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent) {
        this.itemComponentType = itemComponentType;
        this.playerComponentType = playerComponentType;
        this.interactionManagerType = InteractionModule.get().getInteractionManagerComponent();
        this.playerSpatialComponent = playerSpatialComponent;
        this.dependencies = (Set<Dependency<EntityStore>>)Set.of(new SystemDependency(Order.AFTER, PlayerSpatialSystem.class, OrderPriority.CLOSEST));
        this.query = (Query<EntityStore>)Query.and(itemComponentType, TransformComponent.getComponentType(), Query.not((Query<Object>)Interactable.getComponentType()), Query.not((Query<Object>)PickupItemComponent.getComponentType()), Query.not((Query<Object>)PreventPickup.getComponentType()));
    }
    
    @Nonnull
    @Override
    public Set<Dependency<EntityStore>> getDependencies() {
        return this.dependencies;
    }
    
    @Nonnull
    @Override
    public Query<EntityStore> getQuery() {
        return this.query;
    }
    
    @Override
    public boolean isParallel(final int archetypeChunkSize, final int taskCount) {
        return false;
    }
    
    @Override
    public void tick(final float dt, final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
        final Ref<EntityStore> itemRef = archetypeChunk.getReferenceTo(index);
        final ItemComponent itemComponent = archetypeChunk.getComponent(index, this.itemComponentType);
        assert itemComponent != null;
        if (!itemComponent.pollPickupDelay(dt)) {
            return;
        }
        if (!itemComponent.pollPickupThrottle(dt)) {
            return;
        }
        final TimeResource timeResource = commandBuffer.getResource(TimeResource.getResourceType());
        final SpatialResource<Ref<EntityStore>, EntityStore> playerSpatialResource = store.getResource(this.playerSpatialComponent);
        final SpatialStructure<Ref<EntityStore>> spatialStructure = playerSpatialResource.getSpatialStructure();
        final TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType());
        assert transformComponent != null;
        final Vector3d itemEntityPosition = transformComponent.getPosition();
        final DespawnComponent despawnComponent = archetypeChunk.getComponent(index, DespawnComponent.getComponentType());
        final float pickupRadius = itemComponent.getPickupRadius(commandBuffer);
        ItemStack itemStack = itemComponent.getItemStack();
        final Item item = itemStack.getItem();
        final String interactions = item.getInteractions().get(InteractionType.Pickup);
        if (interactions == null) {
            final ObjectList<Ref<EntityStore>> targetPlayerRefs = SpatialResource.getThreadLocalReferenceList();
            spatialStructure.ordered(itemEntityPosition, pickupRadius, targetPlayerRefs);
            for (final Ref<EntityStore> targetPlayerRef : targetPlayerRefs) {
                if (store.getArchetype(targetPlayerRef).contains(DeathComponent.getComponentType())) {
                    continue;
                }
                final Player playerComponent = store.getComponent(targetPlayerRef, this.playerComponentType);
                assert playerComponent != null;
                PlayerSettings playerSettings = commandBuffer.getComponent(targetPlayerRef, PlayerSettings.getComponentType());
                if (playerSettings == null) {
                    playerSettings = PlayerSettings.defaults();
                }
                final ItemContainer itemContainer = playerComponent.getInventory().getContainerForItemPickup(item, playerSettings);
                final ItemStackTransaction transaction = itemContainer.addItemStack(itemStack);
                final ItemStack remainder = transaction.getRemainder();
                if (ItemStack.isEmpty(remainder)) {
                    itemComponent.setRemovedByPlayerPickup(true);
                    commandBuffer.removeEntity(itemRef, RemoveReason.REMOVE);
                    playerComponent.notifyPickupItem(targetPlayerRef, itemStack, itemEntityPosition, commandBuffer);
                    final Holder<EntityStore> pickupItemHolder = ItemComponent.generatePickedUpItem(itemRef, commandBuffer, targetPlayerRef, itemEntityPosition);
                    commandBuffer.addEntity(pickupItemHolder, AddReason.SPAWN);
                    break;
                }
                if (remainder.equals(itemStack)) {
                    continue;
                }
                final int quantity = itemStack.getQuantity() - remainder.getQuantity();
                itemStack = remainder;
                itemComponent.setItemStack(remainder);
                final float newLifetime = itemComponent.computeLifetimeSeconds(commandBuffer);
                DespawnComponent.trySetDespawn(commandBuffer, timeResource, itemRef, despawnComponent, newLifetime);
                final Holder<EntityStore> pickupItemHolder2 = ItemComponent.generatePickedUpItem(itemRef, commandBuffer, targetPlayerRef, itemEntityPosition);
                commandBuffer.addEntity(pickupItemHolder2, AddReason.SPAWN);
                if (quantity <= 0) {
                    continue;
                }
                playerComponent.notifyPickupItem(targetPlayerRef, itemStack.withQuantity(quantity), itemEntityPosition, commandBuffer);
            }
            return;
        }
        final Ref<EntityStore> targetRef = spatialStructure.closest(itemEntityPosition);
        if (targetRef == null) {
            return;
        }
        final TransformComponent targetTransformComponent = store.getComponent(targetRef, TransformComponent.getComponentType());
        assert targetTransformComponent != null;
        final InteractionManager targetInteractionManagerComponent = store.getComponent(targetRef, this.interactionManagerType);
        assert targetInteractionManagerComponent != null;
        final Vector3d targetPosition = targetTransformComponent.getPosition();
        final double distance = targetPosition.distanceTo(itemEntityPosition);
        if (distance > pickupRadius) {
            return;
        }
        final Ref<EntityStore> reference = archetypeChunk.getReferenceTo(index);
        commandBuffer.run(_store -> {
            final InteractionContext context = InteractionContext.forInteraction(targetInteractionManagerComponent, targetRef, InteractionType.Pickup, commandBuffer);
            final InteractionChain chain = targetInteractionManagerComponent.initChain(InteractionType.Pickup, context, RootInteraction.getRootInteractionOrUnknown(interactions), false);
            context.getMetaStore().putMetaObject(Interaction.TARGET_ENTITY, reference);
            targetInteractionManagerComponent.executeChain(reference, commandBuffer, chain);
            _store.removeEntity(reference, RemoveReason.REMOVE);
        });
    }
}
