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

import net.mc_pandacraft.java.plugin.pandacraftutils.ConfigManager;
import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.util.NumberConversions;

public class ChatAnalysisPlayer {
	private long time_before_resend_same_message = ConfigManager.getInstance().ChatAnalysis_timeBeforeResendSameMessage;// 30 sec
	private long time_before_resend_same_command = ConfigManager.getInstance().ChatAnalysis_timeBeforeResendSameCommand;// 30 sec
	
	// définit si un message a été tapé super vite ou non
	/* pour un message reçu, on prends la durée depuis le message précédent,
	 * et on le compare au produit de cette variable par le nombre de caractère du nouveau message
	 *  */
	private long time_per_caracter_for_new_message = ConfigManager.getInstance().ChatAnalysis_timePerCaracterForNewMessage;// 0.1 sec
	
	private int max_violation_level = ConfigManager.getInstance().ChatAnalysis_maxViolationLevel;
	
	private int nb_second_for_1_vl_down = ConfigManager.getInstance().ChatAnalysis_nbSecondForOneVLDown;
	
	
	
	
	
	
	
	
	private Player player;
	private PandacraftUtils plugin;
	private String last_message = null;
	private long last_message_time = 0;
	private String last_command = null;
	private long last_command_time = 0;
	
	private int violation_level = 0;
	
	
	public ChatAnalysisPlayer(PandacraftUtils pl, Player p)
	{
		player = p;
		plugin = pl;
	}
	
	
	
	private void addVL(int nb)
	{
		violation_level += nb;
		plugin.getLogger().info("ViolationLevel for player "+player.getDisplayName()+"§r : +"+nb+" -> "+violation_level);
		if (violation_level >= max_violation_level)
			Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
	            @Override
	            public void run() {
	            	player.kickPlayer("Les spams/insultes/publicités sont interdits !");
	            }
	        }, 1L);
			
			
		
		
	}
	
	private void removeVL(int nb)
	{
		violation_level -= nb;
		if (violation_level < 0) violation_level = 0;
	}
	
	
	public int getVL() { return violation_level; }
	public int getMaxVL() { return max_violation_level; }
	
	
	public Player getPlayer() { return player; }
	
	
	
	public void onAsyncPlayerChat(AsyncPlayerChatEvent event)
	{
		if (event.getPlayer() != player)
			return;
		if (event.getPlayer().hasPermission("pandacraft.antispam.exempt"))
			return;
		String message = event.getMessage();
		long time = System.currentTimeMillis();
		if (last_message != null)
		{
			if (last_message.equals(message) && time - last_message_time < time_before_resend_same_message)
			{
				event.getPlayer().sendMessage(ChatColor.RED+"Evitez de renvoyer le même message !");
				if (violation_level >= max_violation_level/2)
					event.setCancelled(true);
				else
					event.setMessage(analyseString(message));
				addVL(5);
				return;
			}
			else
			{
				long  time_since_last_message = time - last_message_time;
				long timeout_needed = message.length() * time_per_caracter_for_new_message;
				if (time_since_last_message < timeout_needed)
				{

					event.getPlayer().sendMessage(ChatColor.RED+"Vous parlez un peu trop vite, ralentissez x)");
					addVL(4);
					event.setMessage(analyseString(message));
					return;
				}
			}
		}
		
		message = analyseString(message);
		
		event.setMessage(message);
		
		removeVL(NumberConversions.floor(((time - last_message_time)/1000)/nb_second_for_1_vl_down));
		
		
		last_message = message;
		last_message_time = time;
	}
	
	public void onPlayerCommandPreprocess (PlayerCommandPreprocessEvent event)
	{
		if (event.getPlayer() != player)
			return;
		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);
				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);
				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);
				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")//	reste à traiter pour la censure
				|| commande.equals("email"))//	reste à traiter pour la censure
		{
			if (last_command != null)
			{
				if (last_command.equals(command_line) && time - last_command_time < time_before_resend_same_command)
				{
					event.getPlayer().sendMessage(ChatColor.RED+"Patientez avant de renvoyer cette commande !");
					if (violation_level >= max_violation_level/2)
						event.setCancelled(true);
					addVL(5);
					event.setMessage(command_line);
					return;
				}
			}
			removeVL(NumberConversions.floor(((time - last_command_time)/1000)/nb_second_for_1_vl_down));
			
			last_command = command_line;
			last_command_time = time;

			event.setMessage(command_line);
		}

	}
	
	
	
	
	private String analyseString(String s)
	{
		
		// é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)
		{
			addVL(nb_duplicated_char/4+1);
			player.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
				addVL(4);
				s = s.toLowerCase();
				player.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}", "**.**.**.**");
			addVL(3);
		}
		
		
		// pour chaque insultes présentes dans la configuration du plugin
		for (String regex : ConfigManager.getInstance().ChatAnalysis_badWords)
		{
			if (s.matches("(?i:(.+[^a-zA-Z]|)"+regex+"(|[^a-zA-Z].+))"))
			{
				s = s.replaceAll("(?i:"+regex+")", "*****");
				addVL(5);
			}
		}
		
		
		return s;
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
