import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* <p>
* Classe récapitulant toutes les actions possibles pour un utilisateur
* </p>
*/

public class ChatApp {
	
	/* Liste des utilisateurs actifs */
	private ListUtilisateurs actifUsers ;
	private static ArrayList<Integer> ListPort = new ArrayList<Integer>();
	private Map<Historique,String> mapHistorique ;
	
	
	
	
	
	
	public static ArrayList<Integer> getListPort() {
		return ListPort;
	}

	/* ChatApp est associé à un utilisateur */
	private Utilisateur me;
	
	 /**
     * Constructeur de l'application de chat
     * 
     * @param pseudo Pseudo de l'utilisateur
     * @param port Port de communication 
     */
	public ChatApp(String pseudo, Integer port){
		this.actifUsers = new ListUtilisateurs() ;
	    // Recuperer adresse IP de l'utilisateur 
		InetAddress ip = null ;
		try {
			ip = InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		//ip.getHostAddress();
		this.me = new Utilisateur(pseudo,port,ip);
		this.actifUsers.addList(getMe());
	}
	
	
	
	/**
     * Modification du pseudo de l'utilisateur 
     * Envoie en broadcast son ancien pseudo et son nouveau
     * 
     * @param nouveau correspond au nouveau pseudo
     */
	public void modifierPseudo(String nouveau) throws IOException {
		// @ de broadcast du réseau de l'utilisateur me 
	    InetAddress broadcastAdress = InetAddress.getLoopbackAddress(); // A MODIFIER 
	    // Message que l'on envoie à tous les utilisateurs actifs
		String broadcastMessage = "Modification Pseudo\n" + this.getMe().getPseudo() + "\n" + nouveau + "\n";
		for(Integer p : ListPort ) {
			if(!(p.equals(this.getMe().getPort())))
			{
				UDPEchange.connexion(broadcastAdress,broadcastMessage, p);
			}
		}
	}
	
	
	/**
     * Methode appelée lors de la connexion d'un nouvel utilisateur. 
     * Il va prévenir les utilisateurs du réseau de son arrivée.
     * 
     */
	public void connexion() throws IOException {
		// @ de broadcast du réseau de l'utilisateur me 
	    InetAddress broadcastAdress = InetAddress.getLoopbackAddress(); // A MODIFIER 
	    // Message que l'on envoie à tous les utilisateurs actifs
		String broadcastMessage = "Connexion\n" + this.getMe().toString() ;
		for(Integer p : ListPort ) {
			if(!(p.equals(this.getMe().getPort())))
			{
				UDPEchange.connexion(broadcastAdress,broadcastMessage, p);
			}
		}
	}
	
	/**
     * Methode appelée lors de la déconnexion de l'utilisateur. 
     * Il va prévenir les utilisateurs du réseau de son départ.
     * 
     */
	public void deconnexion() throws IOException {
		// @ de broadcast du réseau de l'utilisateur me 
	    InetAddress broadcastAdress = InetAddress.getLoopbackAddress(); // A MODIFIER 
	    // Message que l'on envoie à tous les utilisateurs actifs
		String broadcastMessage = "Deconnexion\n" + this.getMe().toString() ;
		for(Integer p : ListPort ) {
			if( !(p.equals(this.getMe().getPort())))
			{
				UDPEchange.connexion(broadcastAdress,broadcastMessage, p);
			}
		}
	}
	
	public static void main (String[] args) throws IOException {
		//Integer p = 2345 ;
		ChatApp app = new ChatApp(args[0],Integer.parseInt(args[1])) ;
		ListPort.add(1234);
		ListPort.add(3000);
		ListPort.add(4000);
		ExecutorService exec = Executors.newFixedThreadPool(1000);
		exec.submit(new Runner(app)); 
		try {
			app.connexion();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if (app.getMe().getPort() == 4000) {
		    try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			app.modifierPseudo("Doudou");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			app.modifierPseudo("Eliot");
			/*try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			app.deconnexion(); */
		}
	}
	public Utilisateur getMe() {
		return me;
	}

	public ListUtilisateurs getActifUsers() {
		return actifUsers;
	}
	
}
class Runner implements Runnable {
    ChatApp app ; 
    public Runner(ChatApp app) {
        this.app = app ;
    }
    @Override
    public void run() {
    	
    	UDPEchange.ecouteUDP(app);
    	
    }
}

