package net.mc_pandacraft.java.plugin.pandacraftutils.simple_commands.staff_player_help;

import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;

import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
import net.mc_pandacraft.java.util.TimeUtil;

import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Score;
import org.bukkit.scoreboard.Scoreboard;

public class CommandStaff implements CommandExecutor, Listener {
	
	private PandacraftUtils plugin;
	
	
	private Queue<WaitingPlayer> playerQueue = new LinkedList<WaitingPlayer>();
	
	private Scoreboard scoreboardPlayerQueue;
	
	
	public CommandStaff(PandacraftUtils pl) {
		plugin = pl;
		plugin.getCommand("staff").setExecutor(this);

		plugin.getServer().getPluginManager().registerEvents(this, plugin);
		
		
		scoreboardPlayerQueue = Bukkit.getScoreboardManager().getNewScoreboard();
	}
	
	

	@Override
	public boolean onCommand(CommandSender sender, Command cmd, String alias,
			String[] args) {
		
		
		
		if (sender instanceof Player && !((Player)sender).hasPermission("pandacraft.grade.staff"))
		{	// un joueur qui n'est pas du staff

			// le joueur est-il déjà en file d'attente ?
			if (getWaitingPlayer((Player)sender) != null) {
				if (args.length > 0 && args[0].equalsIgnoreCase("annuler")) {
					removePlayer((Player)sender);
					updateScoreBoardWaitingList();
					sender.sendMessage(ChatColor.GREEN+"Vous avez été retiré de la file d'attente");
					return true;
				}
				else if (args.length > 0 && args[0].equalsIgnoreCase("position")) {

					sender.sendMessage(ChatColor.GREEN+"Vous êtes à la position "+getPlayerPosition((Player)sender)+" de la file d'attente");
					return true;
				}
				sender.sendMessage(ChatColor.GREEN+"Vous êtes déjà dans la file d'attente");
				sender.sendMessage(ChatColor.GREEN+"Commande : "+ChatColor.GRAY+"/staff position"+ChatColor.RED+" pour connaitre votre position"+
									"ou "+ChatColor.GRAY+"/staff annuler"+ChatColor.RED+" pour sortir de la file d'attente");
				return true;
			}
			// le joueur n'a-t-il pas mis un message en argument de la commande
			if (args.length == 0) {
				sender.sendMessage(ChatColor.GREEN+"Vous n'êtes pas dans la file d'attente");
				sender.sendMessage(ChatColor.GREEN+"Cette file d'attente sers à demander un service à une personne du staff connecté");
				sender.sendMessage(ChatColor.RED+"Commande : "+ChatColor.GRAY+"/staff "+ChatColor.ITALIC+"Message"+
											ChatColor.RED+" pour rentrer dans la file d'attente");
				return true;
			}
			
			playerQueue.add(new WaitingPlayer(((Player)sender).getName(), StringUtils.join(args, " "), ((Player)sender).getLocation()));
			updateScoreBoardWaitingList();
			sender.sendMessage(ChatColor.GREEN+"Veuillez maintenant patienter quelques instant, le temps que le staff traite le début de la file d'attente ;)");
			sender.sendMessage(ChatColor.GREEN+"Vous êtes à la position "+getPlayerPosition((Player)sender)+" de la file d'attente");
			return true;
		}
		else if (sender instanceof Player)
		{	// un joueur du staff
			if (args.length == 0) {
				showWaintingList(sender);
				sender.sendMessage(ChatColor.GOLD+"Pour connaitre les commandes, faites "+ChatColor.GRAY+"/staff ?");
				return true;
			}
			else
			{
				return onCommand_admin_commands(sender, args);
			}
			
		}
		else
		{	// ce n'est pas un joueur (console)
			
			
			if (args.length == 0) {
				showWaintingList(sender);
				return true;
			}
			else
			{
				return onCommand_admin_commands(sender, args);
			}
			
			
		}
		
	}
	
	
	
	
	
	
	private boolean onCommand_admin_commands(CommandSender sender, String[] args) {
		if (args[0].equalsIgnoreCase("?"))
		{	// affichage de l'aide
			sender.sendMessage(ChatColor.GOLD+"--- Commandes administratives pour gérer la file d'attente ---");
			if (sender instanceof Player)
				sender.sendMessage(ChatColor.GRAY+"/staff select <Joueur>"+ChatColor.RESET+" : prendre en charge un joueur de la file");
			sender.sendMessage(ChatColor.GRAY+"/staff remove <Joueur>"+ChatColor.RESET+" : retire un joueur de la file sans le prendre en charge");
			sender.sendMessage(ChatColor.GRAY+"/staff add <Joueur> <Message>"+ChatColor.RESET+" : ajoute un joueur dans la file");
			return true;
		}
		else if (args[0].equalsIgnoreCase("select") && args.length > 1 && sender instanceof Player)
		{
			WaitingPlayer wp = getWaitingPlayer(args[1]);
			if (wp == null) {
				sender.sendMessage(ChatColor.RED+"Le joueur n'est pas dans la liste");
				return true;
			}
			
			
			removePlayer(args[1]);
			updateScoreBoardWaitingList();
			
			
			Player p = plugin.getServer().getPlayerExact(wp.getPlayerName());
			if (p != null && p.isOnline()) {
				// le joueur est en ligne
				sender.sendMessage(ChatColor.GREEN+"-----------------------------------------------");
				sender.sendMessage(p.getName()+ChatColor.RESET+" : "+wp.getMessage()+" - "+ChatColor.ITALIC+"Il y a "+TimeUtil.durationToString((new Date()).getTime() - wp.getDate().getTime()));
				sender.sendMessage(ChatColor.GREEN+"Vous avez été téléporté vers ce joueur");
				((Player)sender).teleport(p.getLocation());
				sender.sendMessage(ChatColor.GREEN+"-----------------------------------------------");

				p.sendMessage(ChatColor.GREEN+"-----------------------------------------------");
				p.sendMessage(((Player)sender).getDisplayName()+ChatColor.RESET+ChatColor.GREEN+" s'occupe maintenant de vous :)");
				p.sendMessage(ChatColor.GREEN+"-----------------------------------------------");
				
			}
			else {
				// le joueur n'est pas en ligne
				sender.sendMessage(ChatColor.GREEN+"-----------------------------------------------");
				sender.sendMessage(wp.getPlayerName()+ChatColor.RESET+" : "+wp.getMessage());
				sender.sendMessage(ChatColor.GREEN+"Vous avez été téléporté vers l'endroit concerné par la demande du joueur");
				((Player)sender).teleport(wp.getLocation());
				sender.sendMessage(ChatColor.GREEN+"-----------------------------------------------");
				return true;
			}
			
			

			
			return true;
			
		}
		else if (args[0].equalsIgnoreCase("remove") && args.length > 1)
		{
			WaitingPlayer wp = getWaitingPlayer(args[1]);
			if (wp == null) {
				sender.sendMessage(ChatColor.RED+"Le joueur n'est pas dans la liste");
				return true;
			}
			
			removePlayer(args[1]);
			updateScoreBoardWaitingList();
			Player p = plugin.getServer().getPlayerExact(wp.getPlayerName());
			if (p != null && p.isOnline()) {
				p.sendMessage(ChatColor.RED+"Vous avez été retiré de la liste des joueurs en attente");
			}
			
			sender.sendMessage(ChatColor.GREEN+wp.getPlayerName()+ChatColor.RESET+ChatColor.GREEN+" a été retiré de la file d'attente");
			
			return true;
			
		}
		else if (args[0].equalsIgnoreCase("add") && args.length > 1)
		{

			Player p = plugin.getServer().getPlayer(args[1]);
			
			if (p == null || !p.isOnline()) {
				sender.sendMessage(ChatColor.RED+"Le joueur n'existe pas ou n'est pas en ligne");
				return true;
			}
			
			WaitingPlayer wp = getWaitingPlayer(p.getName());
			if (wp != null) {
				sender.sendMessage(ChatColor.RED+"Le joueur est déjà dans la liste");
				return true;
			}
			
			
			// on trafique le message pour 2 raisons :
			// - on retire les paramètres qui ne font pas partie du message ("add" et le nom du joueur ajouté)
			// - on les replaces par l'info sur le membre du staff qui l'a ajouté à la liste
			args[0] = ChatColor.ITALIC+"(Ajouté par";
			args[1] = sender.getName() +")"+ ChatColor.RESET;
			String message = StringUtils.join(args, " ");
			
			
			playerQueue.add(new WaitingPlayer(p.getName(),message, p.getLocation()));
			
			updateScoreBoardWaitingList();
			
			sender.sendMessage(ChatColor.GREEN+"Vous venez d'ajouter "+p.getDisplayName()+ChatColor.RESET+ChatColor.GREEN+" dans la file d'attente");
			
			p.sendMessage(ChatColor.GREEN+sender.getName()+" vous a ajouté dans la file d'attente pour traiter votre demande plus tard");
			return true;
		}
		sender.sendMessage(ChatColor.RED+"La commande a mal été tapé");
		return false;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	private WaitingPlayer getWaitingPlayer(String p) {
		for (WaitingPlayer wp : playerQueue)
		{
			if (wp != null && wp.getPlayerName().equalsIgnoreCase(p))
				return wp;
		}
		return null;
	}
	
	
	private WaitingPlayer getWaitingPlayer(OfflinePlayer p) {
		return getWaitingPlayer(p.getName());
	}
	
	
	
	
	private int getPlayerPosition(OfflinePlayer p) {
		int i = 0;
		for (WaitingPlayer wp : playerQueue)
		{
			i++;
			if (wp != null && wp.getPlayerName().equalsIgnoreCase(p.getName()))
				return i;
		}
		return -1;
	}
	

	
	private void removePlayer(String p) {
		WaitingPlayer wp = getWaitingPlayer(p);
		if (wp != null)
			playerQueue.remove(wp);
	}
	private void removePlayer(OfflinePlayer p) {
		removePlayer(p.getName());
	}
	
	
	
	
	
	
	
	
	private void showWaintingList(CommandSender sender) {
		sender.sendMessage(ChatColor.BOLD+"-- File d'attente des joueurs pour le staff --");
		
		int i=0;
		for (WaitingPlayer wp : playerQueue) {
			i++;
			Player p = plugin.getServer().getPlayerExact(wp.getPlayerName());
			String name;
			if (p == null || !p.isOnline())
				name = wp.getPlayerName();
			else
				name = p.getDisplayName();
			
			sender.sendMessage(i+". "+name+ChatColor.RESET+" : "+wp.getMessage()+" - "
					+ChatColor.ITALIC+"Il y a "+TimeUtil.durationToString((new Date()).getTime() - wp.getDate().getTime()));
		}
		sender.sendMessage(ChatColor.BOLD+"-------------------------------------------");
		
	}
	
	
	
	
	
	
	
	
	private void updateScoreBoardWaitingList() {
		Objective obj = scoreboardPlayerQueue.getObjective("file_attente");
		if (obj != null)
			obj.unregister();
		
		
		obj = scoreboardPlayerQueue.registerNewObjective("file_attente", "dummy");
		obj.setDisplayName(ChatColor.GOLD+"File d'attente staff");
		obj.setDisplaySlot(DisplaySlot.SIDEBAR);
		
		int i=0;
		for (WaitingPlayer wp : playerQueue) {
			i++;
			
			Player p = plugin.getServer().getPlayerExact(wp.getPlayerName());
			String name;
			if (p == null || !p.isOnline())
				name = wp.getPlayerName();
			else
				name = p.getPlayerListName();
			
			String line = i+"."+name;
			int boardPos = playerQueue.size()-i+1;
			
			
			Score score = obj.getScore(plugin.getServer().getOfflinePlayer(line.substring(0, (line.length()>16)?16:line.length())));
			
			score.setScore(boardPos);
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	@EventHandler
	public void onPlayerJoin(PlayerJoinEvent event) {
		Player p = event.getPlayer();
		if (p.hasPermission("pandacraft.grade.staff"))
			p.setScoreboard(scoreboardPlayerQueue);
		plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
			@Override public void run() { updateScoreBoardWaitingList(); }
		}, 2L);
		
	}
	
	@EventHandler
	public void onPlayerQuit(PlayerQuitEvent event) {
		plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
			@Override public void run() { updateScoreBoardWaitingList(); }
		}, 2L);
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	private class WaitingPlayer {
		
		private String player;
		private String message;
		private Date creationDate;
		private Location location;
		
		
		public WaitingPlayer(String p, String m, Location l) {
			
			player = p;
			message = m;
			creationDate = new Date();
			location = l;
		}
		
		
		public String getPlayerName() { return player; }
		
		public String getMessage() { return message; }
		
		public Date getDate() { return creationDate; }
		
		public Location getLocation() { return location; }
	}
}
