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

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

import com.hypixel.hytale.component.ComponentAccessor;
import java.util.function.Consumer;
import com.hypixel.hytale.function.consumer.IntObjectConsumer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.event.IEventRegistry;
import java.util.List;
import com.hypixel.hytale.function.consumer.BooleanConsumer;
import java.util.concurrent.CopyOnWriteArrayList;
import com.hypixel.hytale.server.npc.NPCPlugin;
import java.util.EnumMap;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import javax.annotation.Nullable;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.server.core.universe.world.World;
import javax.annotation.Nonnull;
import java.util.Map;
import com.hypixel.hytale.server.npc.blackboard.view.IBlackboardView;

public abstract class EventView<ViewType extends IBlackboardView<ViewType>, EventType extends Enum<EventType>, NotificationType extends EventNotification> implements IBlackboardView<ViewType>
{
    @Nonnull
    protected final Map<EventType, EventTypeRegistration<EventType, NotificationType>> entityMapsByEventType;
    @Nonnull
    protected final World world;
    protected final EventType[] eventTypes;
    @Nullable
    protected EventRegistry eventRegistry;
    @Nullable
    protected ComponentRegistryProxy<EntityStore> entityStoreRegistry;
    protected boolean shutdown;
    protected final NotificationType reusableEventNotification;
    
    protected EventView(final Class<EventType> type, final EventType[] eventTypes, final NotificationType reusableEventNotification, @Nonnull final World world) {
        this.entityMapsByEventType = new EnumMap<EventType, EventTypeRegistration<EventType, NotificationType>>(type);
        this.eventTypes = eventTypes;
        this.reusableEventNotification = reusableEventNotification;
        this.world = world;
        this.entityStoreRegistry = NPCPlugin.get().getEntityStoreRegistry();
        this.eventRegistry = new EventRegistry(new CopyOnWriteArrayList<BooleanConsumer>(), () -> !this.shutdown, String.format("EventView for world %s is not enabled!", world.getName()), NPCPlugin.get().getEventRegistry());
    }
    
    @Override
    public boolean isOutdated(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        return false;
    }
    
    @Override
    public void onWorldRemoved() {
        this.shutdown = true;
        if (this.eventRegistry != null) {
            this.eventRegistry.shutdown();
            this.eventRegistry = null;
        }
    }
    
    @Override
    public void cleanup() {
        for (final EventType eventType : this.eventTypes) {
            this.entityMapsByEventType.get(eventType).cleanup();
        }
    }
    
    public int getSetCount() {
        int count = 0;
        for (final EventType type : this.eventTypes) {
            count += this.entityMapsByEventType.get(type).getSetCount();
        }
        return count;
    }
    
    public void forEach(@Nonnull final IntObjectConsumer<EventType> setConsumer, @Nonnull final Consumer<Ref<EntityStore>> npcConsumer) {
        for (final EventType eventType : this.eventTypes) {
            this.entityMapsByEventType.get(eventType).forEach(setConsumer, npcConsumer);
        }
    }
    
    protected void onEvent(final int senderTypeId, final double x, final double y, final double z, final Ref<EntityStore> initiator, final Ref<EntityStore> skip, @Nonnull final ComponentAccessor<EntityStore> componentAccessor, final EventType type) {
        this.reusableEventNotification.setPosition(x, y, z);
        this.reusableEventNotification.setInitiator(initiator);
        this.entityMapsByEventType.get(type).relayEvent(senderTypeId, (EventNotification)this.reusableEventNotification, (Ref)skip, (ComponentAccessor)componentAccessor);
    }
}
