package org.inventivetalent.npclib.command;

import com.google.common.base.Strings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.inventivetalent.npclib.NPCLibPlugin;
import org.inventivetalent.npclib.NPCType;
import org.inventivetalent.npclib.npc.living.human.NPCPlayer;
import org.inventivetalent.pluginannotations.command.*;

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

public class SpawnCommands {

	private NPCLibPlugin plugin;

	public SpawnCommands(NPCLibPlugin plugin) {
		this.plugin = plugin;
	}

	@Command(name = "spawnNpc",
			 aliases = {},
			 usage = "<Type> [x] [y] [z] [world]",
			 description = "Spawn an NPC at your location or the specified coordinates",
			 min = 1,
			 max = 5,
			 fallbackPrefix = "npclib",
			 errorHandler = FeedbackErrorHandler.class)
	@Permission("npclib.command.spawn")
	public void spawnNPC(CommandSender sender, String typeString, @OptionalArg Double x, @OptionalArg Double y, @OptionalArg Double z, @OptionalArg String worldName) {
		NPCType npcType = NPCType.fromString(typeString);
		if (npcType == null) {
			sender.sendMessage("§cCould not find type for '" + typeString + "'");
			return;
		}
		Location location = parseLocation(sender, x, y, z, worldName);
		if (location == null) { return; }

		plugin.getPluginNpcRegistry().spawnNPC(location, npcType);
		sender.sendMessage("§aNPC spawned at §7" + location.getWorld().getName() + "," + location.getX() + "," + location.getY() + "," + location.getZ());
	}

	@Command(name = "spawnPlayer",
			 aliases = { "spawnNpcPlayer" },
			 usage = "<Name> [x] [y] [z] [world] [skin]",
			 description = "Spawn a Player NPC at your location or the specified coordinates",
			 min = 1,
			 max = 6,
			 fallbackPrefix = "npclib",
			 errorHandler = FeedbackErrorHandler.class)
	@Permission("npclib.command.spawnplayer")
	public void spawnPlayer(CommandSender sender, String name, @OptionalArg Double x, @OptionalArg Double y, @OptionalArg Double z, @OptionalArg String worldName, @OptionalArg String skin) {
		if (name.length() > 16) {
			sender.sendMessage("§cName is too long (" + name.length() + ">16)");
			return;
		}
		Location location = parseLocation(sender, x, y, z, worldName);
		if (location == null) { return; }

		NPCPlayer npc = plugin.getPluginNpcRegistry().spawnPlayerNPC(location, NPCPlayer.class, UUID.randomUUID(), name);
		if (skin == null || skin.isEmpty() && !"none".equals(skin)) {
			skin = name;
		}
		if (!"none".equals(skin)) {
			npc.setSkin(skin);
		}
		sender.sendMessage("§aNPC spawned at §7" + location.getWorld().getName() + "," + location.getX() + "," + location.getY() + "," + location.getZ());
	}

	@Completion(name = "spawnNpc")
	public void spawnNPC(List<String> list, CommandSender sender, String typeString, @OptionalArg Double x, @OptionalArg Double y, @OptionalArg Double z, @OptionalArg String worldName) {
		if (x == null && NPCType.fromString(typeString) == null) {
			for (NPCType npcType : NPCType.values()) {
				list.add(npcType.name());
			}
			return;
		}
		if (x != null && y != null && z != null) {
			for (World world : Bukkit.getWorlds()) {
				list.add(world.getName());
			}
		}
	}

	@Completion(name = "spawnPlayer")
	public void spawnPlayer(List<String> list, CommandSender sender, String name, @OptionalArg Double x, @OptionalArg Double y, @OptionalArg Double z, @OptionalArg String worldName) {
		if (name != null && x != null && y != null && z != null) {
			for (World world : Bukkit.getWorlds()) {
				list.add(world.getName());
			}
		}
	}

	Location parseLocation(CommandSender sender, Double x, Double y, Double z, String worldName) {
		Location location;
		if (sender instanceof Entity) {
			location = ((Entity) sender).getLocation();
			if (x != null) { location.setX(x); }
			if (y != null) { location.setY(y); }
			if (z != null) { location.setZ(z); }
			if (worldName != null) {
				World world = Bukkit.getWorld(worldName);
				if (world == null) {
					sender.sendMessage("§cWorld '" + worldName + "' does not exist");
					return null;
				}
				location.setWorld(world);
			}
		} else {
			if (Strings.isNullOrEmpty(worldName)) {
				sender.sendMessage("§cPlease specify the location");
				return null;
			}
			World world = Bukkit.getWorld(worldName);
			if (world == null) {
				sender.sendMessage("§cWorld '" + worldName + "' does not exist");
				return null;
			}
			location = new Location(world, x, y, z);
		}
		return location;
	}

}

@@ -379,24 +379,74 @@
 .NPCPlayer;%0A
+import org.inventivetalent.npclib.skin.SkinLayer;%0A
 import org.i
@@ -489,16 +489,16 @@
 mand.*;%0A
-
 %0Aimport 
@@ -1714,16 +1714,23 @@
  %22%3CName%3E
+ %5Bskin%5D
  %5Bx%5D %5By%5D
@@ -1741,23 +1741,16 @@
  %5Bworld%5D
- %5Bskin%5D
 %22,%0A%09%09%09 d
@@ -2028,32 +2028,58 @@
 er, String name,
+ @OptionalArg String skin,
  @OptionalArg Do
@@ -2165,34 +2165,8 @@
 Name
-, @OptionalArg String skin
 ) %7B%0A
@@ -2638,16 +2638,52 @@
 n);%0A%09%09%7D%0A
+%09%09npc.setSkinLayers(SkinLayer.HAT);%0A
 %09%09sender
@@ -3360,32 +3360,32 @@
  %22spawnPlayer%22)%0A
-
 %09public void spa
@@ -3438,32 +3438,58 @@
 er, String name,
+ @OptionalArg String skin,
  @OptionalArg Do

move the skin argument