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

package com.hypixel.hytale.server.core.modules.entitystats;

import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.modules.interaction.InteractionModule;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.server.core.universe.world.World;
import org.bouncycastle.util.Arrays;
import java.util.Iterator;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.Map;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.server.core.entity.EntityUtils;
import com.hypixel.hytale.server.core.entity.LivingEntity;
import com.hypixel.hytale.server.core.modules.entity.AllLegacyLivingEntityTypesQuery;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.universe.Universe;
import javax.annotation.Nullable;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.entity.Entity;
import com.hypixel.hytale.server.core.modules.entitystats.asset.DefaultEntityStatTypes;
import com.hypixel.hytale.server.core.asset.type.entityeffect.config.EntityEffect;
import com.hypixel.hytale.assetstore.AssetMap;
import com.hypixel.hytale.assetstore.JsonAsset;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.component.system.ISystem;
import com.hypixel.hytale.assetstore.event.LoadedAssetsEvent;
import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.server.core.asset.type.particle.config.ParticleSystem;
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
import java.util.List;
import java.util.Collections;
import com.hypixel.hytale.server.core.asset.packet.AssetPacketGenerator;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatTypePacketGenerator;
import java.util.function.Function;
import com.hypixel.hytale.assetstore.codec.AssetCodec;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
import com.hypixel.hytale.assetstore.AssetStore;
import com.hypixel.hytale.server.core.asset.HytaleAssetStore;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.StatCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.GlidingCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.SprintingCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.WieldingCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.OutOfCombatCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.PlayerCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.EnvironmentCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.AliveCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.ChargingCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.SuffocatingCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.NoDamageTakenCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.RegenHealthCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.LogicCondition;
import com.hypixel.hytale.server.core.modules.entitystats.asset.condition.Condition;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.server.core.modules.entitystats.modifier.StaticModifier;
import com.hypixel.hytale.server.core.modules.entitystats.modifier.Modifier;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.component.SystemType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.common.plugin.PluginManifest;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;

public class EntityStatsModule extends JavaPlugin
{
    public static final PluginManifest MANIFEST;
    private static EntityStatsModule instance;
    private ComponentType<EntityStore, EntityStatMap> entityStatMapComponentType;
    private SystemType<EntityStore, EntityStatsSystems.StatModifyingSystem> statModifyingSystemType;
    static final /* synthetic */ boolean $assertionsDisabled;
    
    public static EntityStatsModule get() {
        return EntityStatsModule.instance;
    }
    
    public EntityStatsModule(@Nonnull final JavaPluginInit init) {
        super(init);
        EntityStatsModule.instance = this;
    }
    
    @Override
    protected void setup() {
        Modifier.CODEC.register("Boost", StaticModifier.class, StaticModifier.ENTITY_CODEC);
        Modifier.CODEC.register("Static", StaticModifier.class, StaticModifier.ENTITY_CODEC);
        Condition.CODEC.register("LogicCondition", LogicCondition.class, LogicCondition.CODEC);
        Condition.CODEC.register("RegenHealth", RegenHealthCondition.class, RegenHealthCondition.CODEC);
        Condition.CODEC.register("NoDamageTaken", NoDamageTakenCondition.class, NoDamageTakenCondition.CODEC);
        Condition.CODEC.register("Suffocating", SuffocatingCondition.class, SuffocatingCondition.CODEC);
        Condition.CODEC.register("Charging", ChargingCondition.class, ChargingCondition.CODEC);
        Condition.CODEC.register("Alive", AliveCondition.class, AliveCondition.CODEC);
        Condition.CODEC.register("Environment", EnvironmentCondition.class, EnvironmentCondition.CODEC);
        Condition.CODEC.register("Player", PlayerCondition.class, PlayerCondition.CODEC);
        Condition.CODEC.register("OutOfCombat", OutOfCombatCondition.class, OutOfCombatCondition.CODEC);
        Condition.CODEC.register("Wielding", WieldingCondition.class, WieldingCondition.CODEC);
        Condition.CODEC.register("Sprinting", SprintingCondition.class, SprintingCondition.CODEC);
        Condition.CODEC.register("Gliding", GlidingCondition.class, GlidingCondition.CODEC);
        Condition.CODEC.register("Stat", StatCondition.class, StatCondition.CODEC);
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(EntityStatType.class, new IndexedLookupTableAssetMap(EntityStatType[]::new)).setPath()).setCodec(EntityStatType.CODEC)).setKeyFunction(EntityStatType::getId)).setPacketGenerator(new EntityStatTypePacketGenerator()).setReplaceOnRemove(EntityStatType::getUnknownFor)).preLoadAssets(Collections.singletonList(EntityStatType.UNKNOWN)).loadsAfter(SoundEvent.class, ParticleSystem.class)).build());
        this.getEventRegistry().register(LoadedAssetsEvent.class, EntityStatType.class, this::onLoadedAssetsEvent);
        this.statModifyingSystemType = this.getEntityStoreRegistry().registerSystemType((Class<? super EntityStatsSystems.StatModifyingSystem>)EntityStatsSystems.StatModifyingSystem.class);
        this.entityStatMapComponentType = this.getEntityStoreRegistry().registerComponent(EntityStatMap.class, "EntityStats", EntityStatMap.CODEC);
        this.getEntityStoreRegistry().registerSystem(new EntityStatsSystems.Setup(this.entityStatMapComponentType));
        this.getEntityStoreRegistry().registerSystem(new PlayerRegenerateStatsSystem());
        this.getEntityStoreRegistry().registerSystem(new EntityStatsSystems.Recalculate(this.entityStatMapComponentType));
        this.getEntityStoreRegistry().registerSystem(new EntityStatsSystems.EntityTrackerUpdate(this.entityStatMapComponentType));
        this.getEntityStoreRegistry().registerSystem((ISystem<EntityStore>)new EntityStatsSystems.EntityTrackerRemove(this.entityStatMapComponentType));
        this.getEntityStoreRegistry().registerSystem(new EntityStatsSystems.Changes(this.entityStatMapComponentType));
        this.getEntityStoreRegistry().registerSystem(new EntityStatsSystems.ClearChanges(this.entityStatMapComponentType));
        this.getEventRegistry().register(LoadedAssetsEvent.class, Item.class, x$0 -> onLoadedAssetsInvalidate((LoadedAssetsEvent<Object, JsonAsset, AssetMap>)x$0));
        this.getEventRegistry().register(LoadedAssetsEvent.class, EntityEffect.class, x$0 -> onLoadedAssetsInvalidate((LoadedAssetsEvent<Object, JsonAsset, AssetMap>)x$0));
    }
    
    @Override
    protected void start() {
        DefaultEntityStatTypes.update();
        if (DefaultEntityStatTypes.getHealth() == Integer.MIN_VALUE || DefaultEntityStatTypes.getOxygen() == Integer.MIN_VALUE || DefaultEntityStatTypes.getMana() == Integer.MIN_VALUE || DefaultEntityStatTypes.getStamina() == Integer.MIN_VALUE || DefaultEntityStatTypes.getSignatureEnergy() == Integer.MIN_VALUE || DefaultEntityStatTypes.getAmmo() == Integer.MIN_VALUE) {
            throw new IllegalStateException("Missing default EntityStatType");
        }
    }
    
    @Nullable
    @Deprecated(forRemoval = true)
    public static EntityStatMap get(@Nonnull final Entity entity) {
        final Ref<EntityStore> ref = entity.getReference();
        if (ref == null || !ref.isValid()) {
            return null;
        }
        final Store<EntityStore> store = ref.getStore();
        return store.getComponent(ref, get().getEntityStatMapComponentType());
    }
    
    private void onLoadedAssetsEvent(final LoadedAssetsEvent<String, EntityStatType, IndexedLookupTableAssetMap<String, EntityStatType>> event) {
        DefaultEntityStatTypes.update();
        Universe.get().getWorlds().forEach((s, world) -> world.execute(() -> {
            final Store<EntityStore> store = world.getEntityStore().getStore();
            store.forEachEntityParallel(EntityStatMap.getComponentType(), (index, archetypeChunk, commandBuffer) -> archetypeChunk.getComponent(index, EntityStatMap.getComponentType()).update());
        }));
    }
    
    private static <K, T extends JsonAsset<K>, M extends AssetMap<K, T>> void onLoadedAssetsInvalidate(final LoadedAssetsEvent<K, T, M> event) {
        Universe.get().getWorlds().forEach((s, world) -> world.execute(() -> {
            final Store<EntityStore> store = world.getEntityStore().getStore();
            store.forEachEntityParallel(AllLegacyLivingEntityTypesQuery.INSTANCE, (index, archetypeChunk, commandBuffer) -> {
                final LivingEntity livingEntity = (LivingEntity)EntityUtils.getEntity(index, archetypeChunk);
                if (!EntityStatsModule.$assertionsDisabled && livingEntity == null) {
                    throw new AssertionError();
                }
                else {
                    livingEntity.getStatModifiersManager().setRecalculate(true);
                }
            });
        }));
    }
    
    @Nullable
    public static Int2FloatMap resolveEntityStats(@Nullable final Object2FloatMap<String> raw) {
        if (raw == null || raw.isEmpty()) {
            return null;
        }
        Int2FloatMap out = null;
        for (final Object2FloatMap.Entry<String> entry : raw.object2FloatEntrySet()) {
            final int index = EntityStatType.getAssetMap().getIndex(entry.getKey());
            if (index == Integer.MIN_VALUE) {
                continue;
            }
            if (out == null) {
                out = new Int2FloatOpenHashMap();
            }
            out.put(index, entry.getFloatValue());
        }
        return out;
    }
    
    @Nullable
    public static <T> Int2ObjectMap<T> resolveEntityStats(@Nullable final Map<String, T> raw) {
        if (raw == null || raw.isEmpty()) {
            return null;
        }
        Int2ObjectMap<T> out = null;
        for (final Map.Entry<String, T> entry : raw.entrySet()) {
            final int index = EntityStatType.getAssetMap().getIndex(entry.getKey());
            if (index == Integer.MIN_VALUE) {
                continue;
            }
            if (out == null) {
                out = new Int2ObjectOpenHashMap<T>();
            }
            out.put(index, entry.getValue());
        }
        return out;
    }
    
    @Nullable
    public static int[] resolveEntityStats(@Nullable final String[] raw) {
        if (Arrays.isNullOrEmpty(raw)) {
            return null;
        }
        int[] out = new int[raw.length];
        int size = 0;
        for (int i = 0; i < raw.length; ++i) {
            final int index = EntityStatType.getAssetMap().getIndex(raw[i]);
            if (index != Integer.MIN_VALUE) {
                out[size++] = index;
            }
        }
        if (size != raw.length) {
            out = Arrays.copyOf(out, size);
        }
        return out;
    }
    
    public ComponentType<EntityStore, EntityStatMap> getEntityStatMapComponentType() {
        return this.entityStatMapComponentType;
    }
    
    public SystemType<EntityStore, EntityStatsSystems.StatModifyingSystem> getStatModifyingSystemType() {
        return this.statModifyingSystemType;
    }
    
    static {
        MANIFEST = PluginManifest.corePlugin(EntityStatsModule.class).depends(EntityModule.class).depends(InteractionModule.class).build();
    }
    
    public class PlayerRegenerateStatsSystem extends EntityStatsSystems.Regenerate<Player>
    {
        public PlayerRegenerateStatsSystem(final EntityStatsModule this$0) {
            super(this$0.entityStatMapComponentType, Player.getComponentType());
        }
    }
}
