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

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

import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.server.core.modules.physics.component.Velocity;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.DisableProcessingAssert;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import com.hypixel.hytale.server.core.asset.type.projectile.config.Projectile;
import com.hypixel.hytale.math.shape.Box;
import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.system.HolderSystem;
import com.hypixel.hytale.component.RemoveReason;
import java.util.logging.Level;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.entity.entities.ProjectileComponent;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.system.RefSystem;
import javax.annotation.Nonnull;
import com.hypixel.hytale.logger.HytaleLogger;

public class LegacyProjectileSystems
{
    @Nonnull
    private static final HytaleLogger LOGGER;
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
    
    public static class OnAddRefSystem extends RefSystem<EntityStore>
    {
        @Nonnull
        private static final ComponentType<EntityStore, ProjectileComponent> PROJECTILE_COMPONENT_TYPE;
        
        @Override
        public Query<EntityStore> getQuery() {
            return OnAddRefSystem.PROJECTILE_COMPONENT_TYPE;
        }
        
        @Override
        public void onEntityAdded(@Nonnull final Ref<EntityStore> ref, @Nonnull final AddReason reason, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
            final ProjectileComponent projectileComponent = commandBuffer.getComponent(ref, OnAddRefSystem.PROJECTILE_COMPONENT_TYPE);
            assert projectileComponent != null;
            if (projectileComponent.getProjectile() == null) {
                LegacyProjectileSystems.LOGGER.at(Level.WARNING).log("Removing projectile entity %s as it failed to initialize correctly!", ref);
                commandBuffer.removeEntity(ref, RemoveReason.REMOVE);
            }
        }
        
        @Override
        public void onEntityRemove(@Nonnull final Ref<EntityStore> ref, @Nonnull final RemoveReason reason, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
        }
        
        static {
            PROJECTILE_COMPONENT_TYPE = ProjectileComponent.getComponentType();
        }
    }
    
    public static class OnAddHolderSystem extends HolderSystem<EntityStore>
    {
        @Nonnull
        private static final ComponentType<EntityStore, ProjectileComponent> PROJECTILE_COMPONENT_TYPE;
        
        @Override
        public void onEntityAdd(@Nonnull final Holder<EntityStore> holder, @Nonnull final AddReason reason, @Nonnull final Store<EntityStore> store) {
            if (!holder.getArchetype().contains(NetworkId.getComponentType())) {
                holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
            }
            final ProjectileComponent projectileComponent = holder.getComponent(OnAddHolderSystem.PROJECTILE_COMPONENT_TYPE);
            assert projectileComponent != null;
            projectileComponent.initialize();
            final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(projectileComponent.getAppearance());
            BoundingBox boundingBox;
            if (modelAsset != null) {
                final Model model = Model.createUnitScaleModel(modelAsset);
                holder.putComponent(ModelComponent.getComponentType(), new ModelComponent(model));
                holder.putComponent(PersistentModel.getComponentType(), new PersistentModel(model.toReference()));
                boundingBox = new BoundingBox(model.getBoundingBox());
            }
            else {
                final Projectile projectileAsset = projectileComponent.getProjectile();
                if (projectileAsset != null) {
                    boundingBox = new BoundingBox(Box.horizontallyCentered(projectileAsset.getRadius(), projectileAsset.getHeight(), projectileAsset.getRadius()));
                }
                else {
                    boundingBox = new BoundingBox(Box.horizontallyCentered(0.25, 0.25, 0.25));
                }
            }
            holder.putComponent(BoundingBox.getComponentType(), boundingBox);
            projectileComponent.initializePhysics(boundingBox);
        }
        
        @Override
        public void onEntityRemoved(@Nonnull final Holder<EntityStore> holder, @Nonnull final RemoveReason reason, @Nonnull final Store<EntityStore> store) {
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return OnAddHolderSystem.PROJECTILE_COMPONENT_TYPE;
        }
        
        static {
            PROJECTILE_COMPONENT_TYPE = ProjectileComponent.getComponentType();
        }
    }
    
    public static class TickingSystem extends EntityTickingSystem<EntityStore> implements DisableProcessingAssert
    {
        @Nonnull
        private static final HytaleLogger LOGGER;
        @Nonnull
        private final ComponentType<EntityStore, TransformComponent> transformComponentType;
        @Nonnull
        private final ComponentType<EntityStore, Velocity> velocityComponentType;
        @Nonnull
        private final ComponentType<EntityStore, BoundingBox> boundingBoxComponentType;
        @Nonnull
        private final ComponentType<EntityStore, ProjectileComponent> projectileComponentType;
        @Nonnull
        private final Archetype<EntityStore> archetype;
        
        public TickingSystem(@Nonnull final ComponentType<EntityStore, ProjectileComponent> projectileComponentType, @Nonnull final ComponentType<EntityStore, TransformComponent> transformComponentType, @Nonnull final ComponentType<EntityStore, Velocity> velocityComponentType, @Nonnull final ComponentType<EntityStore, BoundingBox> boundingBoxComponentType) {
            this.projectileComponentType = projectileComponentType;
            this.velocityComponentType = velocityComponentType;
            this.boundingBoxComponentType = boundingBoxComponentType;
            this.transformComponentType = transformComponentType;
            this.archetype = Archetype.of(projectileComponentType, transformComponentType, velocityComponentType, boundingBoxComponentType);
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return this.archetype;
        }
        
        @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 TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType);
            assert transformComponent != null;
            final ProjectileComponent projectileComponent = archetypeChunk.getComponent(index, this.projectileComponentType);
            assert projectileComponent != null;
            final Velocity velocityComponent = archetypeChunk.getComponent(index, this.velocityComponentType);
            assert velocityComponent != null;
            final BoundingBox boundingBox = archetypeChunk.getComponent(index, this.boundingBoxComponentType);
            final Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
            try {
                if (projectileComponent.consumeDeadTimer(dt)) {
                    projectileComponent.onProjectileDeath(ref, transformComponent.getPosition(), commandBuffer);
                    commandBuffer.removeEntity(ref, RemoveReason.REMOVE);
                    return;
                }
                final World world = commandBuffer.getExternalData().getWorld();
                projectileComponent.getSimplePhysicsProvider().tick(dt, velocityComponent, world, transformComponent, ref, commandBuffer);
            }
            catch (final Throwable throwable) {
                TickingSystem.LOGGER.at(Level.SEVERE).withCause(throwable).log("Exception while ticking entity! Removing!! %s", projectileComponent);
                commandBuffer.removeEntity(ref, RemoveReason.REMOVE);
            }
        }
        
        static {
            LOGGER = HytaleLogger.forEnclosingClass();
        }
    }
}
