package net.apunch.blacksmith.config;

import java.util.Arrays;

/**
 * An enum representing all of Blacksmith's settings
 */
public enum Setting {

    BASE_PRICE("base-prices.default", 10.0),
    PRICE_PER_DURABILITY_POINT("price-per-durability-point.default", 1.0),
    BUSY_WITH_PLAYER_MESSAGE("defaults.messages.busy-with-player", "§cI'm busy at the moment. Come back later!"),
    BUSY_WITH_REFORGE_MESSAGE("defaults.messages.busy-with-reforge", "§cI'm working on it. Be patient!"),
    COOL_DOWN_UNEXPIRED_MESSAGE(
            "defaults.messages.cool-down-not-expired",
            "§cYou've already had your chance! Give me a break!"),
    COST_MESSAGE(
            "defaults.messages.cost",
            "§eIt will cost §a<price> §eto reforge that §a<item>§e! Click again to reforge!"),
    DROP_ITEM("defaults.drop-item", true),
    DISABLE_COOL_DOWN("defaults.disable-cool-down", false),
    DISABLE_DELAY("defaults.disable-delay", false),
    ENCHANTMENT_MODIFIER("enchantment-modifiers.default", 5),
    FAIL_CHANCE("defaults.percent-chance-to-fail-reforge", 10),
    FAIL_MESSAGE("defaults.messages.fail-reforge", "§cWhoops! Didn't mean to do that! Maybe next time?"),
    INSUFFICIENT_FUNDS_MESSAGE(
            "defaults.messages.insufficient-funds",
            "§cYou don't have enough money to reforge that item!"),
    INVALID_ITEM_MESSAGE("defaults.messages.invalid-item", "§cI'm sorry, but I don't know how to reforge that!"),
    ITEM_UNEXPECTEDLY_CHANGED_MESSAGE(
            "defaults.messages.item-changed-during-reforge",
            "§cThat's not the item you wanted to reforge before!"),
    EXTRA_ENCHANTMENT_CHANCE("defaults.percent-chance-for-extra-enchantment", 5),
    MAX_ENCHANTMENTS("defaults.maximum-enchantments", 3),
    MAX_REFORGE_DELAY("defaults.delays-in-seconds.maximum", 30),
    MIN_REFORGE_DELAY("defaults.delays-in-seconds.minimum", 5),
    REFORGE_COOL_DOWN("defaults.delays-in-seconds.reforge-cool-down", 60),
    START_REFORGE_MESSAGE("defaults.messages.start-reforge", "§eOk, let's see what I can do..."),
    SUCCESS_MESSAGE("defaults.messages.successful-reforge", "There you go! All better!"),
    NATURAL_COST("defaults.natural-cost", true);

    private final String path;
    private final String childPath;
    private Object value;

    /**
     * Instantiates a new setting
     *
     * @param path  <p>The full config path for this setting</p>
     * @param value <p>The default value of this setting</p>
     */
    Setting(String path, Object value) {
        this.path = path;
        this.value = value;
        String[] pathParts = path.split("\\.");
        this.childPath = String.join(".", Arrays.copyOfRange(pathParts, 1, pathParts.length));
    }

    /**
     * Gets the full config path for this setting
     *
     * @return <p>The full config path for this setting</p>
     */
    public String getPath() {
        return path;
    }

    /**
     * Gets the config path without the root node
     *
     * @return <p>The config path without the root node</p>
     */
    public String getChildPath() {
        return childPath;
    }

    /**
     * Gets this setting as a boolean
     *
     * <p>This will throw an exception if used for a non-boolean value</p>
     *
     * @return <p>This setting as a boolean</p>
     */
    public boolean asBoolean() {
        if (value instanceof String) {
            return Boolean.parseBoolean((String) value);
        } else {
            return (Boolean) value;
        }
    }

    /**
     * Gets this setting as a double
     *
     * <p>This will throw an exception if used for a non-double setting</p>
     *
     * @return <p>This setting as a double</p>
     */
    public double asDouble() {
        if (value instanceof String) {
            return Double.parseDouble((String) value);
        } else if (value instanceof Integer) {
            return (Integer) value;
        } else {
            return (Double) value;
        }
    }

    /**
     * Gets this setting as an integer
     *
     * <p>This will throw an exception if used for a non-integer setting</p>
     *
     * @return <p>This setting as an integer</p>
     */
    public int asInt() {
        if (value instanceof String) {
            return Integer.parseInt((String) value);
        } else {
            return (Integer) value;
        }
    }

    /**
     * Gets this setting as a string
     *
     * @return <p>This setting as a string</p>
     */
    public String asString() {
        return value.toString();
    }

    /**
     * Gets the value of this setting
     *
     * @return <p>The value of this setting</p>
     */
    Object get() {
        return value;
    }

    /**
     * Sets the value of this setting
     *
     * @param value <p>The new value of this setting</p>
     */
    void set(Object value) {
        this.value = value;
    }

}
