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

package com.hypixel.hytale.server.flock;

import com.hypixel.hytale.component.system.EcsEvent;
import javax.annotation.Nullable;
import com.hypixel.hytale.protocol.GameMode;
import com.hypixel.hytale.server.core.event.events.ecs.ChangeGameModeEvent;
import com.hypixel.hytale.component.system.EntityEventSystem;
import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
import java.util.Iterator;
import java.util.UUID;
import java.util.logging.Level;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.AddReason;
import javax.annotation.Nonnull;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.server.core.entity.group.EntityGroup;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.system.RefSystem;

public class FlockSystems
{
    public static class EntityRemoved extends RefSystem<EntityStore>
    {
        private final ComponentType<EntityStore, UUIDComponent> flockIdComponentType;
        private final ComponentType<EntityStore, EntityGroup> entityGroupComponentType;
        private final ComponentType<EntityStore, Flock> flockComponentType;
        private final Archetype<EntityStore> archetype;
        
        public EntityRemoved(final ComponentType<EntityStore, Flock> flockComponentType) {
            this.flockIdComponentType = UUIDComponent.getComponentType();
            this.entityGroupComponentType = EntityGroup.getComponentType();
            this.flockComponentType = flockComponentType;
            this.archetype = Archetype.of(this.flockIdComponentType, this.entityGroupComponentType, flockComponentType);
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return this.archetype;
        }
        
        @Override
        public void onEntityAdded(@Nonnull final Ref<EntityStore> ref, @Nonnull final AddReason reason, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
        }
        
        @Override
        public void onEntityRemove(@Nonnull final Ref<EntityStore> ref, @Nonnull final RemoveReason reason, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
            final UUID flockId = store.getComponent(ref, this.flockIdComponentType).getUuid();
            final EntityGroup entityGroup = store.getComponent(ref, this.entityGroupComponentType);
            final Flock flock = store.getComponent(ref, this.flockComponentType);
            switch (reason) {
                case REMOVE: {
                    entityGroup.setDissolved(true);
                    for (final Ref<EntityStore> memberRef : entityGroup.getMemberList()) {
                        commandBuffer.removeComponent(memberRef, FlockMembership.getComponentType());
                        final TransformComponent transformComponent = commandBuffer.getComponent(memberRef, TransformComponent.getComponentType());
                        assert transformComponent != null;
                        transformComponent.markChunkDirty(commandBuffer);
                    }
                    flock.setRemovedStatus(Flock.FlockRemovedStatus.DISSOLVED);
                    entityGroup.clear();
                    if (flock.isTrace()) {
                        FlockPlugin.get().getLogger().at(Level.INFO).log("Flock %s: Dissolving", flockId);
                        break;
                    }
                    break;
                }
                case UNLOAD: {
                    flock.setRemovedStatus(Flock.FlockRemovedStatus.UNLOADED);
                    entityGroup.clear();
                    if (flock.isTrace()) {
                        FlockPlugin.get().getLogger().at(Level.INFO).log("Flock %s: Flock unloaded, size=%s", flockId, entityGroup.size());
                        break;
                    }
                    break;
                }
            }
        }
    }
    
    public static class Ticking extends EntityTickingSystem<EntityStore>
    {
        private final ComponentType<EntityStore, Flock> flockComponentType;
        
        public Ticking(final ComponentType<EntityStore, Flock> flockComponentType) {
            this.flockComponentType = flockComponentType;
        }
        
        @Override
        public Query<EntityStore> getQuery() {
            return this.flockComponentType;
        }
        
        @Override
        public boolean isParallel(final int archetypeChunkSize, final int taskCount) {
            return EntityTickingSystem.maybeUseParallel(archetypeChunkSize, taskCount);
        }
        
        @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 Flock flock = archetypeChunk.getComponent(index, this.flockComponentType);
            flock.swapDamageDataBuffers();
        }
    }
    
    public static class PlayerChangeGameModeEventSystem extends EntityEventSystem<EntityStore, ChangeGameModeEvent>
    {
        public PlayerChangeGameModeEventSystem() {
            super(ChangeGameModeEvent.class);
        }
        
        @Override
        public void handle(final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final ChangeGameModeEvent event) {
            if (event.getGameMode() == GameMode.Adventure) {
                return;
            }
            final Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
            commandBuffer.tryRemoveComponent(ref, FlockMembership.getComponentType());
        }
        
        @Nullable
        @Override
        public Query<EntityStore> getQuery() {
            return (Query<EntityStore>)Archetype.empty();
        }
    }
}
