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

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

import com.hypixel.hytale.protocol.ColorLight;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import it.unimi.dsi.fastutil.objects.ObjectList;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.modules.entity.component.DynamicLight;
import com.hypixel.hytale.server.core.modules.entity.DespawnComponent;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.component.RemoveReason;
import java.util.List;
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.component.TransformComponent;
import com.hypixel.hytale.component.query.Query;
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.modules.entity.component.Interactable;
import javax.annotation.Nonnull;
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 ItemMergeSystem extends EntityTickingSystem<EntityStore>
{
    public static final float RADIUS = 2.0f;
    @Nonnull
    private final ComponentType<EntityStore, ItemComponent> itemComponentComponentType;
    @Nonnull
    private final ComponentType<EntityStore, Interactable> interactableComponentType;
    @Nonnull
    private final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> itemSpatialComponent;
    @Nonnull
    private final Query<EntityStore> query;
    
    public ItemMergeSystem(@Nonnull final ComponentType<EntityStore, ItemComponent> itemComponentComponentType, @Nonnull final ComponentType<EntityStore, Interactable> interactableComponentType, @Nonnull final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> itemSpatialComponent) {
        this.itemComponentComponentType = itemComponentComponentType;
        this.itemSpatialComponent = itemSpatialComponent;
        this.interactableComponentType = interactableComponentType;
        this.query = (Query<EntityStore>)Query.and(itemComponentComponentType, TransformComponent.getComponentType(), Query.not((Query<Object>)interactableComponentType), Query.not((Query<Object>)PreventItemMerging.getComponentType()));
    }
    
    @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 ItemComponent itemComponent = archetypeChunk.getComponent(index, this.itemComponentComponentType);
        assert itemComponent != null;
        ItemStack itemStack = itemComponent.getItemStack();
        if (itemStack == null) {
            return;
        }
        final Item itemAsset = itemStack.getItem();
        final int maxStack = itemAsset.getMaxStack();
        if (maxStack <= 1 || itemStack.getQuantity() >= maxStack) {
            return;
        }
        if (!itemComponent.pollMergeDelay(dt)) {
            return;
        }
        final SpatialResource<Ref<EntityStore>, EntityStore> spatialResource = store.getResource(this.itemSpatialComponent);
        final TimeResource timeResource = store.getResource(TimeResource.getResourceType());
        final TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType());
        assert transformComponent != null;
        final Vector3d position = transformComponent.getPosition();
        final ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
        spatialResource.getSpatialStructure().ordered(position, 2.0, results);
        final Ref<EntityStore> reference = archetypeChunk.getReferenceTo(index);
        for (final Ref<EntityStore> otherReference : results) {
            if (otherReference.isValid()) {
                if (otherReference.equals(reference)) {
                    continue;
                }
                final ItemComponent otherItemComponent = store.getComponent(otherReference, this.itemComponentComponentType);
                assert otherItemComponent != null;
                final ItemStack otherItemStack = otherItemComponent.getItemStack();
                if (otherItemStack == null) {
                    continue;
                }
                if (commandBuffer.getArchetype(otherReference).contains(this.interactableComponentType)) {
                    continue;
                }
                if (!itemStack.isStackableWith(otherItemStack)) {
                    continue;
                }
                final int otherQuantity = otherItemStack.getQuantity();
                if (otherQuantity >= maxStack) {
                    continue;
                }
                final int combinedTotal = itemStack.getQuantity() + otherQuantity;
                if (combinedTotal <= maxStack) {
                    commandBuffer.removeEntity(otherReference, RemoveReason.REMOVE);
                    otherItemComponent.setItemStack(null);
                    itemStack = itemStack.withQuantity(combinedTotal);
                }
                else {
                    otherItemComponent.setItemStack(itemStack.withQuantity(combinedTotal - maxStack));
                    final float newLifetime = otherItemComponent.computeLifetimeSeconds(commandBuffer);
                    DespawnComponent.trySetDespawn(commandBuffer, timeResource, otherReference, commandBuffer.getComponent(otherReference, DespawnComponent.getComponentType()), newLifetime);
                    final ColorLight otherItemDynamicLight = otherItemComponent.computeDynamicLight();
                    if (otherItemDynamicLight != null) {
                        final DynamicLight otherDynamicLightComponent = commandBuffer.getComponent(otherReference, DynamicLight.getComponentType());
                        if (otherDynamicLightComponent != null) {
                            otherDynamicLightComponent.setColorLight(otherItemDynamicLight);
                        }
                        else {
                            commandBuffer.putComponent(otherReference, DynamicLight.getComponentType(), new DynamicLight(otherItemDynamicLight));
                        }
                    }
                    itemStack = itemStack.withQuantity(maxStack);
                }
                itemComponent.setItemStack(itemStack);
                final float newLifetime = itemComponent.computeLifetimeSeconds(commandBuffer);
                DespawnComponent.trySetDespawn(commandBuffer, timeResource, reference, archetypeChunk.getComponent(index, DespawnComponent.getComponentType()), newLifetime);
                if (itemStack.getQuantity() >= maxStack) {
                    break;
                }
                continue;
            }
        }
    }
}
