package io.papermc.paper.plugin.storage;

import io.papermc.paper.plugin.entrypoint.strategy.LegacyPluginLoadingStrategy;
import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy;
import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException;
import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public abstract class ConfiguredProviderStorage<T> extends SimpleProviderStorage<T> {

    private static final Logger LOGGER = Logger.getLogger("ConfiguredOrderedProviderStorage");
    public static final boolean LEGACY_PLUGIN_LOADING = Boolean.getBoolean("paper.useLegacyPluginLoading");

    protected ConfiguredProviderStorage(ProviderConfiguration<T> onLoad) {
        // This doesn't work with reloading.
        // Should we care?
        super(LEGACY_PLUGIN_LOADING ? new LegacyPluginLoadingStrategy<>(onLoad) : new ModernPluginLoadingStrategy<>(onLoad));
    }

    @Override
    protected void handleCycle(PluginGraphCycleException exception) {
        List<String> logMessages = new ArrayList<>();
        for (List<String> list : exception.getCycles()) {
            logMessages.add(String.join(" -> ", list) + " -> " + list.get(0));
        }

        LOGGER.log(Level.SEVERE, "Circular dependencies detected! This happens when");
        LOGGER.log(Level.SEVERE, "  i) plugin A has a plugin B in its (soft)depend list, and plugin B has plugin A in its (soft)depend list, or");
        LOGGER.log(Level.SEVERE, "  ii) plugin A has plugin B both in its (soft)depend list and its loadbefore list.");
        LOGGER.log(Level.SEVERE, "Circular dependencies:");
        for (String logMessage : logMessages) {
            LOGGER.log(Level.SEVERE, "  " + logMessage);
        }
        LOGGER.log(Level.SEVERE, "Please report this to the plugin authors of the first plugin of each loop or join the PaperMC Discord server for further help.");
        LOGGER.log(Level.SEVERE, "If you would like to still load these plugins, acknowledging that there may be unexpected plugin loading issues, run the server with -Dpaper.useLegacyPluginLoading=true");

        if (this.exitOnCycleDependencies()) {
            throw new IllegalStateException("Circular plugin dependencies from plugins " + exception.getCycles().stream().map(cycle -> cycle.get(0)).collect(Collectors.joining(", ")));
        }
    }

    public boolean exitOnCycleDependencies() {
        return true;
    }

}
