public interface CommandHandler {

} public class Locale extends BukkitRunnable {
    
    private static HashMap<String, HashMap<String, String>> localeStrings = new HashMap<String, HashMap<String,String>>();
    private static FileConfiguration config = think.rpgitems.Plugin.config;
    private Plugin plugin;
    private long lastUpdate = 0;
    private File dataFolder;
    private String version;
    private Locale(Plugin plugin) {
        this.plugin = plugin;
        lastUpdate = plugin.getConfig().getLong("lastLocaleUpdate", 0);
        version = plugin.getDescription().getVersion();
        if (!plugin.getConfig().getString("pluginVersion", "0.0").equals(version)) {
            lastUpdate = 0;
            plugin.getConfig().set("pluginVersion", version);
            plugin.saveConfig();
        }
        dataFolder = plugin.getDataFolder();
        reloadLocales(plugin);
        if (!plugin.getConfig().contains("localeDownload")) {
            plugin.getConfig().set("localeDownload", true);
            plugin.saveConfig();
        }
    }
    
    private final static String localeUpdateURL = "http://198.199.127.128/rpgitems/index.php?page=localeget&lastupdate=";
    private final static String localeDownloadURL = "http://www.rpgitems2.bugs3.com/locale/%s/%s.lang";
    
    public static Set<String> getLocales() {
        return localeStrings.keySet();
    }

    @Override
    public void run() {
        if (!plugin.getConfig().getBoolean("localeDownload", true)) {
            cancel();
        }
        try {
            URL updateURL = new URL(localeUpdateURL + lastUpdate);
            lastUpdate = System.currentTimeMillis();
            URLConnection conn = updateURL.openConnection();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));     
            ArrayList<String> locales = new ArrayList<String>();
            String line = null;
            while ((line = reader.readLine()) != null) {
                locales.add(line);
            }
            reader.close();
            File localesFolder = new File(dataFolder, "locale/");
            localesFolder.mkdirs();
            for (String locale : locales) {
                URL downloadURL = new URL(String.format(localeDownloadURL, version, locale));
                File outFile = new File(dataFolder, "locale/" + locale + ".lang");
                InputStream in = downloadURL.openStream();
                FileOutputStream out = new FileOutputStream(outFile);
                byte []buf = new byte[1024];
                int bytesRead;
                while ((bytesRead = in.read(buf)) != -1) {
                    out.write(buf, 0, bytesRead);
                }
                in.close();
                out.close();
            }
        } catch (Exception e) {
            return;
        }
        (new BukkitRunnable() {            
            @Override
            public void run() {
                ConfigurationSection config = plugin.getConfig();
                config.set("lastLocaleUpdate", lastUpdate);
                plugin.saveConfig();
                reloadLocales(plugin);
                for (RPGItem item : ItemManager.itemById.valueCollection()) {
                    item.rebuild();
                }
            }
        }).runTask(plugin);
    }
    
    public static void reloadLocales(Plugin plugin) {
        localeStrings.clear();
        localeStrings.put("en_GB", loadLocaleStream(plugin.getResource("locale/en_GB.lang")));
        localeStrings.put("fr_FR", loadLocaleStream(plugin.getResource("locale/fr_FR.lang")));
        localeStrings.put("es_ES", loadLocaleStream(plugin.getResource("locale/es_ES.lang")));
    }
    
    private static HashMap<String, String> loadLocaleStream(InputStream in, HashMap<String, String> map) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line = null;
            while((line = reader.readLine()) != null) {
                if (line.startsWith("#")) continue;
                String[] args = line.split("=");
                map.put(args[0].trim(), args[1].trim());
            }
            return map;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    private static HashMap<String, String> loadLocaleStream(InputStream in) {
        return loadLocaleStream(in, new HashMap<String, String>());
    }

    public static String getPlayerLocale(Player player) {
    	String language = config.getString("language");
    	
    	if(language.equals("es_ES")){
    		return "es_ES";
    	}else if(language.equals("fr_FR")){
    		return "fr_FR";
    	}else if(language.equals("en_GB")){
    		return "en_GB";
    	}else{
    		Plugin.plugin.getLogger().warning("Error language you've set : '" + language + "' isn't supported or don't exist ! Languages aviables are es_ES, fr_FR and en_GB");
    		return "en_GB";
    	}
    }

    public static void init(Plugin plugin) {
        (new Locale(plugin)).runTaskTimerAsynchronously(plugin, 0, 24l * 60l * 60l * 20l);
    }
    
    public static String get(String key, String locale) {
        if (!localeStrings.containsKey(locale))
            return get(key);
        HashMap<String, String> strings = localeStrings.get(locale);
        if (strings == null || !strings.containsKey(key)){
        	return get(key);
        }
        return strings.get(key);
    }
    
    private static String get(String key) {
        HashMap<String, String> strings = localeStrings.get("en_GB");
        if (!strings.containsKey(key))
            return "!" + key + "!";
        return strings.get(key);
    }
} public class ItemManager {
    public static TIntObjectHashMap<RPGItem> itemById = new TIntObjectHashMap<RPGItem>();
    public static HashMap<String, RPGItem> itemByName = new HashMap<String, RPGItem>();
    public static HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
    public static int currentPos = 0;

    public static void load(Plugin plugin) {
        try {
            FileInputStream in = null;
            YamlConfiguration itemStorage = null;
            try {
                File f = new File(plugin.getDataFolder(), "items.yml");
                in = new FileInputStream(f);
                byte[] data = new byte[(int) f.length()];
                in.read(data);
                itemStorage = new YamlConfiguration();
                String str = new String(data, "UTF-8");
                itemStorage.loadFromString(str);
            } catch (FileNotFoundException e) {
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InvalidConfigurationException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null)
                        in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            currentPos = itemStorage.getInt("pos", 0);
            ConfigurationSection section = itemStorage.getConfigurationSection("items");
            if (section == null) return;
            for (String key : section.getKeys(false)) {
                RPGItem item = new RPGItem(section.getConfigurationSection(key));
                itemById.put(item.getID(), item);
                itemByName.put(item.getName(), item);
                for (Power power : item.powers) {
                    Power.powerUsage.put(power.getName(), Power.powerUsage.get(power.getName()) + 1);
                }
            }
            
            if (itemStorage.contains("groups")) {
                ConfigurationSection gSection = itemStorage.getConfigurationSection("groups");
                for (String key : gSection.getKeys(false)) {
                    ItemGroup group = new ItemGroup(gSection.getConfigurationSection(key));
                    groups.put(group.getName(), group);
                }
            }
        } catch (Exception e) {
            //Something went wrong
            plugin.getLogger().severe("Error loading items.yml. Creating backup");
            File file = new File(plugin.getDataFolder(), "items.yml");
            long time = System.currentTimeMillis();
            File backup = new File(plugin.getDataFolder(), time + "-items.yml");
            FileUtil.copy(file, backup);
            File log = new File(plugin.getDataFolder(), time + "-log.txt");
            PrintStream ps = null;
            try {
                ps = new PrintStream(log);
                ps.printf("RPGItems (%s) ItemManager.load\r\n", plugin.getDescription().getVersion());
                e.printStackTrace(ps);
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            } finally {
                ps.close();
            }
        }
    }

    public static void save(Plugin plugin) {

        YamlConfiguration itemStorage = new YamlConfiguration();

        itemStorage.set("items", null);
        itemStorage.set("pos", currentPos);
        ConfigurationSection newSection = itemStorage.createSection("items");
        for (RPGItem item : itemById.valueCollection()) {
            ConfigurationSection itemSection = newSection.getConfigurationSection(item.getName());
            if (itemSection == null) {
                itemSection = newSection.createSection(item.getName());
            }
            item.save(itemSection);
        }

        ConfigurationSection groupsSection = itemStorage.createSection("groups");
        
        for (Entry<String, ItemGroup> group : groups.entrySet()) {
            ConfigurationSection groupSection = groupsSection.createSection(group.getKey());
            group.getValue().save(groupSection);
        }
        
        FileOutputStream out = null;
        try {
            File f = new File(plugin.getDataFolder(), "items.yml");
            out = new FileOutputStream(f);
            out.write(itemStorage.saveToString().getBytes("UTF-8"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static RPGItem toRPGItem(ItemStack item) {
        if (item == null)
            return null;
        if (!item.hasItemMeta())
            return null;
        ItemMeta meta = item.getItemMeta();
        if (!meta.hasDisplayName())
            return null;
        try {
            int id = ItemManager.decodeId(meta.getDisplayName());
            RPGItem rItem = ItemManager.getItemById(id);
            return rItem;
        } catch (Exception e) {
            return null;
        }
    }

    public static RPGItem newItem(String name) {
        if (itemByName.containsKey(name))
            return null;
        int free = 0;
        while (true) {
            free = currentPos++;
            if (!itemById.containsKey(free))
                break;
        }
        RPGItem item = new RPGItem(name, free);
        itemById.put(free, item);
        itemByName.put(name, item);
        return item;
    }

    public static RPGItem getItemById(int id) {
        return itemById.get(id);
    }

    public static RPGItem getItemByName(String uid) {
        return itemByName.get(uid);
    }

    public static int decodeId(String str) throws Exception {
        if (str.length() < 16) {
            throw new Exception();
        }
        StringBuilder out = new StringBuilder();
        for (int i = 0; i < 16; i++) {
            if (str.charAt(i) != ChatColor.COLOR_CHAR)
                throw new Exception();
            i++;
            out.append(str.charAt(i));
        }
        return Integer.parseInt(out.toString(), 16);
    }

    public static void remove(RPGItem item) {
        itemByName.remove(item.getName());
        itemById.remove(item.getID());
    }

} public class RPGItem {
    private ItemStack item;

    private HashMap<String, ItemMeta> localeMeta = new HashMap<String, ItemMeta>();

    private int id;
    private String name;
    private String encodedID;
    
    private boolean haspermission;
    private String permission;
    private String displayName;
    private Quality quality = Quality.TRASH;
    private int damageMin = 0, damageMax = 3;
    private int armour = 0;
    private String loreText = "";
    private String type = Plugin.plugin.getConfig().getString("defaults.sword", "Sword");
    private String hand = Plugin.plugin.getConfig().getString("defaults.hand", "One handed");
    public boolean ignoreWorldGuard = false;
    public List<String> description = new ArrayList<String>();
    
    // Powers
    public ArrayList<Power> powers = new ArrayList<Power>();
    private ArrayList<PowerLeftClick> powerLeftClick = new ArrayList<PowerLeftClick>();
    private ArrayList<PowerRightClick> powerRightClick = new ArrayList<PowerRightClick>();
    private ArrayList<PowerProjectileHit> powerProjectileHit = new ArrayList<PowerProjectileHit>();
    private ArrayList<PowerHit> powerHit = new ArrayList<PowerHit>();
    private ArrayList<PowerTick> powerTick = new ArrayList<PowerTick>();

    // Recipes
    public int recipechance = 6;
    public boolean hasRecipe = false;
    public List<ItemStack> recipe = null;

    // Drops
    public TObjectDoubleHashMap<String> dropChances = new TObjectDoubleHashMap<String>();

    private int tooltipWidth = 150;

    // Durability
    private int maxDurability;
    private boolean hasBar = false;
    private boolean forceBar = false;

    public RPGItem(String name, int id) {
        this.name = name;
        this.id = id;
        encodedID = getMCEncodedID(id);
        item = new ItemStack(Material.WOOD_SWORD);

        displayName = item.getType().toString();
        
        localeMeta.put("en_GB", item.getItemMeta());
        
        rebuild();
    }

    @SuppressWarnings("unchecked")
    public RPGItem(ConfigurationSection s) {

        name = s.getString("name");
        id = s.getInt("id");
        setDisplay(s.getString("display"), false);
        setType(s.getString("type", Plugin.plugin.getConfig().getString("defaults.sword", "Sword")), false);
        setHand(s.getString("hand", Plugin.plugin.getConfig().getString("defaults.hand", "One handed")), false);
        setLore(s.getString("lore"), false);
        description = (List<String>) s.getList("description", new ArrayList<String>());
        for (int i = 0; i < description.size(); i++) {
            description.set(i, ChatColor.translateAlternateColorCodes('&', description.get(i)));
        }
        quality = Quality.valueOf(s.getString("quality"));
        damageMin = s.getInt("damageMin");
        damageMax = s.getInt("damageMax");
        armour = s.getInt("armour", 0);
        item = new ItemStack(Material.valueOf(s.getString("item")));
        ItemMeta meta = item.getItemMeta();
        if (meta instanceof LeatherArmorMeta) {
            ((LeatherArmorMeta) meta).setColor(Color.fromRGB(s.getInt("item_colour", 0)));
        } else {
            item.setDurability((short) s.getInt("item_data", 0));
        }
        for (String locale : Locale.getLocales()) {
            localeMeta.put(locale, meta.clone());
        }
        ignoreWorldGuard = s.getBoolean("ignoreWorldGuard", false);

        // Powers
        ConfigurationSection powerList = s.getConfigurationSection("powers");
        if (powerList != null) {
            for (String sectionKey : powerList.getKeys(false)) {
                ConfigurationSection section = powerList.getConfigurationSection(sectionKey);
                try {
                    if (!Power.powers.containsKey(section.getString("powerName"))) {
                        // Invalid power
                        continue;
                    }
                    Power pow = Power.powers.get(section.getString("powerName")).newInstance();
                    pow.init(section);
                    pow.item = this;
                    addPower(pow, false);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
 
        
        encodedID = getMCEncodedID(id);
        haspermission = s.getBoolean("haspermission", false);
        permission = s.getString("permission", "a.default.permission");
        // Recipes
        recipechance = s.getInt("recipechance", 6);
        hasRecipe = s.getBoolean("hasRecipe", false);
        if (hasRecipe) {
            recipe = (List<ItemStack>) s.getList("recipe");
        }

        ConfigurationSection drops = s.getConfigurationSection("dropChances");
        if (drops != null) {
            for (String key : drops.getKeys(false)) {
                double chance = drops.getDouble(key, 0.0);
                chance = Math.min(chance, 100.0);
                if (chance > 0) {
                    dropChances.put(key, chance);
                    if (!Events.drops.containsKey(key)) {
                        Events.drops.put(key, new HashSet<Integer>());
                    }
                    Set<Integer> set = Events.drops.get(key);
                    set.add(getID());
                } else {
                    dropChances.remove(key);
                    if (Events.drops.containsKey(key)) {
                        Set<Integer> set = Events.drops.get(key);
                        set.remove(getID());
                    }
                }
                dropChances.put(key, chance);
            }
        }
        if (item.getType().getMaxDurability() != 0) {
            hasBar = true;
        }
        maxDurability = s.getInt("maxDurability", item.getType().getMaxDurability());
        forceBar = s.getBoolean("forceBar", false);

        if (maxDurability == 0) {
            maxDurability = -1;
        }
        
        rebuild();
        }
        

    public void save(ConfigurationSection s) {
        s.set("name", name);
        s.set("id", id);
        s.set("haspermission", haspermission);
        s.set("permission", permission);
        s.set("display", displayName.replaceAll("" + ChatColor.COLOR_CHAR, "&"));
        s.set("quality", quality.toString());
        s.set("damageMin", damageMin);
        s.set("damageMax", damageMax);
        s.set("armour", armour);
        s.set("type", type.replaceAll("" + ChatColor.COLOR_CHAR, "&"));
        s.set("hand", hand.replaceAll("" + ChatColor.COLOR_CHAR, "&"));
        s.set("lore", loreText.replaceAll("" + ChatColor.COLOR_CHAR, "&"));
        ArrayList<String> descriptionConv = new ArrayList<String>(description);
        for (int i = 0; i < descriptionConv.size(); i++) {
            descriptionConv.set(i, descriptionConv.get(i).replaceAll("" + ChatColor.COLOR_CHAR, "&"));
        }
        s.set("description", descriptionConv);
        s.set("item", item.getType().toString());
        s.set("ignoreWorldGuard", ignoreWorldGuard);

        ItemMeta meta = localeMeta.get("en_GB");
        if (meta instanceof LeatherArmorMeta) {
            s.set("item_colour", ((LeatherArmorMeta) meta).getColor().asRGB());
        } else {
            s.set("item_data", item.getDurability());
        }
        ConfigurationSection powerConfigs = s.createSection("powers");
        int i = 0;
        for (Power p : powers) {
            MemoryConfiguration pConfig = new MemoryConfiguration();
            pConfig.set("powerName", p.getName());
            p.save(pConfig);
            powerConfigs.set(Integer.toString(i), pConfig);
            i++;
        }

        // Recipes
        s.set("recipechance", recipechance);
        s.set("hasRecipe", hasRecipe);
        if (hasRecipe) {
            s.set("recipe", recipe);
        }

        ConfigurationSection drops = s.createSection("dropChances");
        for (String key : dropChances.keySet()) {
            drops.set(key, dropChances.get(key));
        }

        s.set("maxDurability", maxDurability);
        s.set("forceBar", forceBar);
    }

    public void resetRecipe(boolean removeOld) {
        if (removeOld) {
            Iterator<Recipe> it = Bukkit.recipeIterator();
            while (it.hasNext()) {
                Recipe recipe = it.next();
                RPGItem rpgitem = ItemManager.toRPGItem(recipe.getResult());
                if (rpgitem == null)
                    continue;
                if (rpgitem.getID() == getID()) {
                    it.remove();
                }
            }
        }
        if (hasRecipe) {
            Set<ItemStack> iSet = new HashSet<ItemStack>();
            for (ItemStack m : recipe) {
                iSet.add(m);
            }
            ItemStack[] iList = iSet.toArray(new ItemStack[iSet.size()]);
            item.setItemMeta(getLocaleMeta("en_GB"));
            ShapedRecipe shapedRecipe = new ShapedRecipe(item);
            int i = 0;
            Map<ItemStack, Character> iMap = new HashMap<ItemStack, Character>();
            for (ItemStack m : iList) {
                iMap.put(m, (char) (65 + i));
                i++;
            }
            iMap.put(null, ' ');
            StringBuilder out = new StringBuilder();
            for (ItemStack m : recipe) {
                out.append(iMap.get(m));
            }
            String shape = out.toString();
            shapedRecipe.shape(new String[] { shape.substring(0, 3), shape.substring(3, 6), shape.substring(6, 9) });
            for (Entry<ItemStack, Character> e : iMap.entrySet()) {
                if (e.getKey() != null) {
                    shapedRecipe.setIngredient(e.getValue(), e.getKey().getType(), e.getKey().getDurability());
                }
            }
            Bukkit.addRecipe(shapedRecipe);
        }
    }

    public void leftClick(Player player) {
        for (PowerLeftClick power : powerLeftClick) {
            power.leftClick(player);
        }
    }

    public void rightClick(Player player) {
        for (PowerRightClick power : powerRightClick) {
            power.rightClick(player);
        }
    }

    public void projectileHit(Player player, Projectile arrow) {
        for (PowerProjectileHit power : powerProjectileHit) {
            power.projectileHit(player, arrow);
        }
    }

    public void hit(Player player, LivingEntity e, double d) {
        for (PowerHit power : powerHit) {
            power.hit(player, e, d);
        }
    }

    public void tick(Player player) {
        for (PowerTick power : powerTick) {
            power.tick(player);
        }
    }

    public void rebuild() {
        for (String locale : Locale.getLocales()) {
            if (!localeMeta.containsKey(locale))
                localeMeta.put(locale, getLocaleMeta("en_GB"));
        }
        for (String locale : Locale.getLocales()) {
            List<String> lines = getTooltipLines(locale);
            ItemMeta meta = getLocaleMeta(locale);
            meta.setDisplayName(lines.get(0));
            lines.remove(0);
            meta.setLore(lines);
            setLocaleMeta(locale, meta);
            // item.setItemMeta(meta);
        }

        for (Player player : Bukkit.getOnlinePlayers()) {
            Iterator<ItemStack> it = player.getInventory().iterator();
            String locale = Locale.getPlayerLocale(player);
            while (it.hasNext()) {
                ItemStack item = it.next();
                if (ItemManager.toRPGItem(item) != null)
                    updateItem(item, locale, false);
            }
            for (ItemStack item : player.getInventory().getArmorContents()) {
                if (ItemManager.toRPGItem(item) != null)
                    updateItem(item, locale, false);

            }
        }
        resetRecipe(true);
    }

    public static RPGMetadata getMetadata(ItemStack item) {
        //Check for broken item
        if (!item.hasItemMeta() || !item.getItemMeta().hasLore() || item.getItemMeta().getLore().size() == 0) {
            //Broken item
            return new RPGMetadata();
        }
        return RPGMetadata.parseLoreline(item.getItemMeta().getLore().get(0));
    }

    public static void updateItem(ItemStack item, String locale) {
        updateItem(item, locale, getMetadata(item));
    }

    public static void updateItem(ItemStack item, String locale, RPGMetadata rpgMeta) {
        updateItem(item, locale, rpgMeta, false);
    }

    public static void updateItem(ItemStack item, String locale, boolean updateDurability) {
        updateItem(item, locale, getMetadata(item), false);
    }

    public static void updateItem(ItemStack item, String locale, RPGMetadata rpgMeta, boolean updateDurability) {
        RPGItem rItem = ItemManager.toRPGItem(item);
        if (rItem == null)
            return;
        item.setType(rItem.item.getType());
        ItemMeta meta = rItem.getLocaleMeta(locale);
        if (!(meta instanceof LeatherArmorMeta) && updateDurability) {
            item.setDurability(rItem.item.getDurability());
        }
        List<String> lore = meta.getLore();
        rItem.addExtra(rpgMeta, item, lore);
        lore.set(0, meta.getLore().get(0) + rpgMeta.toMCString());
        meta.setLore(lore);
        item.setItemMeta(meta);
    }

    public void addExtra(RPGMetadata rpgMeta, ItemStack item, List<String> lore) {
        if (maxDurability > 0) {
            if (!rpgMeta.containsKey(RPGMetadata.DURABILITY)) {
                rpgMeta.put(RPGMetadata.DURABILITY, Integer.valueOf(maxDurability));
            }
            int durability = ((Number) rpgMeta.get(RPGMetadata.DURABILITY)).intValue();

            if (!hasBar || forceBar) {
                StringBuilder out = new StringBuilder();
                char boxChar = '\u25A0';
                int boxCount = tooltipWidth / 4;
                int mid = (int) ((double) boxCount * ((double) durability / (double) maxDurability));
                for (int i = 0; i < boxCount; i++) {
                    out.append(i < mid ? ChatColor.GREEN : i == mid ? ChatColor.YELLOW : ChatColor.RED);
                    out.append(boxChar);
                }
                lore.add(out.toString());
            }
            if (hasBar) {
                item.setDurability((short) (item.getType().getMaxDurability() - ((short) ((double) item.getType().getMaxDurability() * ((double) durability / (double) maxDurability)))));
            }
        } else if (maxDurability <= 0) {
            item.setDurability(hasBar ? (short)0 : this.item.getDurability());
        }
    }

    public List<String> getTooltipLines(String locale) {
        ArrayList<String> output = new ArrayList<String>();
        int width = 150;
        output.add(encodedID + quality.colour + ChatColor.BOLD + displayName);
        int dWidth = getStringWidthBold(ChatColor.stripColor(displayName));
        if (dWidth > width)
            width = dWidth;

        dWidth = getStringWidth(ChatColor.stripColor(hand + "     " + type));
        if (dWidth > width)
            width = dWidth;
        String damageStr = null;
        if (damageMin == 0 && damageMax == 0 && armour != 0) {
            damageStr = armour + "% " + Plugin.plugin.getConfig().getString("defaults.armour", "Armour");
        } else if (armour == 0 && damageMin == 0 && damageMax == 0) {
            damageStr = null;
        } else if (damageMin == damageMax) {
            damageStr = damageMin + " " + Plugin.plugin.getConfig().getString("defaults.damage", "Damage");
        } else {
            damageStr = damageMin + "-" + damageMax + " " + Plugin.plugin.getConfig().getString("defaults.damage", "Damage");
        }
        if (damageMin != 0 || damageMax != 0 || armour != 0) {
            dWidth = getStringWidth(damageStr);
            if (dWidth > width)
                width = dWidth;
        }

        for (Power p : powers) {
            dWidth = getStringWidth(ChatColor.stripColor(p.displayText(locale)));
            if (dWidth > width)
                width = dWidth;
        }

        for (String s : description) {
            dWidth = getStringWidth(ChatColor.stripColor(s));
            if (dWidth > width)
                width = dWidth;
        }

        tooltipWidth = width;

        output.add(ChatColor.WHITE + hand + StringUtils.repeat(" ", (width - getStringWidth(ChatColor.stripColor(hand + type))) / 4) + type);
        if (damageStr != null) {
            output.add(ChatColor.WHITE + damageStr);
        }

        for (Power p : powers) {
            output.add(p.displayText(locale));
        }
        if (loreText.length() != 0) {
            int cWidth = 0;
            int tWidth = 0;
            StringBuilder out = new StringBuilder();
            StringBuilder temp = new StringBuilder();
            out.append(ChatColor.YELLOW);
            out.append(ChatColor.ITALIC);
            String currentColour = ChatColor.YELLOW.toString();
            String dMsg = "\"" + loreText + "\"";
            for (int i = 0; i < dMsg.length(); i++) {
                char c = dMsg.charAt(i);
                temp.append(c);
                if (c == ChatColor.COLOR_CHAR || c == '&') {
                    i += 1;
                    temp.append(dMsg.charAt(i));
                    currentColour = ChatColor.COLOR_CHAR + "" + dMsg.charAt(i);
                    continue;
                }
                if (c == ' ')
                    tWidth += 4;
                else
                    tWidth += Font.widths[c] + 1;
                if (c == ' ' || i == dMsg.length() - 1) {
                    if (cWidth + tWidth > width) {
                        cWidth = 0;
                        cWidth += tWidth;
                        tWidth = 0;
                        output.add(out.toString());
                        out = new StringBuilder();
                        out.append(currentColour);
                        out.append(ChatColor.ITALIC);
                        out.append(temp);
                        temp = new StringBuilder();
                    } else {
                        out.append(temp);
                        temp = new StringBuilder();
                        cWidth += tWidth;
                        tWidth = 0;
                    }
                }
            }
            out.append(temp);
            output.add(out.toString());
        }

        for (String s : description) {
            output.add(s);
        }
        return output;
    }

    public ItemStack toItemStack(String locale) {
        ItemStack rStack = item.clone();
        RPGMetadata rpgMeta = new RPGMetadata();
        ItemMeta meta = getLocaleMeta(locale);
        List<String> lore = meta.getLore();
        lore.set(0, meta.getLore().get(0) + rpgMeta.toMCString());
        addExtra(rpgMeta, rStack, lore);
        meta.setLore(lore);
        rStack.setItemMeta(meta);
        return rStack;
    }

    public ItemMeta getLocaleMeta(String locale) {
        ItemMeta meta = localeMeta.get(locale);
        if (meta == null)
            meta = localeMeta.get("en_GB");
        return meta.clone();
    }

    public void setLocaleMeta(String locale, ItemMeta meta) {
        localeMeta.put(locale, meta);
    }

    public String getName() {
        return name;
    }

    public int getID() {
        return id;
    }

    public String getMCEncodedID() {
        return encodedID;
    }

    public static String getMCEncodedID(int id) {
        String hex = String.format("%08x", id);
        StringBuilder out = new StringBuilder();
        for (char h : hex.toCharArray()) {
            out.append(ChatColor.COLOR_CHAR);
            out.append(h);
        }
        return out.toString();
    }

    private static int getStringWidth(String str) {
        int width = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            width += Font.widths[c] + 1;
        }
        return width;
    }

    private static int getStringWidthBold(String str) {
        int width = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            width += Font.widths[c] + 2;
        }
        return width;
    }

    public void print(CommandSender sender) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        List<String> lines = getTooltipLines(locale);
        for (String s : lines) {
            sender.sendMessage(s);
        }
        sender.sendMessage(String.format(Locale.get("message.print.durability", locale), maxDurability));
    }

    public void setDisplay(String str) {
        setDisplay(str, true);
    }

    public void setDisplay(String str, boolean update) {
        displayName = ChatColor.translateAlternateColorCodes('&', str);
        if (update)
            rebuild();
    }

    public String getDisplay() {
        return quality.colour + ChatColor.BOLD + displayName;
    }

    public void setType(String str) {
        setType(str, true);
    }

    public void setType(String str, boolean update) {
        type = ChatColor.translateAlternateColorCodes('&', str);
        if (update)
            rebuild();
    }

    public String getType() {
        return type;
    }

    public void setHand(String h) {
        setHand(h, true);
    }

    public void setHand(String h, boolean update) {
        hand = ChatColor.translateAlternateColorCodes('&', h);
        if (update)
            rebuild();
    }

    public String getHand() {
        return hand;
    }

    public void setDamage(int min, int max) {
        setDamage(min, max, true);
    }

    public void setDamage(int min, int max, boolean update) {
        damageMin = min;
        damageMax = max;
        armour = 0;
        if (update)
            rebuild();
    }

    public int getDamageMin() {
        return damageMin;
    }

    public int getDamageMax() {
        return damageMax;
    }
    
    public int getRecipeChance() {
        return recipechance;
    } 
 
    public void setRecipeChance(int p) {
        setRecipeChance(p, true);
    }

    public void setRecipeChance(int p, boolean update) {
        recipechance = p;
        if (update)
            rebuild();
    }
    
    public String getPermission() {
        return permission;
    } 
    
    public boolean getHasPermission() {
        return haspermission;
    }
    
    public void setPermission(String p) {
        setPermission(p, true);
    }

    public void setPermission(String p, boolean update) {
        permission = p;
        if (update)
            rebuild();
    }

    public void setHaspermission(boolean b) {
        setHaspermission(b, true);
    }

    public void setHaspermission(boolean b, boolean update) {
        haspermission = b;
        if (update)
            rebuild();
    }

    public void setArmour(int a) {
        setArmour(a, true);
    }

    public void setArmour(int a, boolean update) {
        armour = a;
        damageMin = damageMax = 0;
        if (update)
            rebuild();
    }

    public int getArmour() {
        return armour;
    }

    public void setLore(String str) {
        setLore(str, true);
    }

    public void setLore(String str, boolean update) {
        loreText = ChatColor.translateAlternateColorCodes('&', str);
        if (update)
            rebuild();
    }

    public String getLore() {
        return loreText;
    }

    public void setQuality(Quality q) {
        setQuality(q, true);
    }

    public void setQuality(Quality q, boolean update) {
        quality = q;
        if (update)
            rebuild();
    }

    public Quality getQuality() {
        return quality;
    }

    public void setItem(Material mat) {
        setItem(mat, true);
    }

    public void setItem(Material mat, boolean update) {
        if (maxDurability == item.getType().getMaxDurability()) {
            maxDurability = mat.getMaxDurability();
        }
        item.setType(mat);
        if (update)
            rebuild();
    }

    public void setDataValue(short value, boolean update) {
        item.setDurability(value);
        if (update)
            rebuild();
    }

    public void setDataValue(short value) {
        item.setDurability(value);
    }

    public short getDataValue() {
        return item.getDurability();
    }

    public Material getItem() {
        return item.getType();
    }

    public void setMaxDurability(int newVal) {
        setMaxDurability(newVal, true);
    }

    public void setMaxDurability(int newVal, boolean update) {
        maxDurability = newVal;
        if (update)
            rebuild();
    }

    public int getMaxDurability() {
        return maxDurability <= 0 ? -1 : maxDurability;
    }

    public void give(Player player) {
        player.getInventory().addItem(toItemStack(Locale.getPlayerLocale(player)));
    }

    public void addPower(Power power) {
        addPower(power, true);
    }

    public void addPower(Power power, boolean update) {
        powers.add(power);
        Power.powerUsage.put(power.getName(), Power.powerUsage.get(power.getName()) + 1);
        if (power instanceof PowerHit) {
            powerHit.add((PowerHit) power);
        }
        if (power instanceof PowerLeftClick) {
            powerLeftClick.add((PowerLeftClick) power);
        }
        if (power instanceof PowerRightClick) {
            powerRightClick.add((PowerRightClick) power);
        }
        if (power instanceof PowerProjectileHit) {
            powerProjectileHit.add((PowerProjectileHit) power);
        }
        if (power instanceof PowerTick) {
            powerTick.add((PowerTick) power);
        }
        if (update)
            rebuild();
    }

    public boolean removePower(String pow) {
        Iterator<Power> it = powers.iterator();
        Power power = null;
        while (it.hasNext()) {
            Power p = it.next();
            if (p.getName().equalsIgnoreCase(pow)) {
                it.remove();
                power = p;
                rebuild();
                break;
            }
        }
        if (power != null) {
            if (power instanceof PowerHit) {
                powerHit.remove((PowerHit) power);
            }
            if (power instanceof PowerLeftClick) {
                powerLeftClick.remove(power);
            }
            if (power instanceof PowerRightClick) {
                powerRightClick.remove(power);
            }
            if (power instanceof PowerProjectileHit) {
                powerProjectileHit.remove(power);
            }
            if (power instanceof PowerTick) {
                powerTick.remove(power);
            }
        }
        return power != null;
    }

    public void addDescription(String str) {
        addDescription(str, true);
    }

    public void addDescription(String str, boolean update) {
        description.add(ChatColor.translateAlternateColorCodes('&', str));
        if (update)
            rebuild();
    }

    public void toggleBar() {
        forceBar = !forceBar;
        rebuild();
    }

} public class PowerArrow extends Power implements PowerRightClick{

    public long cooldownTime = 20;

    @Override
    public void rightClick(Player player) {
        long cooldown;
       if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
       }else{ 
    	   RPGValue value = RPGValue.get(player, item, "arrow.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "arrow.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.playSound(player.getLocation(), Sound.SHOOT_ARROW, 1.0f, 1.0f);
            Arrow arrow = player.launchProjectile(Arrow.class);
            Events.removeArrows.put(arrow.getEntityId(), (byte) 1);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
       }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.arrow", locale), (double) cooldownTime / 20d);
    }

    @Override
    public String getName() {
        return "arrow";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
    }
} public class PowerCommand extends Power implements PowerRightClick, PowerLeftClick {

    public String command = "";
    public String display = "Runs command";
    public String permission = "";
    public boolean isRight = true;
    public long cooldownTime = 20;

    @Override
    public void rightClick(Player player) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{  
    	if (isRight) {
            long cooldown;
            RPGValue value = RPGValue.get(player, item, "command." + command + ".cooldown");
            if (value == null) {
                cooldown = System.currentTimeMillis() / 50;
                value = new RPGValue(player, item, "command." + command + ".cooldown", cooldown);
            } else {
                cooldown = value.asLong();
            }
            if (cooldown <= System.currentTimeMillis() / 50) {
                value.set(System.currentTimeMillis() / 50 + cooldownTime);
                if (permission.length() != 0 && !permission.equals("*")) {
                    PermissionAttachment attachment = player.addAttachment(Plugin.plugin, 1);
                    String[] perms = permission.split("\\.");
                    StringBuilder p = new StringBuilder();
                    for (int i = 0; i < perms.length; i++) {
                        p.append(perms[i]);
                        attachment.setPermission(p.toString(), true);
                        p.append('.');
                    }
                }
                boolean wasOp = player.isOp();
                if (permission.equals("*"))
                    player.setOp(true);
                player.chat("/" + command.replaceAll("\\{player\\}", player.getName()));
                if (permission.equals("*"))
                    player.setOp(wasOp);
            } else {
                player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
            }
        }
        }
    }

    @Override
    public void leftClick(Player player) {
        if (!isRight) {
            long cooldown;
            RPGValue value = RPGValue.get(player, item, "command." + command + ".cooldown");
            if (value == null) {
                cooldown = System.currentTimeMillis() / 50;
                value = new RPGValue(player, item, "command." + command + ".cooldown", cooldown);
            } else {
                cooldown = value.asLong();
            }
            if (cooldown <= System.currentTimeMillis() / 50) {
                value.set(System.currentTimeMillis() / 50 + cooldownTime);
                if (permission.length() != 0 && !permission.equals("*")) {
                    PermissionAttachment attachment = player.addAttachment(Plugin.plugin, 1);
                    String[] perms = permission.split("\\.");
                    StringBuilder p = new StringBuilder();
                    for (int i = 0; i < perms.length; i++) {
                        p.append(perms[i]);
                        attachment.setPermission(p.toString(), true);
                        p.append('.');
                    }
                }
                boolean wasOp = player.isOp();
                if (permission.equals("*"))
                    player.setOp(true);
                player.chat("/" + command.replaceAll("\\{player\\}", player.getName()));
                if (permission.equals("*"))
                    player.setOp(wasOp);
            } else {
                player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
            }
        }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + display;
    }

    @Override
    public String getName() {
        return "command";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
        command = s.getString("command", "");
        display = s.getString("display", "");
        isRight = s.getBoolean("isRight", true);
        permission = s.getString("permission", "");
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
        s.set("command", command);
        s.set("display", display);
        s.set("isRight", isRight);
        s.set("permission", permission);
    }
} public class PowerConsume extends Power implements PowerRightClick {

    @Override
    public void rightClick(Player player) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        ItemStack item = player.getInventory().getItemInHand();
        int count = item.getAmount() - 1;
        if (count == 0) {
            item.setAmount(0);
            item.setType(Material.AIR);
            player.setItemInHand(null);
        } else {
            item.setAmount(count);
        }
        }
    }

    @Override
    public void init(ConfigurationSection s) {

    }

    @Override
    public void save(ConfigurationSection s) {

    }

    @Override
    public String getName() {
        return "consume";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + Locale.get("power.consume", locale);
    }
} public class PowerFireball extends Power implements PowerRightClick {

    public long cooldownTime = 20;

    @Override
    public void rightClick(Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        RPGValue value = RPGValue.get(player, item, "tnt.fireball");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "tnt.fireball", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.playSound(player.getLocation(), Sound.GHAST_FIREBALL, 1.0f, 1.0f);
            player.launchProjectile(SmallFireball.class);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.fireball", locale), (double) cooldownTime / 20d);
    }

    @Override
    public String getName() {
        return "fireball";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
    }
} public class PowerFlame extends Power implements PowerHit {

    public int burnTime = 20;

    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{  
    	e.setFireTicks(burnTime);
    }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.flame", locale), (double) burnTime / 20d);
    }

    @Override
    public String getName() {
        return "flame";
    }

    @Override
    public void init(ConfigurationSection s) {
        burnTime = s.getInt("burntime");
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("burntime", burnTime);
    }
} public class PowerFood extends Power implements PowerRightClick {
	public int foodpoints;
	@Override
    public void rightClick(Player player) {
	       if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
	       }else{
          ItemStack item = player.getInventory().getItemInHand();
          int count = item.getAmount() - 1;
          if (count == 0) {
        	player.setFoodLevel(player.getFoodLevel() + foodpoints);
            item.setAmount(0);
            item.setType(Material.AIR);
            player.setItemInHand(item);
          } else {
        	player.setFoodLevel(player.getFoodLevel() + foodpoints);
            item.setAmount(count);
        }
	  }
    }

    @Override
    public void init(ConfigurationSection s) {
      foodpoints = s.getInt("foodpoints");
    }

    @Override
    public void save(ConfigurationSection s) {
      s.set("foodpoints", foodpoints); 
    }

    @Override
    public String getName() {
        return "food";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.food", locale),foodpoints);
    }
} public class PowerIce extends Power implements PowerRightClick {

    public long cooldownTime = 20;

    @Override
    public void rightClick(final Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{  
        RPGValue value = RPGValue.get(player, item, "ice.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "ice.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.playSound(player.getLocation(), Sound.FIZZ, 1.0f, 0.1f);
            final FallingBlock block = player.getWorld().spawnFallingBlock(player.getLocation().add(0, 1.8, 0), Material.ICE, (byte) 0);
            block.setVelocity(player.getLocation().getDirection().multiply(2d));
            block.setDropItem(false);
            BukkitRunnable run = new BukkitRunnable() {

                @SuppressWarnings("deprecation")
				public void run() {
                    boolean hit = false;
                    World world = block.getWorld();
                    Location bLoc = block.getLocation();
                    loop: for (int x = -1; x < 2; x++) {
                        for (int y = -1; y < 2; y++) {
                            for (int z = -1; z < 2; z++) {
                                Location loc = block.getLocation().add(x, y, z);
                                if (world.getBlockTypeIdAt(loc) != Material.AIR.getId()) {
                                    Block b = world.getBlockAt(loc);
                                    if (b.getType().isSolid()) {
                                        if (checkBlock(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 1, 1, 1, bLoc.getX() - 0.5d, bLoc.getY() - 0.5d, bLoc.getZ() - 0.5d, 1, 1, 1)) {
                                            hit = true;
                                            break loop;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (!hit) {
                        List<Entity> entities = block.getNearbyEntities(1, 1, 1);
                        for (Entity e : entities) {
                            if (e != player) {
                                hit = true;
                                break;
                            }
                        }
                    }
                    if (block.isDead() || hit) {
                        block.remove();
                        block.getLocation().getBlock().setType(Material.AIR);
                        cancel();
                        final TObjectLongHashMap<Location> changedBlocks = new gnu.trove.map.hash.TObjectLongHashMap<Location>();
                        for (int x = -1; x < 2; x++) {
                            for (int y = -1; y < 3; y++) {
                                for (int z = -1; z < 2; z++) {
                                    Location loc = block.getLocation().add(x, y, z);
                                    Block b = world.getBlockAt(loc);
                                    if (!b.getType().isSolid()) {
                                        changedBlocks.put(b.getLocation(), b.getTypeId() | (b.getData() << 16));
                                        b.setType(Material.ICE);
                                    }
                                }
                            }
                        }
                        (new BukkitRunnable() {
                            Random random = new Random();

                            @SuppressWarnings("deprecation")
							public void run() {
                                for (int i = 0; i < 4; i++) {
                                    if (changedBlocks.isEmpty()) {
                                        cancel();
                                        return;
                                    }
                                    int index = random.nextInt(changedBlocks.size());
                                    long data = changedBlocks.values()[index];
                                    Location position = (Location) changedBlocks.keys()[index];
                                    changedBlocks.remove(position);
                                    Block c = position.getBlock();
                                    position.getWorld().playEffect(position, Effect.STEP_SOUND, c.getTypeId());
                                    c.setTypeId((int) (data & 0xFFFF));
                                    c.setData((byte) (data >> 16));
                                }

                            }
                        }).runTaskTimer(Plugin.plugin, 4 * 20 + new Random().nextInt(40), 3);
                    }

                }
            };
            run.runTaskTimer(Plugin.plugin, 0, 1);

        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    private boolean checkBlock(double x1, double y1, double z1, double w1, double h1, double d1, double x2, double y2, double z2, double w2, double h2, double d2) {
        if (x1 + w1 < x2)
            return false;
        if (x2 + w2 < x1)
            return false;
        if (y1 + h1 < y2)
            return false;
        if (y2 + h2 < y1)
            return false;
        if (z1 + d1 < z2)
            return false;
        if (z2 + d2 < z1)
            return false;

        return true;
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.ice", locale), (double) cooldownTime / 20d);
    }

    @Override
    public String getName() {
        return "ice";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
    }
} public class PowerKnockup extends Power implements PowerHit {

    public int chance = 20;
    public double power = 2;

    private Random rand = new Random();

    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else if (rand.nextInt(chance) == 0)
            e.setVelocity(player.getLocation().getDirection().setY(power));
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.knockup", locale), (int) ((1d / (double) chance) * 100d));
    }

    @Override
    public String getName() {
        return "knockup";
    }

    @Override
    public void init(ConfigurationSection s) {
        chance = s.getInt("chance");
        power = s.getDouble("power", 2);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("chance", chance);
        s.set("power", power);
    }

} public class PowerLifeSteal extends Power implements PowerHit {

    public int chance = 20;
    private Random random = new Random();
    @Override
    public void hit(Player player, LivingEntity e, double damage) {
    	if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else if (random.nextInt(chance) == 0){
          if ((player.getHealth() + damage) >= player.getMaxHealth()){
        	  player.setHealth(player.getMaxHealth());
          }else
        	player.setHealth(player.getHealth() + damage);
    }
    }	

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.lifesteal", locale), (double) chance);
    }

    @Override
    public String getName() {
        return "lifesteal";
    }

    @Override
    public void init(ConfigurationSection s) {
        chance = s.getInt("chance");
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("chance", chance);
    }
} public class PowerLightning extends Power implements PowerHit, PowerProjectileHit {

    public int chance = 20;
    private Random random = new Random();

    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else if (random.nextInt(chance) == 0)
            e.getWorld().strikeLightning(e.getLocation());
    }

    @Override
    public void projectileHit(Player player, Projectile p) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
     	   player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));
        }else if (random.nextInt(chance) == 0)
            p.getWorld().strikeLightning(p.getLocation());
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.lightning", locale), (int) ((1d / (double) chance) * 100d));
    }

    @Override
    public String getName() {
        return "lightning";
    }

    @Override
    public void init(ConfigurationSection s) {
        chance = s.getInt("chance");
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("chance", chance);
    }
} public class PowerPotionHit extends Power implements PowerHit {

    public int chance = 20;
    private Random random = new Random();
    public PotionEffectType type = PotionEffectType.HARM;
    public int duration = 20;
    public int amplifier = 1;

    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else if (random.nextInt(chance) == 0)
            e.addPotionEffect(new PotionEffect(type, duration, amplifier));
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.potionhit", locale), (int) ((1d / (double) chance) * 100d), type.getName().toLowerCase().replace('_', ' '));
    }

    @Override
    public String getName() {
        return "potionhit";
    }

    @Override
    public void init(ConfigurationSection s) {
        chance = s.getInt("chance", 20);
        duration = s.getInt("duration", 20);
        amplifier = s.getInt("amplifier", 1);
        type = PotionEffectType.getByName(s.getString("type", PotionEffectType.HARM.getName()));
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("chance", chance);
        s.set("duration", duration);
        s.set("amplifier", amplifier);
        s.set("type", type.getName());
    }
} public class PowerPotionSelf extends Power implements PowerRightClick {

    public long cooldownTime = 20;
    public int amplifier = 3;
    public int time = 20;
    public PotionEffectType type = PotionEffectType.HEAL;

    @Override
    public void rightClick(Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{  
        RPGValue value = RPGValue.get(player, item, "potionself.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "potionself.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.addPotionEffect(new PotionEffect(type, time, amplifier));
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown");
        amplifier = s.getInt("amp");
        time = s.getInt("time");
        type = PotionEffectType.getByName(s.getString("type", "heal"));
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
        s.set("amp", amplifier);
        s.set("time", time);
        s.set("type", type.getName());
    }

    @Override
    public String getName() {
        return "potionself";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.potionself", locale), type.getName().toLowerCase().replaceAll("_", " "), amplifier + 1, ((double) time) / 20d);
    }

} public class PowerPotionTick extends Power implements PowerTick {

    public int amplifier = 2;
    public PotionEffectType effect = PotionEffectType.SPEED;

    @Override
    public void tick(Player player) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
     	   player.sendMessage(ChatColor.RED + String.format(Locale.get("message.error.permission", Locale.getPlayerLocale(player))));
        }else{  
    	boolean hasEffect = false;
        for (PotionEffect potionEffect : player.getActivePotionEffects()) {
            if (potionEffect.getType().equals(effect) && potionEffect.getDuration() == 25) {
                player.addPotionEffect(new PotionEffect(effect, 30, amplifier, true), true);
                hasEffect = true;
                break;
            }
        }
        if (!hasEffect) {
            player.addPotionEffect(new PotionEffect(effect, 30, amplifier, true), true);
        }
        }

    }

    @Override
    public void init(ConfigurationSection s) {
        amplifier = s.getInt("amplifier");
        effect = PotionEffectType.getByName(s.getString("effect", "heal"));

    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("amplifier", amplifier);
        s.set("effect", effect.getName());

    }

    @Override
    public String getName() {
        return "potiontick";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.potiontick", locale), effect.getName().toLowerCase().replaceAll("_", " "), amplifier + 1);
    }

} public class PowerRainbow extends Power implements PowerRightClick {

    public long cooldownTime = 20;
    public int count = 5;
    private Random random = new Random();

    @Override
    public void rightClick(Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        RPGValue value = RPGValue.get(player, item, "arrow.rainbow");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "arrow.rainbow", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.playSound(player.getLocation(), Sound.SHOOT_ARROW, 1.0f, 1.0f);
            final ArrayList<FallingBlock> blocks = new ArrayList<FallingBlock>();
            for (int i = 0; i < count; i++) {
                FallingBlock block = player.getWorld().spawnFallingBlock(player.getLocation().add(0, 1.8, 0), Material.WOOL, (byte) random.nextInt(16));
                block.setVelocity(player.getLocation().getDirection().multiply(new Vector(random.nextDouble() * 2d + 0.5, random.nextDouble() * 2d + 0.5, random.nextDouble() * 2d + 0.5)));
                block.setDropItem(false);
                blocks.add(block);
            }
            (new BukkitRunnable() {

                ArrayList<Location> fallLocs = new ArrayList<Location>();
                Random random = new Random();

                public void run() {

                    Iterator<Location> l = fallLocs.iterator();
                    while (l.hasNext()) {
                        Location loc = l.next();
                        if (random.nextBoolean()) {
                            Block b = loc.getBlock();
                            if (b.getType() == Material.WOOL) {
                                loc.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.WOOL.getId(), b.getData());
                                b.setType(Material.AIR);
                            }
                            l.remove();
                        }
                        if (random.nextInt(5) == 0) {
                            break;
                        }
                    }

                    Iterator<FallingBlock> it = blocks.iterator();
                    while (it.hasNext()) {
                        FallingBlock block = it.next();
                        if (block.isDead()) {
                            fallLocs.add(block.getLocation());
                            it.remove();
                        }
                    }

                    if (fallLocs.isEmpty() && blocks.isEmpty()) {
                        cancel();
                    }

                }
            }).runTaskTimer(Plugin.plugin, 0, 5);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.rainbow", locale), count, (double) cooldownTime / 20d);
    }

    @Override
    public String getName() {
        return "rainbow";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
        count = s.getInt("count", 5);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
        s.set("count", count);
    }
} public class PowerRumble extends Power implements PowerRightClick {

    public long cooldownTime = 20;
    public int power = 2;
    public int distance = 15;

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
        power = s.getInt("power", 2);
        distance = s.getInt("distance", 15);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
        s.set("power", power);
        s.set("distance", distance);
    }

    @Override
    public void rightClick(final Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        RPGValue value = RPGValue.get(player, item, "rumble.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "rumble.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            final Location location = player.getLocation().add(0, -0.2, 0);
            final Vector direction = player.getLocation().getDirection();
            direction.setY(0);
            direction.normalize();
            BukkitRunnable task = new BukkitRunnable() {

                private int count = 0;

                public void run() {
                    Location above = location.clone().add(0, 1, 0);
                    if (above.getBlock().getType().isSolid() || !location.getBlock().getType().isSolid()) {
                        cancel();
                        return;
                    }

                    Location temp = location.clone();
                    for (int x = -2; x <= 2; x++) {
                        for (int z = -2; z <= 2; z++) {
                            temp.setX(x + location.getBlockX());
                            temp.setZ(z + location.getBlockZ());
                            Block block = temp.getBlock();
                            temp.getWorld().playEffect(temp, Effect.STEP_SOUND, block.getTypeId());
                        }
                    }
                    Entity[] near = getNearbyEntities(location, 1.5);
                    boolean hit = false;
                    Random random = new Random();
                    for (Entity e : near) {
                        if (e != player) {
                            hit = true;
                            break;
                        }
                    }
                    if (hit) {
                        location.getWorld().createExplosion(location.getX(), location.getY(), location.getZ(), power, false, false);
                        near = getNearbyEntities(location, 2.5);
                        for (Entity e : near) {
                            if (e != player)
                                e.setVelocity(new Vector(random.nextGaussian() / 4d, 1d + random.nextDouble() * (double) power, random.nextGaussian() / 4d));
                        }
                        cancel();
                        return;
                    }
                    location.add(direction);
                    if (count >= distance) {
                        cancel();
                    }
                    count++;
                }
            };
            task.runTaskTimer(Plugin.plugin, 0, 3);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public String getName() {
        return "rumble";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.rumble", locale), (double) cooldownTime / 20d);
    }
} public class PowerSkyHook extends Power implements PowerRightClick {
    
    public Material railMaterial = Material.GLASS;
    public int hookDistance = 10;
    
    @Override
    public void rightClick(final Player player) {
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{ 
    	RPGValue isHooking = RPGValue.get(player, item, "skyhook.isHooking");
        if (isHooking == null) {
            isHooking = new RPGValue(player, item, "skyhook.isHooking", false);
        }
        if (isHooking.asBoolean()) {
            player.setVelocity(player.getLocation().getDirection());
            isHooking.set(false);
            return;
        }
        Block block = player.getTargetBlock(null, hookDistance);
        if (block.getType() != railMaterial) {
            player.sendMessage(ChatColor.AQUA + Locale.get("message.skyhook.fail", Locale.getPlayerLocale(player)));
            return;
        }
        isHooking.set(true);
        final Location location = player.getLocation();
        player.setAllowFlight(true);
        player.setVelocity(location.getDirection().multiply(block.getLocation().distance(location) / 2d));
        player.setFlying(true);
        (new BukkitRunnable() {
            
            private int delay = 0;
            
            @Override
            public void run() {
                if (!player.getAllowFlight()) {
                    cancel();
                    RPGValue.get(player, item, "skyhook.isHooking").set(false);
                    return;
                }
                if (!RPGValue.get(player, item, "skyhook.isHooking").asBoolean()) {
                    player.setFlying(false);
                    if (player.getGameMode() != GameMode.CREATIVE) 
                        player.setAllowFlight(false);
                    cancel();
                    return;
                }
                player.setFlying(true);
                player.getLocation(location);
                location.add(0, 2.4, 0);
                if (delay < 20) {
                    delay++;
                    if (location.getBlock().getType() == railMaterial) {
                        delay = 20;
                    }
                    return;
                }
                Vector dir = location.getDirection().setY(0).normalize();
                location.add(dir);
                if (location.getBlock().getType() != railMaterial) {
                    player.setFlying(false);
                    if (player.getGameMode() != GameMode.CREATIVE) 
                        player.setAllowFlight(false);
                    cancel();
                    RPGValue.get(player, item, "skyhook.isHooking").set(false);
                    return;
                }
                player.setVelocity(dir.multiply(0.5));
                
            }
        }).runTaskTimer(Plugin.plugin, 0, 0);
    }
    }
    @Override
    public void init(ConfigurationSection s) {
        railMaterial = Material.valueOf(s.getString("railMaterial", "GLASS"));
        hookDistance = s.getInt("hookDistance", 10);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("railMaterial", railMaterial.toString());
        s.set("hookDistance", hookDistance);
    }

    @Override
    public String getName() {
        return "skyhook";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + Locale.get("power.skyhook", locale);
    }

} public class PowerTNTCannon extends Power implements PowerRightClick {

    public long cooldownTime = 20;

    @Override
    public void rightClick(Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        RPGValue value = RPGValue.get(player, item, "tnt.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "tnt.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            player.playSound(player.getLocation(), Sound.SHOOT_ARROW, 1.0f, 1.0f);
            TNTPrimed tnt = player.getWorld().spawn(player.getLocation().add(0, 1.8, 0), TNTPrimed.class);
            tnt.setVelocity(player.getLocation().getDirection().multiply(2d));
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.tntcannon", locale), (double) cooldownTime / 20d);
    }

    @Override
    public String getName() {
        return "tntcannon";
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown", 20);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
    }
} public class PowerTeleport extends Power implements PowerRightClick, PowerProjectileHit {

    public int distance = 5;
    public long cooldownTime = 20;

    @Override
    public void rightClick(Player player) {
        long cooldown;
        if (item.getHasPermission() == true && player.hasPermission(item.getPermission()) == false){
        }else{
        RPGValue value = RPGValue.get(player, item, "teleport.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "teleport.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            // float dist = 0;
            World world = player.getWorld();
            Location start = player.getLocation();
            start.setY(start.getY() + 1.6);
            // Location current = new Location(world, 0, 0, 0);
            Block lastSafe = world.getBlockAt(start);
            // Keeping the old method because BlockIterator could get removed (irc)
            // double dir = Math.toRadians(start.getYaw()) + (Math.PI / 2d);
            // double dirY = Math.toRadians(start.getPitch()) + (Math.PI / 2d);
            BlockIterator bi = new BlockIterator(player, distance);
            // while (dist < distance) {
            while (bi.hasNext()) {
                // current.setX(start.getX() + dist * Math.cos(dir) *
                // Math.sin(dirY));
                // current.setY(start.getY() + dist * Math.cos(dirY));
                // current.setZ(start.getZ() + dist * Math.sin(dir) *
                // Math.sin(dirY));
                Block block = bi.next();// world.getBlockAt(current);
                if (!block.getType().isSolid() || (block.getType() == Material.AIR)) {
                    lastSafe = block;
                } else {
                    break;
                }
                // dist+= 0.5;
            }
            Location newLoc = lastSafe.getLocation();
            newLoc.setPitch(start.getPitch());
            newLoc.setYaw(start.getYaw());
            player.teleport(newLoc);
            world.playEffect(newLoc, Effect.ENDER_SIGNAL, 0);
            world.playSound(newLoc, Sound.ENDERMAN_TELEPORT, 1.0f, 0.3f);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
        }
    }

    @Override
    public void projectileHit(Player player, Projectile p) {
        long cooldown;
        RPGValue value = RPGValue.get(player, item, "teleport.cooldown");
        if (value == null) {
            cooldown = System.currentTimeMillis() / 50;
            value = new RPGValue(player, item, "teleport.cooldown", cooldown);
        } else {
            cooldown = value.asLong();
        }
        if (cooldown <= System.currentTimeMillis() / 50) {
            value.set(System.currentTimeMillis() / 50 + cooldownTime);
            World world = player.getWorld();
            Location start = player.getLocation();
            Location newLoc = p.getLocation();
            if (start.distanceSquared(newLoc) >= distance * distance) {
                player.sendMessage(ChatColor.AQUA + Locale.get("message.too.far", Locale.getPlayerLocale(player)));
                return;
            }
            newLoc.setPitch(start.getPitch());
            ;
            newLoc.setYaw(start.getYaw());
            player.teleport(newLoc);
            world.playEffect(newLoc, Effect.ENDER_SIGNAL, 0);
            world.playSound(newLoc, Sound.ENDERMAN_TELEPORT, 1.0f, 0.3f);
        } else {
            player.sendMessage(ChatColor.AQUA + String.format(Locale.get("message.cooldown", Locale.getPlayerLocale(player)), ((double) (cooldown - System.currentTimeMillis() / 50)) / 20d));
        }
    }

    @Override
    public void init(ConfigurationSection s) {
        cooldownTime = s.getLong("cooldown");
        distance = s.getInt("distance");
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("cooldown", cooldownTime);
        s.set("distance", distance);
    }

    @Override
    public String getName() {
        return "teleport";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + String.format(Locale.get("power.teleport", locale), distance, (double) cooldownTime / 20d);
    }
} public class PowerUnbreakable extends Power implements PowerHit {

    @SuppressWarnings("deprecation")
    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        player.getItemInHand().setDurability((short) 0);
        player.updateInventory();
    }

    @Override
    public void init(ConfigurationSection s) {

    }

    @Override
    public void save(ConfigurationSection s) {

    }

    @Override
    public String getName() {
        return "unbreakable";
    }

    @Override
    public String displayText(String locale) {
        return ChatColor.GREEN + Locale.get("power.unbreakable", locale);
    }
} public class PowerUnbreaking extends Power implements PowerHit {

    public int level = 1;
    private Random random = new Random();

    @SuppressWarnings("deprecation")
    @Override
    public void hit(Player player, LivingEntity e, double damage) {
        if (random.nextDouble() < ((double) level) / 100d) {
            System.out.println(player.getItemInHand().getDurability());
            player.getItemInHand().setDurability((short) (player.getItemInHand().getDurability() - 1));
            System.out.println(player.getItemInHand().getDurability());
            player.updateInventory();
        }
    }

    @Override
    public void init(ConfigurationSection s) {
        level = s.getInt("level", 1);
    }

    @Override
    public void save(ConfigurationSection s) {
        s.set("level", level);
    }

    @Override
    public String getName() {
        return "unbreaking";
    }

    @Override
    public String displayText(String locale) {
        return String.format(ChatColor.GREEN + Locale.get("power.unbreaking", locale), level);
    }
}
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import think.rpgitems.commands.CommandDocumentation;
import think.rpgitems.commands.CommandGroup;
import think.rpgitems.commands.CommandHandler;
import think.rpgitems.commands.CommandString;
import think.rpgitems.data.Locale;
import think.rpgitems.item.ItemManager;
import think.rpgitems.item.RPGItem;
import think.rpgitems.power.PowerArrow;
import think.rpgitems.power.PowerCommand;
import think.rpgitems.power.PowerConsume;
import think.rpgitems.power.PowerFireball;
import think.rpgitems.power.PowerFlame;
import think.rpgitems.power.PowerFood;
import think.rpgitems.power.PowerIce;
import think.rpgitems.power.PowerKnockup;
import think.rpgitems.power.PowerLifeSteal;
import think.rpgitems.power.PowerLightning;
import think.rpgitems.power.PowerPotionHit;
import think.rpgitems.power.PowerPotionSelf;
import think.rpgitems.power.PowerPotionTick;
import think.rpgitems.power.PowerRainbow;
import think.rpgitems.power.PowerRumble;
import think.rpgitems.power.PowerSkyHook;
import think.rpgitems.power.PowerTNTCannon;
import think.rpgitems.power.PowerTeleport;
import think.rpgitems.power.PowerUnbreakable;
import think.rpgitems.power.PowerUnbreaking;
package think.rpgitems;



public class PowerHandler implements CommandHandler {

    @CommandString("rpgitem $n[] power arrow")
    @CommandDocumentation("$command.rpgitem.arrow")
    @CommandGroup("item_power_arrow")
    public void arrow(CommandSender sender, RPGItem item) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerArrow pow = new PowerArrow();
        pow.cooldownTime = 20;
        pow.item = item;
        item.addPower(pow);
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power arrow $cooldown:i[]")
    @CommandDocumentation("$command.rpgitem.arrow.full")
    @CommandGroup("item_power_arrow")
    public void arrow(CommandSender sender, RPGItem item, int cooldown) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerArrow pow = new PowerArrow();
        pow.item = item;
        pow.cooldownTime = cooldown;
        item.addPower(pow);
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power command $cooldown:i[] $o[left,right] $display:s[] $command:s[]")
    @CommandDocumentation("$command.rpgitem.command")
    @CommandGroup("item_power_command_b")
    public void command(CommandSender sender, RPGItem item, int cooldown, String mouse, String displayText, String command) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerCommand com = new PowerCommand();
        com.cooldownTime = cooldown;
        command = command.trim();
        if (command.charAt(0) == '/') {
            command = command.substring(1);
        }
        com.isRight = mouse.equals("right");
        com.display = displayText;
        com.command = command;
        com.item = item;
        item.addPower(com);
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power command $cooldown:i[] $o[left,right] $display:s[] $command:s[] $permission:s[]")
    @CommandDocumentation("$command.rpgitem.command.full")
    @CommandGroup("item_power_command_a")
    public void command(CommandSender sender, RPGItem item, int cooldown, String mouse, String displayText, String command, String permission) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerCommand com = new PowerCommand();
        com.cooldownTime = cooldown;
        command = command.trim();
        if (command.charAt(0) == '/') {
            command = command.substring(1);
        }
        com.isRight = mouse.equals("right");
        com.display = displayText;
        com.command = command;
        com.permission = permission;
        com.item = item;
        item.addPower(com);
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power command $cooldown:i[] $o[left,right] $details:s[]")
    @CommandDocumentation("$command.rpgitem.command.old")
    @CommandGroup("item_power_command_c")
    public void command(CommandSender sender, RPGItem item, int cooldown, String mouse, String details) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        String[] pArgs = details.split("\\|");
        if (pArgs.length < 2) {
            sender.sendMessage(ChatColor.RED + Locale.get("message.error.command.format", locale));
            return;
        }
        String display = pArgs[0].trim();
        String command = pArgs[1].trim();
        if (command.charAt(0) == '/') {
            command = command.substring(1);
        }
        String permission = "";
        if (pArgs.length > 2) {
            permission = pArgs[2].trim();
        }

        PowerCommand com = new PowerCommand();
        com.cooldownTime = cooldown;

        com.isRight = mouse.equals("right");
        com.item = item;
        com.display = display;
        com.command = command;
        com.permission = permission;

        item.addPower(com);
        item.rebuild();
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power consume")
    @CommandDocumentation("$command.rpgitem.consume")
    @CommandGroup("item_power_consume")
    public void consume(CommandSender sender, RPGItem item) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerConsume pow = new PowerConsume();
        pow.item = item;
        item.addPower(pow);
        ItemManager.save(Plugin.plugin);
        sender.sendMessage(ChatColor.AQUA + Locale.get("message.power.ok", locale));
    }

    @CommandString("rpgitem $n[] power fireball")
    @CommandDocumentation("$command.rpgitem.fireball")
    @CommandGroup("item_power_fireball")
    public void fireball(CommandSender sender, RPGItem item) {
        String locale = sender instanceof Player ? Locale.getPlayerLocale((Player) sender) : "en_GB";
        PowerFireball pow = new PowerFireball();