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

package com.hypixel.hytale.builtin.path;

import com.hypixel.hytale.component.system.EcsEvent;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.dependency.SystemDependency;
import com.hypixel.hytale.component.dependency.OrderPriority;
import com.hypixel.hytale.component.dependency.Order;
import com.hypixel.hytale.component.dependency.Dependency;
import java.util.Set;
import com.hypixel.hytale.server.core.prefab.event.PrefabPasteEvent;
import com.hypixel.hytale.component.system.WorldEventSystem;
import com.hypixel.hytale.codec.Codec;
import java.util.function.Predicate;
import com.hypixel.hytale.component.spatial.SpatialStructure;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.server.core.HytaleServerConfig;
import java.util.logging.Level;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.server.core.command.system.CommandRegistry;
import com.hypixel.hytale.component.spatial.KDTree;
import com.hypixel.hytale.codec.DirectDecodeCodec;
import com.hypixel.hytale.builtin.path.entities.PatrolPathMarkerEntity;
import com.hypixel.hytale.component.system.ISystem;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.assetstore.event.LoadedAssetsEvent;
import com.hypixel.hytale.builtin.path.commands.WorldPathCommand;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.builtin.path.commands.PrefabPathCommand;
import com.hypixel.hytale.builtin.buildertools.BuilderToolsPlugin;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;

public class PathPlugin extends JavaPlugin
{
    public static final KeyedCodec<String> PATH_MARKER_MODEL;
    public static final String DEFAULT_PATH_MARKER_MODEL = "NPC_Path_Marker";
    private static PathPlugin instance;
    private ResourceType<EntityStore, WorldPathData> worldPathDataResourceType;
    private ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> prefabPathSpatialResource;
    private ComponentType<EntityStore, WorldPathBuilder> worldPathBuilderComponentType;
    private Model pathMarkerModel;
    
    public static PathPlugin get() {
        return PathPlugin.instance;
    }
    
    public PathPlugin(@Nonnull final JavaPluginInit init) {
        super(init);
    }
    
    @Override
    protected void setup() {
        PathPlugin.instance = this;
        final CommandRegistry commandRegistry = this.getCommandRegistry();
        final EventRegistry eventRegistry = this.getEventRegistry();
        final ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
        if (BuilderToolsPlugin.get().isEnabled()) {
            commandRegistry.registerCommand(new PrefabPathCommand());
        }
        commandRegistry.registerCommand(new WorldPathCommand());
        eventRegistry.register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelsChanged);
        entityStoreRegistry.registerSystem(new PrefabPasteEventSystem());
        this.getEntityRegistry().registerEntity("PatrolPathMarker", PatrolPathMarkerEntity.class, PatrolPathMarkerEntity::new, PatrolPathMarkerEntity.CODEC);
        this.worldPathDataResourceType = entityStoreRegistry.registerResource(WorldPathData.class, WorldPathData::new);
        this.prefabPathSpatialResource = entityStoreRegistry.registerSpatialResource(() -> new KDTree(Ref::isValid));
        this.worldPathBuilderComponentType = entityStoreRegistry.registerComponent(WorldPathBuilder.class, () -> {
            throw new UnsupportedOperationException("Not implemented");
        });
        entityStoreRegistry.registerSystem(new PrefabPathSystems.AddOrRemove());
        entityStoreRegistry.registerSystem(new PrefabPathSystems.AddedFromWorldGen());
        entityStoreRegistry.registerSystem(new PathSpatialSystem(this.prefabPathSpatialResource));
        entityStoreRegistry.registerSystem(new PrefabPathSystems.NameplateHolderSystem());
        entityStoreRegistry.registerSystem((ISystem<EntityStore>)new PrefabPathSystems.NameplateRefChangeSystem());
        entityStoreRegistry.registerSystem((ISystem<EntityStore>)new PrefabPathSystems.WorldGenChangeSystem());
        entityStoreRegistry.registerSystem(new PrefabPathSystems.PrefabPlaceEntityEventSystem());
    }
    
    @Override
    protected void start() {
        final HytaleServerConfig.Module config = HytaleServer.get().getConfig().getModule("PathPlugin");
        final String pathMarkerModelId = config.getData(PathPlugin.PATH_MARKER_MODEL).orElse("NPC_Path_Marker");
        final DefaultAssetMap<String, ModelAsset> modelAssetMap = ModelAsset.getAssetMap();
        ModelAsset modelAsset = modelAssetMap.getAsset(pathMarkerModelId);
        if (modelAsset == null) {
            this.getLogger().at(Level.SEVERE).log("Path marker model %s does not exist");
            modelAsset = modelAssetMap.getAsset("NPC_Path_Marker");
            if (modelAsset == null) {
                throw new IllegalStateException(String.format("Default path marker '%s' not found", "NPC_Path_Marker"));
            }
        }
        this.pathMarkerModel = Model.createUnitScaleModel(modelAsset);
    }
    
    public ResourceType<EntityStore, WorldPathData> getWorldPathDataResourceType() {
        return this.worldPathDataResourceType;
    }
    
    public ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> getPrefabPathSpatialResource() {
        return this.prefabPathSpatialResource;
    }
    
    public ComponentType<EntityStore, WorldPathBuilder> getWorldPathBuilderComponentType() {
        return this.worldPathBuilderComponentType;
    }
    
    public Model getPathMarkerModel() {
        return this.pathMarkerModel;
    }
    
    protected void onModelsChanged(@Nonnull final LoadedAssetsEvent<String, ModelAsset, DefaultAssetMap<String, ModelAsset>> event) {
        if (this.pathMarkerModel == null) {
            return;
        }
        final ModelAsset modelAsset = event.getLoadedAssets().get(this.pathMarkerModel.getModelAssetId());
        if (modelAsset == null) {
            return;
        }
        this.pathMarkerModel = Model.createUnitScaleModel(modelAsset);
    }
    
    static {
        PATH_MARKER_MODEL = new KeyedCodec<String>("PathMarkerModel", Codec.STRING);
    }
    
    private static class PrefabPasteEventSystem extends WorldEventSystem<EntityStore, PrefabPasteEvent>
    {
        @Nonnull
        private final Set<Dependency<EntityStore>> dependencies;
        
        protected PrefabPasteEventSystem() {
            super(PrefabPasteEvent.class);
            this.dependencies = (Set<Dependency<EntityStore>>)Set.of(new SystemDependency(Order.AFTER, BuilderToolsPlugin.PrefabPasteEventSystem.class, OrderPriority.CLOSEST));
        }
        
        @Override
        public void handle(@Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final PrefabPasteEvent event) {
            if (event.isPasteStart()) {
                return;
            }
            final ConcurrentHashMap<UUID, UUID> pastedPrefabPathUUIDMap = BuilderToolsPlugin.get().getPastedPrefabPathUUIDMap().get(event.getPrefabId());
            if (pastedPrefabPathUUIDMap == null) {
                return;
            }
            final WorldPathData worldPathDataResource = store.getResource(WorldPathData.getResourceType());
            for (final UUID value : pastedPrefabPathUUIDMap.values()) {
                worldPathDataResource.compactPrefabPath(0, value);
            }
        }
        
        @Nonnull
        @Override
        public Set<Dependency<EntityStore>> getDependencies() {
            return this.dependencies;
        }
    }
}
