package net.knarcraft.blacksmith.config;

import org.bukkit.Material;

import java.util.ArrayList;
import java.util.List;

/**
 * A representation of the presets for different kinds of smiths
 */
public enum SmithPreset {

    /**
     * A blacksmith capable of re-forging all swords
     */
    SWORD_SMITH,

    /**
     * A blacksmith capable of re-forging all weapons (including shields)
     */
    WEAPON_SMITH,

    /**
     * A blacksmith capable of re-forging all armor
     */
    ARMOR_SMITH,

    /**
     * A blacksmith capable of re-forging all tools (hoe, axe, shovel, pickaxe, flint and steel, shears, fishing rod)
     */
    TOOL_SMITH,

    /**
     * A blacksmith capable of re-forging all ranged weapons (bow, crossbow, trident)
     */
    RANGED_SMITH;

    /**
     * Replaces the given string if it's a smith type placeholder
     *
     * @param possiblePlaceholder <p>The string that might be a placeholder</p>
     * @return <p>The string, possibly with the placeholder replaced</p>
     */
    public static String replacePlaceholder(String possiblePlaceholder) {
        for (SmithPreset smithPreset : SmithPreset.values()) {
            if (possiblePlaceholder.replace('-', '_').equalsIgnoreCase("preset:" +
                    smithPreset.name())) {
                return String.join(",", smithPreset.getMaterialNames());
            }
        }
        return possiblePlaceholder;
    }

    /**
     * Gets all materials included in this preset
     *
     * @return <p>All materials in this preset</p>
     */
    public List<Material> getMaterials() {
        return switch (this) {
            case SWORD_SMITH -> getSwords();
            case WEAPON_SMITH -> getWeapons();
            case ARMOR_SMITH -> getArmor();
            case TOOL_SMITH -> getTools();
            case RANGED_SMITH -> getRanged();
        };
    }

    /**
     * Gets all ranged weapon materials
     *
     * @return <p>All ranged weapon materials</p>
     */
    private List<Material> getRanged() {
        List<Material> ranged = new ArrayList<>();
        ranged.add(Material.TRIDENT);
        ranged.add(Material.BOW);
        ranged.add(Material.CROSSBOW);
        return ranged;
    }

    /**
     * Gets all tool materials
     *
     * @return <p>All tool materials</p>
     */
    private List<Material> getTools() {
        List<Material> tools = new ArrayList<>();
        tools.addAll(getMaterialsEndingWith("_HOE"));
        tools.addAll(getMaterialsEndingWith("_SHOVEL"));
        tools.addAll(getMaterialsEndingWith("_AXE"));
        tools.addAll(getMaterialsEndingWith("_PICKAXE"));
        tools.add(Material.FLINT_AND_STEEL);
        tools.add(Material.FISHING_ROD);
        tools.add(Material.SHEARS);
        return tools;
    }

    /**
     * Gets all weapon materials
     *
     * @return <p>All weapon materials</p>
     */
    private List<Material> getWeapons() {
        List<Material> weapons = new ArrayList<>(getSwords());
        weapons.addAll(getRanged());
        weapons.add(Material.SHIELD);
        return weapons;
    }

    /**
     * Gets all sword materials
     *
     * @return <p>All sword materials</p>
     */
    private List<Material> getSwords() {
        return getMaterialsEndingWith("_SWORD");
    }

    private List<Material> getArmor() {
        List<Material> armor = new ArrayList<>();
        armor.addAll(getMaterialsEndingWith("HELMET"));
        armor.addAll(getMaterialsEndingWith("CHESTPLATE"));
        armor.addAll(getMaterialsEndingWith("LEGGINGS"));
        armor.addAll(getMaterialsEndingWith("BOOTS"));
        armor.add(Material.ELYTRA);
        return armor;
    }

    /**
     * Gets all materials ending with the given string
     *
     * @param end <p>The string to look for</p>
     * @return <p>The resulting materials</p>
     */
    private List<Material> getMaterialsEndingWith(String end) {
        List<Material> swords = new ArrayList<>();
        for (Material material : Material.values()) {
            if (!material.name().startsWith("LEGACY") && material.name().endsWith(end)) {
                swords.add(material);
            }
        }
        return swords;
    }

    /**
     * Gets material names of all materials re-forge-able by this smith
     *
     * @return <p>All material names for this smith</p>
     */
    private List<String> getMaterialNames() {
        List<String> items = new ArrayList<>();
        for (Material material : this.getMaterials()) {
            items.add(material.name().toLowerCase().replace("_", "-"));
        }
        return items;
    }

}
