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

import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
import net.mc_pandacraft.java.plugin.pandacraftutils.config.ConfigManager;
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayer;
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager;

import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.util.NumberConversions;

public class ChatAnalysisManager implements Listener {
	
	
	private PandacraftUtils plugin = PandacraftUtils.getInstance();

	public ChatAnalysisManager()
	{
		plugin.getServer().getPluginManager().registerEvents(this, plugin);
	}
	
	@EventHandler(priority=EventPriority.HIGHEST,ignoreCancelled=true)
	public void onAsyncPlayerChat(AsyncPlayerChatEvent event)
	{
		try {
			OnlinePlayer op = OnlinePlayerManager.get(event.getPlayer());
			if (event.getPlayer().hasPermission("pandacraft.antispam.exempt"))
				return;
			String message = event.getMessage();
			long time = System.currentTimeMillis();
			if (op.getLast_message() != null)
			{
				if (op.getLast_message().equals(message) && time - op.getLast_message_time() < ConfigManager.getInstance().defaultConfig.chatAnalysis_timeBeforeResendSameMessage)
				{
					event.getPlayer().sendMessage(ChatColor.RED+"Evitez de renvoyer le même message !");
					if (op.getVL() >= ConfigManager.getInstance().defaultConfig.chatAnalysis_maxViolationLevel/2)
						event.setCancelled(true);
					else
						event.setMessage(analyseString(message, op));
					op.addVL(5);
					return;
				}
				else
				{
					long  time_since_last_message = time - op.getLast_message_time();
					long timeout_needed = message.length() * ConfigManager.getInstance().defaultConfig.chatAnalysis_timePerCaracterForNewMessage;
					if (time_since_last_message < timeout_needed)
					{

						event.getPlayer().sendMessage(ChatColor.RED+"Vous parlez un peu trop vite, ralentissez x)");
						op.addVL(4);
						event.setMessage(analyseString(message, op));
						return;
					}
				}
			}
			
			message = analyseString(message, op);
			
			event.setMessage(message);
			
			op.removeVL(NumberConversions.floor(((time - op.getLast_message_time())/1000)/ConfigManager.getInstance().defaultConfig.chatAnalysis_nbSecondForOneVLDown));
			
			
			op.setLast_message(message);
			op.setLast_message_time(time);
		} catch (NullPointerException e) { }
	}
	
	@EventHandler(priority=EventPriority.HIGHEST)
	public void onPlayerCommandPreprocess (PlayerCommandPreprocessEvent event)
	{
		try {
			OnlinePlayer op = OnlinePlayerManager.get(event.getPlayer());
			if (event.getPlayer().hasPermission("pandacraft.antispam.exempt"))
				return;
			String command_line = event.getMessage();
			String[] command_line_split = event.getMessage().split(" ");
			long time = System.currentTimeMillis();
			String commande = command_line_split[0].substring(1).toLowerCase();
			
			if (commande.equals("")) return;
			
			// traitement du contenu des messages (si elle existe, comme MP ou /me)
			// ici, le message, c'est dès le permier paramètre
			if ((commande.equals("me")
					|| commande.equals("action")
					|| commande.equals("describe")
					|| commande.equals("r")
					|| commande.equals("reply"))
				&& command_line_split.length > 1) {
				try {
					String message = command_line.substring(1+commande.length()+1); //  "/"+commande+" "
					message = analyseString(message, op);
					command_line = "/"+commande+" "+message;
				} catch (IndexOutOfBoundsException e) {  }
				
			}
			// ici, le message, c'est dès le deuxième paramètre
			else if((commande.equals("msg")
					|| commande.equals("m")
					|| commande.equals("tell")
					|| commande.equals("t")
					|| commande.equals("whisper")
					|| commande.equals("w"))
						&& command_line_split.length > 2) {
				try {
					String message = command_line.substring(1+commande.length()
															+1+command_line_split[1].length()
															+1); //  "/"+commande+" "+pseudo+" "
					message = analyseString(message, op);
					command_line = "/"+commande+" "+command_line_split[1]+" "+message;
				} catch (IndexOutOfBoundsException e) {  }
			}
			// ici, le message, c'est dès le troisième paramètre
			else if((commande.equals("mail")
					|| commande.equals("email"))
						&& command_line_split.length > 3) {
				try {
					String message = command_line.substring(1+commande.length()
															+1+command_line_split[1].length()
															+1+command_line_split[2].length()
															+1); //  "/"+commande+" "+sub_command+" "+pseudo+" "
					message = analyseString(message, op);
					command_line = "/"+commande+" "+command_line_split[1]+" "+command_line_split[2]+" "+message;
				} catch (IndexOutOfBoundsException e) {  }
			}
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			if (commande.equals("afk")
					|| commande.equals("away")
					|| commande.equals("time")
					|| commande.equals("day")
					|| commande.equals("night")
					|| commande.equals("me")
					|| commande.equals("action")
					|| commande.equals("describe")
					|| commande.equals("tpa")
					|| commande.equals("call")
					|| commande.equals("tpask")
					|| commande.equals("r")
					|| commande.equals("reply")
					|| commande.equals("msg")
					|| commande.equals("m")
					|| commande.equals("tell")
					|| commande.equals("t")
					|| commande.equals("whisper")
					|| commande.equals("w")
					|| commande.equals("mail")
					|| commande.equals("email"))
			{
				if (op.getLast_command() != null)
				{
					if (op.getLast_command().equals(command_line) && time - op.getLast_command_time() < ConfigManager.getInstance().defaultConfig.chatAnalysis_timeBeforeResendSameCommand)
					{
						event.getPlayer().sendMessage(ChatColor.RED+"Patientez avant de renvoyer cette commande !");
						if (op.getVL() >= ConfigManager.getInstance().defaultConfig.chatAnalysis_maxViolationLevel/2)
							event.setCancelled(true);
						op.addVL(5);
						event.setMessage(command_line);
						return;
					}
				}
				op.removeVL(NumberConversions.floor(((time - op.getLast_command_time())/1000)/ConfigManager.getInstance().defaultConfig.chatAnalysis_nbSecondForOneVLDown));
				
				op.setLast_command(command_line);
				op.setLast_command_time(time);

				event.setMessage(command_line);
			}
		} catch (NullPointerException e) { }
	}
	
	
	
	
	private String analyseString(String s, OnlinePlayer op)
	{
		
		// évite les suites d'au moins 4 caractàres à la suite
		char[] cs = s.toCharArray();
		String r = s.substring(0, (s.length()>=3)?3:s.length());
		int nb_duplicated_char = 0;
		for (int i=3; i<cs.length; i++)
		{
			if (cs[i] == cs[i-1] && cs[i-1] == cs[i-2] && cs[i-2] == cs[i-3])
			{
				nb_duplicated_char++;
				continue;
			}
			
			r = r.concat(String.valueOf(cs[i]));
		}
		
		if (nb_duplicated_char > 0)
		{
			op.addVL(nb_duplicated_char/4+1);
			op.getPlayer().sendMessage(ChatColor.RED+"Evitez les répétitions de caractères !");
			
		}
		
		s = r;
		char[] sChar = s.toCharArray();
		char[] minChar = s.toLowerCase().toCharArray();
		
		
		// vérification des majuscules
		if (sChar.length > 5)
		{
			int nb_caps = 0;
			for (int i=0; i<sChar.length; i++)
				if (sChar[i] != minChar[i])
					nb_caps++;
			
			if (nb_caps * 100 / sChar.length > 70 || nb_caps > 20)
			{
				// si plus de 70% des caractères sont majuscules
				// ou plus de 20 majuscules
				op.addVL(4);
				s = s.toLowerCase();
				op.getPlayer().sendMessage(ChatColor.RED+"Il y a trop de majuscules dans votre message, faites attention avant d'envoyer votre message ;)");
			}
		}
		
		
		
		
		// traiter les insultes et masquage Pub ici
		
		
		// adresse IPv4 basique
		if (s.matches("(.*)([0-9]{1,3}\\.){3}[0-9]{1,3}(:[0-9]{1,5})?(.*)"))
		{
			s = s.replaceAll("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}", "**.**.**.**");
			op.addVL(3);
		}
		
		
		// pour chaque insultes présentes dans la configuration du plugin
		for (String regex : ConfigManager.getInstance().chatBadWordsConfig.getBadWords())
		{
			if (s.matches("(?i:(.+[^a-zA-Z]|)"+regex+"(|[^a-zA-Z].+))"))
			{
				s = s.replaceAll("(?i:"+regex+")", "*****");
				op.addVL(5);
			}
		}
		
		
		return s;
		
	}
	
	
	
	
	
	
	
}
