package net.apunch.blacksmith.config;

import net.apunch.blacksmith.BlacksmithPlugin;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.YamlStorage;

import java.io.File;

/**
 * A class which keeps track of all Blacksmith settings/config values
 */
public class Settings {

    private String busyWithPlayerMessage = Setting.BUSY_WITH_PLAYER_MESSAGE.asString();
    private String busyReforgingMessage = Setting.BUSY_WITH_REFORGE_MESSAGE.asString();
    private String costMessage = Setting.COST_MESSAGE.asString();
    private String invalidItemMessage = Setting.INVALID_ITEM_MESSAGE.asString();
    private String startReforgeMessage = Setting.START_REFORGE_MESSAGE.asString();
    private String successMessage = Setting.SUCCESS_MESSAGE.asString();
    private String failMessage = Setting.FAIL_MESSAGE.asString();
    private String insufficientFundsMessage = Setting.INSUFFICIENT_FUNDS_MESSAGE.asString();
    private String coolDownUnexpiredMessage = Setting.COOL_DOWN_UNEXPIRED_MESSAGE.asString();
    private String itemChangedMessage = Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.asString();
    private int minReforgeDelay = Setting.MIN_REFORGE_DELAY.asInt();
    private int maxReforgeDelay = Setting.MAX_REFORGE_DELAY.asInt();
    private int reforgeCoolDown = Setting.REFORGE_COOL_DOWN.asInt();
    private int failChance = Setting.FAIL_CHANCE.asInt();
    private int extraEnchantmentChance = Setting.EXTRA_ENCHANTMENT_CHANCE.asInt();
    private int maxEnchantments = Setting.MAX_ENCHANTMENTS.asInt();
    private boolean dropItem = Setting.DROP_ITEM.asBoolean();
    private boolean disableCoolDown = Setting.DISABLE_COOL_DOWN.asBoolean();
    private boolean disableDelay = Setting.DISABLE_DELAY.asBoolean();
    private boolean naturalCost = Setting.NATURAL_COST.asBoolean();
    private final YamlStorage config;

    /**
     * Instantiates a new "Settings"
     *
     * @param plugin <p>A reference to the blacksmith plugin</p>
     */
    public Settings(BlacksmithPlugin plugin) {
        config = new YamlStorage(new File(plugin.getDataFolder() + File.separator + "config.yml"),
                "Blacksmith Configuration\nWarning: The values under defaults are the values set for a blacksmith" +
                        "upon creation. To change any values for existing NPCs, edit the citizens NPC file.");
    }

    /**
     * Loads all configuration values from the config file
     */
    public void load() {
        //Load the config from disk
        config.load();
        DataKey root = config.getKey("");
        for (Setting setting : Setting.values()) {
            if (!root.keyExists(setting.getPath())) {
                //If the setting does not exist in the config file, add it
                root.setRaw(setting.getPath(), setting.get());
            } else {
                //Set the setting to the value found in the path
                setting.set(root.getRaw(setting.getPath()));
            }
        }
        //Save any modified values to disk
        config.save();
    }

    /**
     * Gets the configuration used for saving/loading from disk
     *
     * @return <p>The configuration</p>
     */
    public YamlStorage getConfig() {
        return config;
    }

    /**
     * Loads variables from the given data key
     *
     * @param key <p>The data key to load variables from</p>
     */
    public void loadVariables(DataKey key) {
        // Override defaults if they exist
        if (key.keyExists(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath())) {
            busyWithPlayerMessage = key.getString(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath())) {
            busyReforgingMessage = key.getString(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.COST_MESSAGE.getChildPath())) {
            costMessage = key.getString(Setting.COST_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.INVALID_ITEM_MESSAGE.getChildPath())) {
            invalidItemMessage = key.getString(Setting.INVALID_ITEM_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.START_REFORGE_MESSAGE.getChildPath())) {
            startReforgeMessage = key.getString(Setting.START_REFORGE_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.SUCCESS_MESSAGE.getChildPath())) {
            successMessage = key.getString(Setting.SUCCESS_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.FAIL_MESSAGE.getChildPath())) {
            failMessage = key.getString(Setting.FAIL_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath())) {
            insufficientFundsMessage = key.getString(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath())) {
            coolDownUnexpiredMessage = key.getString(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath())) {
            itemChangedMessage = key.getString(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath());
        }
        if (key.keyExists(Setting.MIN_REFORGE_DELAY.getChildPath())) {
            minReforgeDelay = key.getInt(Setting.MIN_REFORGE_DELAY.getChildPath());
        }
        if (key.keyExists(Setting.MAX_REFORGE_DELAY.getChildPath())) {
            maxReforgeDelay = key.getInt(Setting.MAX_REFORGE_DELAY.getChildPath());
        }
        if (key.keyExists(Setting.REFORGE_COOL_DOWN.getChildPath())) {
            reforgeCoolDown = key.getInt(Setting.REFORGE_COOL_DOWN.getChildPath());
        }
        if (key.keyExists(Setting.FAIL_CHANCE.getChildPath())) {
            failChance = key.getInt(Setting.FAIL_CHANCE.getChildPath());
        }
        if (key.keyExists(Setting.MAX_ENCHANTMENTS.getChildPath())) {
            maxEnchantments = key.getInt(Setting.MAX_ENCHANTMENTS.getChildPath());
        }
        if (key.keyExists(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath())) {
            extraEnchantmentChance = key.getInt(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath());
        }
        if (key.keyExists(Setting.DROP_ITEM.getChildPath())) {
            dropItem = key.getBoolean(Setting.DROP_ITEM.getChildPath());
        }
        if (key.keyExists(Setting.DISABLE_COOL_DOWN.getChildPath())) {
            disableCoolDown = key.getBoolean(Setting.DISABLE_COOL_DOWN.getChildPath());
        }
        if (key.keyExists(Setting.DISABLE_DELAY.getChildPath())) {
            disableDelay = key.getBoolean(Setting.DISABLE_DELAY.getChildPath());
        }
        if (key.keyExists(Setting.NATURAL_COST.getChildPath())) {
            naturalCost = key.getBoolean(Setting.NATURAL_COST.getChildPath());
        }
    }

    /**
     * Saves variables to the given data key
     *
     * @param key <p>The data key to save variables to</p>
     */
    public void saveVariables(DataKey key) {
        //This saves variables to the specific NPC. 
        key.setString(Setting.BUSY_WITH_PLAYER_MESSAGE.getChildPath(), getBusyWithPlayerMessage());
        key.setString(Setting.BUSY_WITH_REFORGE_MESSAGE.getChildPath(), getBusyReforgingMessage());
        key.setString(Setting.COST_MESSAGE.getChildPath(), getCostMessage());
        key.setString(Setting.INVALID_ITEM_MESSAGE.getChildPath(), getInvalidItemMessage());
        key.setString(Setting.START_REFORGE_MESSAGE.getChildPath(), getStartReforgeMessage());
        key.setString(Setting.SUCCESS_MESSAGE.getChildPath(), getSuccessMessage());
        key.setString(Setting.FAIL_MESSAGE.getChildPath(), getFailMessage());
        key.setString(Setting.INSUFFICIENT_FUNDS_MESSAGE.getChildPath(), getInsufficientFundsMessage());
        key.setString(Setting.COOL_DOWN_UNEXPIRED_MESSAGE.getChildPath(), getCoolDownUnexpiredMessage());
        key.setString(Setting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE.getChildPath(), getItemChangedMessage());
        key.setInt(Setting.MIN_REFORGE_DELAY.getChildPath(), getMinReforgeDelay());
        key.setInt(Setting.MAX_REFORGE_DELAY.getChildPath(), getMaxReforgeDelay());
        key.setInt(Setting.REFORGE_COOL_DOWN.getChildPath(), getReforgeCoolDown());
        key.setInt(Setting.FAIL_CHANCE.getChildPath(), getFailChance());
        key.setInt(Setting.EXTRA_ENCHANTMENT_CHANCE.getChildPath(), getExtraEnchantmentChance());
        key.setInt(Setting.MAX_ENCHANTMENTS.getChildPath(), getMaxEnchantments());
        key.setBoolean(Setting.DROP_ITEM.getChildPath(), getDropItem());
        key.setBoolean(Setting.DISABLE_DELAY.getChildPath(), getDisableDelay());
        key.setBoolean(Setting.DISABLE_COOL_DOWN.getChildPath(), getDisableCoolDown());
        key.setBoolean(Setting.DISABLE_COOL_DOWN.getChildPath(), getDisableCoolDown());
        key.setBoolean(Setting.NATURAL_COST.getChildPath(), getNaturalCost());
    }

    /**
     * Gets the message to display when the blacksmith is busy with another player
     *
     * @return <p>The busy with player message</p>
     */
    public String getBusyWithPlayerMessage() {
        return busyWithPlayerMessage;
    }

    /**
     * Gets the message to display when the blacksmith is busy with reforging an item
     *
     * @return <p>The busy reforging message</p>
     */
    public String getBusyReforgingMessage() {
        return busyReforgingMessage;
    }

    /**
     * Gets the message to use for displaying an item's cost
     *
     * @return <p>The message to use for displaying item cost</p>
     */
    public String getCostMessage() {
        return costMessage;
    }

    /**
     * Gets the message to display when a blacksmith has been given an invalid item
     *
     * @return <p>The invalid item message</p>
     */
    public String getInvalidItemMessage() {
        return invalidItemMessage;
    }

    /**
     * Gets the message to display when a blacksmith starts reforging an item
     *
     * @return <p>The start reforge message</p>
     */
    public String getStartReforgeMessage() {
        return startReforgeMessage;
    }

    /**
     * Gets the message to display when a blacksmith has successfully repaired an item
     *
     * @return <p>The reforge success message</p>
     */
    public String getSuccessMessage() {
        return successMessage;
    }

    /**
     * Gets the message to display when a blacksmith has failed to repair an item
     *
     * @return <p>The reforge fail message</p>
     */
    public String getFailMessage() {
        return failMessage;
    }

    /**
     * Gets the message to display when a player cannot afford re-forging an item
     *
     * @return <p>The insufficient funds message</p>
     */
    public String getInsufficientFundsMessage() {
        return insufficientFundsMessage;
    }

    /**
     * Gets the message to display when a blacksmith is still affected by a cool-down
     *
     * @return <p>The cool down unexpired message</p>
     */
    public String getCoolDownUnexpiredMessage() {
        return coolDownUnexpiredMessage;
    }

    /**
     * Gets the message to display when a player has changed the item they're trying to reforge
     *
     * @return <p>The item changed message</p>
     */
    public String getItemChangedMessage() {
        return itemChangedMessage;
    }

    /**
     * Gets the minimum delay used to wait for a re-forge to finish.
     *
     * @return <p>The minimum reforge delay</p>
     */
    public int getMinReforgeDelay() {
        return minReforgeDelay;
    }

    /**
     * Gets the maximum delay used to wait for a re-forge to finish
     *
     * @return <p>The maximum reforge delay</p>
     */
    public int getMaxReforgeDelay() {
        return maxReforgeDelay;
    }

    /**
     * Gets the cool-down between each reforge
     *
     * @return <p>The reforge cool-down</p>
     */
    public int getReforgeCoolDown() {
        return reforgeCoolDown;
    }

    /**
     * Gets the chance to fail a re-forge
     *
     * @return <p>The fail chance</p>
     */
    public int getFailChance() {
        return failChance;
    }

    /**
     * Gets the chance for adding an extra enchantment to an item
     *
     * @return <p>The extra enchantment chance</p>
     */
    public int getExtraEnchantmentChance() {
        return extraEnchantmentChance;
    }

    /**
     * Gets the max number of enchantment to add to an item
     *
     * @return <p>The maximum enchantments</p>
     */
    public int getMaxEnchantments() {
        return maxEnchantments;
    }

    /**
     * Gets whether an item should be dropped on the ground instead of being given to the player
     *
     * @return <p>Whether to drop reforged items on the ground</p>
     */
    public boolean getDropItem() {
        return dropItem;
    }

    /**
     * Gets whether to disable the reforge-cool-down
     *
     * @return <p>Whether to disable the reforge-cool-down</p>
     */
    public boolean getDisableCoolDown() {
        return disableCoolDown;
    }

    /**
     * Gets whether to disable the delay between starting reforging and the re-forge finishing
     *
     * @return <p>Whether to disable the reforge delay</p>
     */
    public boolean getDisableDelay() {
        return disableDelay;
    }

    /**
     * Gets whether to use a natural cost calculation
     *
     * <p>The natural cost makes repairs more expensive the more damaged an item is, rather than the opposite.</p>
     *
     * @return <p>Whether to use a natural cost calculation</p>
     */
    public boolean getNaturalCost() {
        return naturalCost;
    }

}