package chatapp.Protocol;

import chatapp.Controller.ChatApp;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * <p>
 *     Classe permettant de gérer les multiples connexions en TCP.
 *     <br> Extend la classe Thread.
 * </p>
 */
public class RunnerEcouteTCP extends Thread {
    public ChatApp app ;
    private PropertyChangeSupport pcs;
    // on conserve les sessions actives dans un attribut liste
    private ArrayList<SessionClavardage> ListeSessions = new ArrayList<>();

    /**
     * Constructeur
     * @param app Un RunnerEcouteTCP est toujours associé a une application de Chat
     */
    public RunnerEcouteTCP(ChatApp app) {
        this.app = app ;
        this.pcs = new PropertyChangeSupport(this);
        this.start();
    }

    /**
     * Permet aux classes qui appellent cette methode de connecter un PropertyChangeListener au PropertyChangeSupport
     * @param pcl Le propertyChangeListener qui va ecouter les evenements du propertyChangeSupport associe
     */
    public void addPropertyChangeListener(PropertyChangeListener pcl) {
        this.pcs.addPropertyChangeListener("NouvelleSession",pcl);
    }

    /**
     * <p>
     * Methode pour qu'un objet de la classe ChatApp soit constamment en a l'écoute de potentielles connexions
     * @param app L'utilisateur en ecoute de potentielles communications
     * </p>
     */
    public void ecouteTCP(ChatApp app) {
        ServerSocket ss;
        System.out.println("Ecoute TCP activee");
        try {
            ss = new ServerSocket(5000); // On ecoute sur le port 5000
            System.out.println("Socket d'ecoute cree");
            while(true) { // Ecoute en boucle
                System.out.println("Attente Session de clavardage");
                Socket link = ss.accept(); // Blocante
                SessionClavardage session = new SessionClavardage(link,app);
                this.ListeSessions.add(session);
                pcs.firePropertyChange("NouvelleSession",false,true);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Méthode permettant d'ajouter une session active dans la liste 'ListeSessions'
     * @param session Session Active que l'on souhaite rajouter
     */
    public void addSession(SessionClavardage session){
        this.ListeSessions.add(session);
        pcs.firePropertyChange("NouvelleSession",false,true);
    }

    /**
     * Méthode permettant de recupérer la derniere session de clavardage créée dans 'ListeSessions'
     * @return Premiere Session Active
     */
    public SessionClavardage getSessionClavardage() {
        return(this.ListeSessions.remove(0));
    }

    /**
     * Méthode qui vient écraser la méthode run de la classe Thread.
     * La méthode 'ecouteTCP' est appelé.
     */
    @Override
    public void run() {
        ecouteTCP(this.app);
    }

}