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

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

import java.util.function.Consumer;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.npc.blackboard.Blackboard;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.util.ChunkUtil;
import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
import javax.annotation.Nonnull;
import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;

public abstract class BlockRegionViewManager<Type extends BlockRegionView<Type>> implements IBlackboardViewManager<Type>
{
    @Nonnull
    protected Long2ObjectConcurrentHashMap<Type> views;
    @Nonnull
    protected LongArrayFIFOQueue removalQueue;
    
    public BlockRegionViewManager() {
        this.views = new Long2ObjectConcurrentHashMap<Type>(true, ChunkUtil.NOT_FOUND);
        this.removalQueue = new LongArrayFIFOQueue();
    }
    
    @Override
    public Type get(@Nonnull final Ref<EntityStore> ref, final Blackboard blackboard, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final TransformComponent transformComponent = componentAccessor.getComponent(ref, TransformComponent.getComponentType());
        assert transformComponent != null;
        return this.get(transformComponent.getPosition(), blackboard);
    }
    
    @Override
    public Type get(@Nonnull final Vector3d position, final Blackboard blackboard) {
        final long index = BlockRegionView.indexViewFromWorldPosition(position);
        return this.get(index, blackboard);
    }
    
    @Override
    public Type get(final int chunkX, final int chunkZ, final Blackboard blackboard) {
        final long index = BlockRegionView.indexViewFromChunkCoordinates(chunkX, chunkZ);
        return this.get(index, blackboard);
    }
    
    @Override
    public Type get(final long index, final Blackboard blackboard) {
        Type view = this.views.getOrDefault(index, null);
        if (view == null) {
            view = this.createView(index, blackboard);
            this.views.put(index, view);
        }
        return view;
    }
    
    protected abstract Type createView(final long p0, final Blackboard p1);
    
    @Override
    public Type getIfExists(final long index) {
        return this.views.get(index);
    }
    
    @Override
    public void cleanup() {
        this.views.forEach((index, entry, viewManager) -> {
            if (viewManager.shouldCleanup(entry)) {
                viewManager.removalQueue.enqueue(index);
            }
            return;
        }, this);
        while (!this.removalQueue.isEmpty()) {
            this.views.remove(this.removalQueue.dequeueLong());
        }
    }
    
    protected abstract boolean shouldCleanup(final Type p0);
    
    @Override
    public void onWorldRemoved() {
    }
    
    @Override
    public void forEachView(@Nonnull final Consumer<Type> consumer) {
        this.views.forEach((index, view) -> consumer.accept(view));
    }
    
    @Override
    public void clear() {
        this.views.clear();
    }
}
