package net.piratjsk.sddls;

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

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;

import net.piratjsk.sddls.listeners.HorseListener;
import net.piratjsk.sddls.listeners.SigningListener;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.HorseInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;

public final class Sddls extends JavaPlugin {

    public static String noAccessMsg;
    public final static ShapelessRecipe recipe = new ShapelessRecipe(new ItemStack(Material.SADDLE)).addIngredient(Material.SADDLE);

    @Override
    public void onEnable() {
        // config
        this.saveDefaultConfig();
        this.loadConfig();

        // 'sddls' command
        this.getCommand("sddls").setExecutor(new SddlsCommand(this));

        // listeners
        this.getServer().getPluginManager().registerEvents(new SigningListener(), this);
        this.getServer().getPluginManager().registerEvents(new HorseListener(), this);
        // register 'sign saddle' recipe
        this.getServer().addRecipe(recipe);
    }

    public void loadConfig() {
        noAccessMsg = this.getConfig().getString("no-access-msg");
    }
    
    public static boolean isHorse(final Entity entity) {
        final EntityType type = entity.getType();
        return     type.equals(EntityType.HORSE)
                || type.equals(EntityType.SKELETON_HORSE)
                || type.equals(EntityType.ZOMBIE_HORSE)
                || type.equals(EntityType.DONKEY)
                || type.equals(EntityType.MULE);
    }

    public static ItemStack getSaddle(final Entity entity) {
        if (!Sddls.isHorse(entity)) return null;
        final Inventory inv = ((InventoryHolder) entity).getInventory();;
        if (inv instanceof HorseInventory)
            return ((HorseInventory) inv).getSaddle();
        return inv.getItem(0);
    }

    public static ItemStack signSaddle(final ItemStack saddle, final Player player) {
        final ItemMeta meta = saddle.getItemMeta();
        final ArrayList<String> lore = meta.hasLore() ? (ArrayList<String>) meta.getLore() : new ArrayList<String>();
        if (isSigned(saddle)) {
            boolean cleaned = false;
            for (final UUID signature : Sddls.getSignatures(saddle)) {
                if (signature.equals(player.getUniqueId())) {
                    for (final Object line : lore.toArray())
                        if (isUUID(line.toString()))
                            lore.remove(line);
                    cleaned = true;
                    break;
                }
            }
            if (!cleaned) lore.add(player.getUniqueId().toString());
        } else {
            lore.add(player.getUniqueId().toString());
        }
        meta.setLore(lore);
        saddle.setItemMeta(meta);
        return saddle;
    }

    public static boolean hasAccess(final ItemStack saddle, final Entity entity) {
        if (!(entity instanceof Player)) return false;
        if (entity.hasPermission("sddls.bypass")) return true;
        if (isSigned(saddle)) {
            for (final UUID signature : getSignatures(saddle))
                if (signature.equals(entity.getUniqueId()))
                    return true;
            return false;
        }
        return true;
    }

    public static OfflinePlayer getOwner(final ItemStack saddle) {
        if (isSigned(saddle))
            return Bukkit.getOfflinePlayer(getSignatures(saddle).get(0));
        return null;
    }

    public static boolean isSigned(final ItemStack saddle) {
        if (saddle.getItemMeta().hasLore())
            for (String line : saddle.getItemMeta().getLore())
                if (isUUID(line))
                    return true;
        return false;
    }

    public static List<UUID> getSignatures(final ItemStack saddle) {
        final List<UUID> signatures = new ArrayList<UUID>();
        if (saddle.getItemMeta().hasLore())
            for (final String line : saddle.getItemMeta().getLore())
                if (isUUID(line))
                    signatures.add(UUID.fromString(line));
        return signatures;
    }

    private static boolean isUUID(final String uuid) {
        return uuid.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}");
    }

}

@@ -741,46 +741,8 @@
  %7B%0A%0A
-    public static String noAccessMsg;%0A
     
@@ -926,17 +926,27 @@
     
-// c
+this.setupC
 onfig
+();
 %0A   
@@ -959,27 +959,129 @@
 his.
-saveDefault
+registerCommand();%0A        this.registerListeners();%0A        this.registerRecipe();%0A    %7D%0A%0A    private void setup
 Config()
 ;%0A  
@@ -1068,33 +1068,34 @@
 id setupConfig()
-;
+ %7B
 %0A        this.lo
@@ -1092,20 +1092,27 @@
    this.
-load
+saveDefault
 Config()
@@ -1117,35 +1117,51 @@
 ();%0A
-%0A
     
+%7D%0A%0A
     
-// 'sddls' c
+private void registerC
 ommand
+() %7B
 %0A   
@@ -1231,29 +1231,49 @@
 ));%0A
-%0A
     
+%7D%0A%0A
     
-// l
+private void registerL
 isteners
 %0A   
@@ -1268,16 +1268,20 @@
 isteners
+() %7B
 %0A       
@@ -1457,44 +1457,46 @@
     
+%7D%0A%0A
     
-// register 'sign saddle' r
+private void registerR
 ecipe
+() %7B
 %0A   
@@ -1545,113 +1545,8 @@
    %7D
-%0A%0A    public void loadConfig() %7B%0A        noAccessMsg = this.getConfig().getString(%22no-access-msg%22);%0A    %7D
 %0A   

refactor main plugin class a bit