package net.mc_pandacraft.java.plugin.pandacraftutils.modules;

import java.util.ArrayList;
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.plugin.pandacraftutils.players.OnlinePlayerManager;
import net.mc_pandacraft.java.util.ScoreBoardUtil;
import net.mc_pandacraft.java.util.TimeUtil;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
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.Scoreboard;

public class StaffQueueManager implements Listener {
	
	private PandacraftUtils plugin = PandacraftUtils.getInstance();
	
	
	private Queue<WaitingPlayer> playerQueue = new LinkedList<WaitingPlayer>();
	
	private Scoreboard scoreboardPlayerQueue = Bukkit.getScoreboardManager().getNewScoreboard();
	
	
	public StaffQueueManager() {
		plugin.getServer().getPluginManager().registerEvents(this, plugin);
	}
	
	
	// le joueur ajouté doit-être en ligne
	public void addWaitingPlayer(Player p, String m) {
		if (getWaitingPlayer(p) != null) return; // le joueur est déjà dans la file
		playerQueue.add(new WaitingPlayer(p.getName(), m, p.getLocation()));
		updateScoreBoardWaitingList();
	}
	
	
	
	
	
	public WaitingPlayer getWaitingPlayer(String p) {
		for (WaitingPlayer wp : playerQueue)
		{
			if (wp != null && wp.getPlayerName().equalsIgnoreCase(p))
				return wp;
		}
		return null;
	}
	
	
	public WaitingPlayer getWaitingPlayer(OfflinePlayer p) {
		return getWaitingPlayer(p.getName());
	}
	
	
	
	
	public int getPlayerPosition(OfflinePlayer p) {
		int i = 0;
		for (WaitingPlayer wp : playerQueue)
		{
			i++;
			if (wp != null && wp.getPlayerName().equals(p.getName()))
				return i;
		}
		return -1;
	}
	

	
	public void removePlayer(String p) {
		WaitingPlayer wp = getWaitingPlayer(p);
		if (wp != null)
		{
			playerQueue.remove(wp);
			updateScoreBoardWaitingList();
		}
	}
	public void removePlayer(OfflinePlayer p) {
		removePlayer(p.getName());
	}
	
	
	
	
	
	public WaitingPlayer getSelectedWaitingPlayer(Player staffPlayer) {
		String staffName = staffPlayer.getName();
		for (WaitingPlayer wp : playerQueue)
		{
			if (wp != null && wp.getStaffPlayerName() != null && wp.getStaffPlayerName().equals(staffName))
				return wp;
		}
		return null;
	}
	
	
	
	
	
	public void updateScoreBoardWaitingList() {
		
		// contient les joueurs qui sont associés à un membre du staff
		ArrayList<String> selectedPlayers = new ArrayList<String>();
		
		// contient les joueurs qui ne sont pas encore associés à un membre du staff connecté
		ArrayList<String> newPlayers = new ArrayList<String>();
		
		int i = 1;
		for (WaitingPlayer wp : playerQueue) {
			String line = i+"."+wp.getPlayerDisplayName();
			if (wp.getStaffPlayerName() == null)
				newPlayers.add(line);
			else
				selectedPlayers.add(line);
			i++;
		}
		
		
		// contients les lignes qui vont être affichés dans la sidebar
		ArrayList<String> lines = new ArrayList<String>();
		
		if (!selectedPlayers.isEmpty()) {
			lines.add("En traitement :");
			lines.addAll(selectedPlayers);
		}
		if (!newPlayers.isEmpty()) {
			lines.add("En attente :");
			lines.addAll(newPlayers);
		}
		
		if (!lines.isEmpty()) {
			lines.add("");
			lines.add("Commande :");
			lines.add(ChatColor.GRAY+"   /staff");
		}
		
		ScoreBoardUtil.updateScoreboardSidebar(scoreboardPlayerQueue, ChatColor.GOLD+"File d'attente staff", lines);
	}
	
	
	
	

	public void showWaintingList(CommandSender sender) {
		
		
		sender.sendMessage(ChatColor.BOLD+"--- File d'attente des joueurs pour le staff ---");

		int i=1;
		for (WaitingPlayer wp : playerQueue) {
			
			String staffPlayer = wp.getStaffPlayerName();
			if (staffPlayer != null)
				staffPlayer = " ("+staffPlayer+ChatColor.RESET+")";
			else
				staffPlayer = "";
			
			sender.sendMessage(i+"."+staffPlayer+" "+wp.getPlayerDisplayName()+ChatColor.RESET+" : "+wp.getMessage()+" - "
					+ChatColor.ITALIC+"Il y a "+TimeUtil.durationToString((new Date()).getTime() - wp.getDate().getTime()));
			i++;
		}
		sender.sendMessage(ChatColor.BOLD+"-------------------------------------------");
		
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	@EventHandler
	public void onPlayerJoin(PlayerJoinEvent event) {
		Player p = event.getPlayer();
		if (OnlinePlayerManager.get(p).isInStaff())
			p.setScoreboard(scoreboardPlayerQueue);
		plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
			@Override public void run() { updateScoreBoardWaitingList(); }
		}, 2L);
		
	}
	
	@EventHandler
	public void onPlayerQuit(PlayerQuitEvent event) {
		
		// on vérifie si un membre du staff se déconnecte
		for (WaitingPlayer wp : playerQueue) {
			if (wp.getStaffPlayerName() != null && wp.getStaffPlayerName().equals(event.getPlayer().getName()))
				wp.setStaffPlayer(null);
		}
		
		plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
			@Override public void run() { updateScoreBoardWaitingList(); }
		}, 2L);
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	public class WaitingPlayer {
		
		private String player;
		private String message;
		private Date creationDate = new Date();
		private Location location; // localisation du joueur au moment où il fait /staff
		private String staffPlayer = null;
		
		
		public WaitingPlayer(String p, String m, Location l) {
			
			player = p;
			message = m;
			location = l;
		}
		
		/**
		 * 
		 * @return le pseudo du joueur
		 */
		public String getPlayerName() { return player; }
		
		/**
		 * 
		 * @return le pseudo du joueur, avec la coloration si il est connecté
		 */
		public String getPlayerDisplayName() {
			Player p = plugin.getServer().getPlayerExact(player);
			if (p == null || !p.isOnline())
				return player;
			else
				return p.getPlayerListName();
		}
		
		public String getMessage() { return message; }
		
		public Date getDate() { return creationDate; }
		
		public Location getLocation() { return location; }
		
		public void setStaffPlayer(Player p) {
			if (p == null) staffPlayer = null;
			else staffPlayer = p.getName();
			updateScoreBoardWaitingList();
		}
		public String getStaffPlayerName() { return staffPlayer; }
	}
}
