package gd.rf.adrianvictor.lib;

import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.config.Configuration;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;

/**
 * Utility class for managing plugin configuration files.
 * <p>
 * This class extends {@link ConfigurationEx} to provide custom methods for loading, saving, and managing
 * configuration files. It automatically handles the creation of parent directories and copies default configuration
 * files from the plugin's resources if they do not exist.
 * <p>
 * <b>Note:</b> This class allows for flexible management of multiple configuration files, specified by their file name.
 */
public class ConfigurationEx extends Configuration {

    private final File configFile;
    private Log logger;
    JavaPlugin plugin;

    /**
     * Constructs a new instance of {@code ConfigUtil}.
     *
     * @param plugin   the plugin instance using this configuration utility
     * @param fileName the name of the configuration file to manage (e.g., "config.yml", "settings.yml")
     */
    public ConfigurationEx(JavaPlugin _plugin, String fileName, Log _logger) {
    	super(new File(_plugin.getDataFolder(), fileName));
    	plugin = _plugin;
    	logger = _logger;
        this.configFile = new File(plugin.getDataFolder(), fileName);
    }

    /**
     * Loads the configuration file.
     * <ul>
     * <li>Creates parent directories if they do not exist.</li>
     * <li>Copies the default configuration file from the plugin's resources if the configuration file does not exist.</li>
     * <li>Attempts to load the configuration by calling the superclass' {@code load()} method.</li>
     * <li>Logs errors if the configuration file cannot be loaded.</li>
     * </ul>
     */
    @Override
    public void load() {
        createParentDirectories();

        if (!configFile.exists()) {
            copyDefaultConfig();
        }

        try {
            super.load();
        } catch (Exception e) {
            logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
        }
    }

    /**
     * Creates the parent directories for the configuration file if they do not exist.
     * <p>
     * Logs an error if the directories cannot be created.
     */
    private void createParentDirectories() {
        try {
            Files.createDirectories(configFile.getParentFile().toPath());
        } catch (IOException e) {
            logger.severe(String.format("Failed to generate default config directory: %s", e.getMessage()));
        }
    }

    /**
     * Copies the default configuration file from the plugin's resources to the target location.
     * <p>
     * This method looks for a file in the plugin's resources with the same name as the configuration file being managed.
     * If found, it copies this file to the plugin's data folder.
     * <p>
     * Logs an error if the default configuration file cannot be found or copied.
     */
    private void copyDefaultConfig() {
        // Load the config from the JAR directly (it is located at the root level)
        String resourcePath = "/" + configFile.getName(); // Root path of JAR

        try (InputStream input = plugin.getClass().getResourceAsStream(resourcePath)) {
            if (input == null) {
                logger.severe(String.format("Default config '%s' wasn't found in the JAR.", configFile.getName()));
                return;
            }

            Files.copy(input, configFile.toPath());
            if (Files.exists(configFile.toPath())) {
                logger.info(String.format("Default config '%s' generated successfully.", configFile.getName()));
            } else {
                logger.warning("We tried to generate the default config file, but it was not found even after the creation. Maybe your permissions are broken?");
            }
        } catch (IOException e) {
            logger.severe(String.format("Failed to generate default config '%s': %s", configFile.getName(), e.getMessage()));
        }
    }

    /**
     * Loads the configuration file and logs the result.
     * <p>
     * Logs a message indicating whether the configuration was loaded successfully.
     */
    public void loadConfig() {
        try {
            this.load();
            logger.info(String.format("Config '%s' loaded successfully.", configFile.getName()));
        } catch (Exception e) {
        	logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
        }
    }

    /**
     * Saves the configuration file and logs the result.
     * <p>
     * Logs a message indicating whether the configuration was saved successfully.
     */
    public void saveConfig() {
        try {
            this.save();
            logger.info(String.format("Config '%s' saved successfully.", configFile.getName()));
        } catch (Exception e) {
        	logger.severe(String.format("Failed to save config '%s': %s", configFile.getName(), e.getMessage()));
        }
    }

    /**
     * Returns the configuration file managed by this utility.
     *
     * @return the configuration file
     */
    public File getConfig() {
        return configFile;
    }
}