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

package com.hypixel.hytale.server.npc.corecomponents.items;

import java.util.function.Supplier;
import com.hypixel.hytale.server.npc.util.InventoryHelper;
import com.hypixel.hytale.server.core.inventory.Inventory;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderActionWithDelay;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.corecomponents.items.builders.BuilderActionPickUpItem;
import javax.annotation.Nullable;
import java.util.List;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.npc.corecomponents.ActionWithDelay;

public class ActionPickUpItem extends ActionWithDelay
{
    protected static final ComponentType<EntityStore, ItemComponent> ITEM_COMPONENT_TYPE;
    protected static final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE;
    protected final double range;
    protected final StorageTarget storageTarget;
    protected final boolean hoover;
    @Nullable
    protected final List<String> hooverItems;
    
    public ActionPickUpItem(@Nonnull final BuilderActionPickUpItem builder, @Nonnull final BuilderSupport support) {
        super(builder, support);
        this.range = builder.getRange(support);
        this.storageTarget = builder.getStorageTarget(support);
        this.hoover = builder.getHoover();
        final String[] items = builder.getItems(support);
        this.hooverItems = ((items != null) ? List.of(items) : null);
    }
    
    @Override
    public void registerWithSupport(@Nonnull final Role role) {
        role.getPositionCache().requireDroppedItemDistance(this.range);
    }
    
    @Override
    public boolean canExecute(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider sensorInfo, final double dt, @Nonnull final Store<EntityStore> store) {
        if (!super.canExecute(ref, role, sensorInfo, dt, store)) {
            return false;
        }
        if (!this.hoover) {
            if (sensorInfo == null || !sensorInfo.hasPosition()) {
                return false;
            }
            final Ref<EntityStore> targetRef = sensorInfo.getPositionProvider().getTarget();
            if (targetRef == null) {
                return false;
            }
            final ItemComponent itemComponent = store.getComponent(targetRef, ActionPickUpItem.ITEM_COMPONENT_TYPE);
            if (itemComponent == null || !itemComponent.canPickUp()) {
                return false;
            }
            final TransformComponent selfTransformComponent = store.getComponent(ref, ActionPickUpItem.TRANSFORM_COMPONENT_TYPE);
            assert selfTransformComponent != null;
            final Vector3d selfPosition = selfTransformComponent.getPosition();
            final TransformComponent targetTransformComponent = store.getComponent(targetRef, ActionPickUpItem.TRANSFORM_COMPONENT_TYPE);
            assert targetTransformComponent != null;
            final Vector3d targetPosition = targetTransformComponent.getPosition();
            final double distanceSquared = selfPosition.distanceSquaredTo(targetPosition);
            if (distanceSquared > this.range * this.range) {
                return false;
            }
        }
        else if (role.getPositionCache().getDroppedItemList().isEmpty()) {
            return false;
        }
        return !this.isDelaying();
    }
    
    @Override
    public boolean execute(@Nonnull final Ref<EntityStore> ref, @Nonnull final Role role, @Nullable final InfoProvider sensorInfo, final double dt, @Nonnull final Store<EntityStore> store) {
        super.execute(ref, role, sensorInfo, dt, store);
        Ref<EntityStore> itemRef = null;
        if (!this.hoover) {
            if (sensorInfo != null) {
                itemRef = sensorInfo.getPositionProvider().getTarget();
            }
        }
        else {
            itemRef = role.getPositionCache().getClosestDroppedItemInRange(ref, 0.0, this.range, ActionPickUpItem::filterItem, role, this, store);
        }
        this.prepareDelay();
        this.startDelay(role.getEntitySupport());
        if (itemRef == null) {
            return false;
        }
        final NPCEntity npcComponent = store.getComponent(ref, NPCEntity.getComponentType());
        assert npcComponent != null;
        final Inventory inventory = npcComponent.getInventory();
        switch (this.storageTarget.ordinal()) {
            case 0: {
                ItemComponent.addToItemContainer(store, itemRef, inventory.getCombinedHotbarFirst());
                break;
            }
            case 1: {
                ItemComponent.addToItemContainer(store, itemRef, inventory.getCombinedStorageFirst());
                break;
            }
            case 2: {
                store.removeEntity(itemRef, RemoveReason.REMOVE);
                break;
            }
        }
        return true;
    }
    
    protected boolean filterItem(@Nonnull final Ref<EntityStore> ref, final Role role, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (!ref.isValid()) {
            return false;
        }
        if (this.hooverItems == null) {
            return true;
        }
        final ItemComponent itemComponent = componentAccessor.getComponent(ref, ActionPickUpItem.ITEM_COMPONENT_TYPE);
        assert itemComponent != null;
        return InventoryHelper.matchesItem(this.hooverItems, itemComponent.getItemStack());
    }
    
    static {
        ITEM_COMPONENT_TYPE = ItemComponent.getComponentType();
        TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
    }
    
    public enum StorageTarget implements Supplier<String>
    {
        Hotbar("Prioritise hotbar"), 
        Inventory("Prioritise inventory"), 
        Destroy("Destroy the item");
        
        private final String description;
        
        private StorageTarget(final String description) {
            this.description = description;
        }
        
        @Override
        public String get() {
            return this.description;
        }
    }
}
