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

package com.hypixel.hytale.server.npc.blackboard.view.combat;

import java.util.ArrayDeque;
import com.hypixel.hytale.component.Resource;
import com.hypixel.hytale.server.npc.NPCPlugin;
import java.util.Collections;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.server.core.modules.entity.AllLegacyEntityTypesQuery;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.system.HolderSystem;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.entity.InteractionChain;
import java.util.Set;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.client.ChargingInteraction;
import com.hypixel.hytale.server.npc.role.support.CombatSupport;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.server.core.modules.interaction.InteractionModule;
import com.hypixel.hytale.server.core.entity.InteractionManager;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import java.util.List;
import javax.annotation.Nonnull;

public class CombatViewSystems
{
    private static void clearCombatData(@Nonnull final CombatData combatData, @Nonnull final CombatDataPool dataPool) {
        if (!combatData.interpreted) {
            return;
        }
        final List<InterpretedCombatData> dataList = combatData.combatData;
        for (int i = 0; i < dataList.size(); ++i) {
            dataPool.releaseCombatData(dataList.get(i));
        }
        dataList.clear();
        combatData.interpreted = false;
    }
    
    @Nonnull
    public static List<InterpretedCombatData> getCombatData(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        final CombatData combatDataComponent = store.getComponent(ref, CombatData.getComponentType());
        if (combatDataComponent.interpreted) {
            return combatDataComponent.unmodifiableCombatData;
        }
        final InteractionManager interactionManager = store.getComponent(ref, InteractionModule.get().getInteractionManagerComponent());
        final CombatDataPool combatDataPool = store.getResource(CombatDataPool.getResourceType());
        final List<InterpretedCombatData> dataList = combatDataComponent.combatData;
        final IndexedLookupTableAssetMap<String, RootInteraction> interactionAssetMap = RootInteraction.getAssetMap();
        final Set<String> attackInteractions = interactionAssetMap.getKeysForTag(CombatSupport.ATTACK_TAG_INDEX);
        final Set<String> meleeInteractions = interactionAssetMap.getKeysForTag(CombatSupport.MELEE_TAG_INDEX);
        final Set<String> rangedInteractions = interactionAssetMap.getKeysForTag(CombatSupport.RANGED_TAG_INDEX);
        final Set<String> blockInteractions = interactionAssetMap.getKeysForTag(CombatSupport.BLOCK_TAG_INDEX);
        interactionManager.forEachInteraction((chain, interaction, list) -> {
            final String rootId = chain.getRootInteraction().getId();
            if (!attackInteractions.contains(rootId)) {
                return list;
            }
            else {
                final InterpretedCombatData entry = combatDataPool.getEmptyCombatData();
                entry.setAttack(rootId);
                entry.setCurrentElapsedTime(chain.getTimeInSeconds());
                entry.setCharging(interaction instanceof ChargingInteraction);
                entry.setPerformingMeleeAttack(meleeInteractions.contains(rootId));
                entry.setPerformingRangedAttack(rangedInteractions.contains(rootId));
                entry.setPerformingBlock(blockInteractions.contains(rootId));
                list.add(entry);
                return list;
            }
        }, (List)dataList);
        combatDataComponent.interpreted = true;
        return combatDataComponent.unmodifiableCombatData;
    }
    
    public static class Ensure extends HolderSystem<EntityStore>
    {
        private final ComponentType<EntityStore, CombatData> combatDataComponentType;
        
        public Ensure(final ComponentType<EntityStore, CombatData> combatDataComponentType) {
            this.combatDataComponentType = combatDataComponentType;
        }
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return AllLegacyEntityTypesQuery.INSTANCE;
        }
        
        @Override
        public void onEntityAdd(@Nonnull final Holder<EntityStore> holder, @Nonnull final AddReason reason, @Nonnull final Store<EntityStore> store) {
            holder.ensureComponent(this.combatDataComponentType);
        }
        
        @Override
        public void onEntityRemoved(@Nonnull final Holder<EntityStore> holder, @Nonnull final RemoveReason reason, @Nonnull final Store<EntityStore> store) {
        }
    }
    
    public static class EntityRemoved extends HolderSystem<EntityStore>
    {
        private final ComponentType<EntityStore, CombatData> combatDataComponentType;
        private final ResourceType<EntityStore, CombatDataPool> dataPoolResourceType;
        
        public EntityRemoved(final ComponentType<EntityStore, CombatData> combatDataComponentType, final ResourceType<EntityStore, CombatDataPool> dataPoolResourceType) {
            this.combatDataComponentType = combatDataComponentType;
            this.dataPoolResourceType = dataPoolResourceType;
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return this.combatDataComponentType;
        }
        
        @Override
        public void onEntityAdd(@Nonnull final Holder<EntityStore> holder, @Nonnull final AddReason reason, @Nonnull final Store<EntityStore> store) {
        }
        
        @Override
        public void onEntityRemoved(@Nonnull final Holder<EntityStore> holder, @Nonnull final RemoveReason reason, @Nonnull final Store<EntityStore> store) {
            final CombatData combatData = holder.getComponent(this.combatDataComponentType);
            final CombatDataPool dataPool = store.getResource(this.dataPoolResourceType);
            CombatViewSystems.clearCombatData(combatData, dataPool);
        }
    }
    
    public static class Ticking extends EntityTickingSystem<EntityStore>
    {
        private final ComponentType<EntityStore, CombatData> combatDataComponentType;
        private final ResourceType<EntityStore, CombatDataPool> dataPoolResourceType;
        
        public Ticking(final ComponentType<EntityStore, CombatData> combatDataComponentType, final ResourceType<EntityStore, CombatDataPool> dataPoolResourceType) {
            this.combatDataComponentType = combatDataComponentType;
            this.dataPoolResourceType = dataPoolResourceType;
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return this.combatDataComponentType;
        }
        
        @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 CombatData combatData = archetypeChunk.getComponent(index, this.combatDataComponentType);
            final CombatDataPool dataPool = store.getResource(this.dataPoolResourceType);
            CombatViewSystems.clearCombatData(combatData, dataPool);
        }
    }
    
    public static class CombatData implements Component<EntityStore>
    {
        private final List<InterpretedCombatData> combatData;
        private final List<InterpretedCombatData> unmodifiableCombatData;
        private boolean interpreted;
        
        public CombatData() {
            this.combatData = new ObjectArrayList<InterpretedCombatData>();
            this.unmodifiableCombatData = Collections.unmodifiableList((List<? extends InterpretedCombatData>)this.combatData);
        }
        
        public static ComponentType<EntityStore, CombatData> getComponentType() {
            return NPCPlugin.get().getCombatDataComponentType();
        }
        
        @Nonnull
        @Override
        public Component<EntityStore> clone() {
            final CombatData data = new CombatData();
            data.interpreted = this.interpreted;
            for (int i = 0; i < this.combatData.size(); ++i) {
                data.combatData.add(this.combatData.get(i).clone());
            }
            return data;
        }
    }
    
    public static class CombatDataPool implements Resource<EntityStore>
    {
        private final ArrayDeque<InterpretedCombatData> combatDataPool;
        
        public CombatDataPool() {
            this.combatDataPool = new ArrayDeque<InterpretedCombatData>();
        }
        
        public static ResourceType<EntityStore, CombatDataPool> getResourceType() {
            return NPCPlugin.get().getCombatDataPoolResourceType();
        }
        
        @Nonnull
        @Override
        public Resource<EntityStore> clone() {
            return new CombatDataPool();
        }
        
        public InterpretedCombatData getEmptyCombatData() {
            if (this.combatDataPool.isEmpty()) {
                return new InterpretedCombatData();
            }
            return this.combatDataPool.poll();
        }
        
        public void releaseCombatData(@Nonnull final InterpretedCombatData combatData) {
            this.combatDataPool.push(combatData);
        }
    }
}
