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

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

import java.util.Map;
import java.util.Objects;
import com.hypixel.hytale.component.ComponentAccessor;
import java.util.function.Consumer;
import com.hypixel.hytale.server.core.event.events.ecs.BreakBlockEvent;
import java.util.Iterator;
import com.hypixel.hytale.server.core.event.events.ecs.DamageBlockEvent;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.npc.blackboard.view.interaction.InteractionView;
import com.hypixel.hytale.server.npc.blackboard.view.attitude.AttitudeView;
import com.hypixel.hytale.server.npc.blackboard.view.resource.ResourceViewManager;
import com.hypixel.hytale.server.npc.blackboard.view.resource.ResourceView;
import com.hypixel.hytale.server.npc.blackboard.view.event.entity.EntityEventView;
import com.hypixel.hytale.server.npc.blackboard.view.SingletonBlackboardViewManager;
import com.hypixel.hytale.server.npc.blackboard.view.event.block.BlockEventView;
import com.hypixel.hytale.server.npc.blackboard.view.blocktype.BlockTypeViewManager;
import com.hypixel.hytale.server.npc.blackboard.view.blocktype.BlockTypeView;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.server.npc.blackboard.view.IBlackboardViewManager;
import com.hypixel.hytale.server.npc.blackboard.view.IBlackboardView;
import java.util.concurrent.ConcurrentHashMap;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Resource;

public class Blackboard implements Resource<EntityStore>
{
    public static final HytaleLogger LOGGER;
    private final ConcurrentHashMap<Class<? extends IBlackboardView<?>>, IBlackboardViewManager<?>> views;
    
    public Blackboard() {
        this.views = new ConcurrentHashMap<Class<? extends IBlackboardView<?>>, IBlackboardViewManager<?>>();
    }
    
    public static ResourceType<EntityStore, Blackboard> getResourceType() {
        return NPCPlugin.get().getBlackboardResourceType();
    }
    
    public void init(@Nonnull final World world) {
        this.registerViewType(BlockTypeView.class, new BlockTypeViewManager());
        this.registerViewType((Class<IBlackboardView<BlockEventView>>)BlockEventView.class, new SingletonBlackboardViewManager<IBlackboardView<BlockEventView>>(new BlockEventView(world)));
        this.registerViewType((Class<IBlackboardView<EntityEventView>>)EntityEventView.class, new SingletonBlackboardViewManager<IBlackboardView<EntityEventView>>(new EntityEventView(world)));
        this.registerViewType(ResourceView.class, new ResourceViewManager());
        this.registerViewType((Class<IBlackboardView<AttitudeView>>)AttitudeView.class, new SingletonBlackboardViewManager<IBlackboardView<AttitudeView>>(new AttitudeView(world)));
        this.registerViewType((Class<IBlackboardView<InteractionView>>)InteractionView.class, new SingletonBlackboardViewManager<IBlackboardView<InteractionView>>(new InteractionView(world)));
    }
    
    public void onEntityDamageBlock(@Nonnull final Ref<EntityStore> ref, @Nonnull final DamageBlockEvent event) {
        for (final IBlackboardViewManager<?> manager : this.views.values()) {
            manager.forEachView(view -> {
                if (view instanceof final BlockEventView blockEventView) {
                    blockEventView.onEntityDamageBlock(ref, event);
                }
            });
        }
    }
    
    public void onEntityBreakBlock(@Nonnull final Ref<EntityStore> ref, @Nonnull final BreakBlockEvent event) {
        for (final IBlackboardViewManager<?> manager : this.views.values()) {
            manager.forEachView(view -> {
                if (view instanceof final BlockEventView blockEventView) {
                    blockEventView.onEntityBreakBlock(ref, event);
                }
            });
        }
    }
    
    private <View extends IBlackboardView<View>> void registerViewType(@Nonnull final Class<View> clazz, @Nonnull final IBlackboardViewManager<View> holder) {
        this.views.put(clazz, holder);
    }
    
    public void cleanupViews() {
        this.views.forEach((clazz, manager) -> manager.cleanup());
    }
    
    public void clear() {
        this.views.forEach((clazz, manager) -> manager.clear());
    }
    
    public void onWorldRemoved() {
        this.views.forEach((clazz, manager) -> manager.onWorldRemoved());
    }
    
    public <View extends IBlackboardView<View>> void forEachView(final Class<View> viewTypeClass, final Consumer<View> consumer) {
        this.getViewManager(viewTypeClass).forEachView(consumer);
    }
    
    public <View extends IBlackboardView<View>> View getView(final Class<View> viewTypeClass, final Ref<EntityStore> ref, final ComponentAccessor<EntityStore> componentAccessor) {
        return this.getViewManager(viewTypeClass).get(ref, this, componentAccessor);
    }
    
    public <View extends IBlackboardView<View>> View getView(final Class<View> viewTypeClass, final int chunkX, final int chunkZ) {
        return this.getViewManager(viewTypeClass).get(chunkX, chunkZ, this);
    }
    
    public <View extends IBlackboardView<View>> View getView(final Class<View> viewTypeClass, final long index) {
        return this.getViewManager(viewTypeClass).get(index, this);
    }
    
    public <View extends IBlackboardView<View>> View getIfExists(final Class<View> viewTypeClass, final long index) {
        return this.getViewManager(viewTypeClass).getIfExists(index);
    }
    
    @Nonnull
    private <View extends IBlackboardView<View>> IBlackboardViewManager<View> getViewManager(final Class<View> viewTypeClass) {
        return Objects.requireNonNull(this.views.get(viewTypeClass), "View type manager not registered!");
    }
    
    @Nonnull
    @Override
    public Resource<EntityStore> clone() {
        final Blackboard blackboard = new Blackboard();
        blackboard.views.putAll(this.views);
        return blackboard;
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
