package ftp_client;
import java.util.ArrayList;

// Ordonnanceur de tāches (Upload/Download)
public class Scheduler {

	/* Variables */
	ArrayList<Task> tasks;	  // Liste des taches	
	public boolean autoStart; // Demarrage automatique des taches
	
	private int nb_task; // Nombre de taches en cours
	public int getNbWorkingTask(){ return nb_task; }
	
	public int max_tasks = 2; // Nombre de taches (non-manuelle) possibles en simultanees, pas plus de 2 par defaut

	/* Constructor */
	public Scheduler(){
		tasks		= new ArrayList<Task>();
		autoStart	= false;
		nb_task 	= 0;
	}

	/* Working ? */
	// Si nb_tack superieur a zero, alors l'ordonnanceur est en travail
	public boolean isWorking(){
		return (nb_task > 0);
	}

	/* Add/Remove task */
	// Ajouter une tache, puis demande de demarrage de l'ordonnanceur
	public void addTask(Task tsk){
		tasks.add(tsk);
		Start();
	}
	
	// Suppression d'une tache
	public void removeTask(Task tsk){
		if(tsk == null) return;
		stopTask(tsk); // On arrete la tache avant de la supprimer
		if(!tsk.isDisposed()) tsk.Dispose();
		try{tasks.remove(tsk);}catch(Exception ex){}
	}

	// Suppression de toutes les taches
	public void removeAll(){
		try{
			for(Task tsk : tasks){
				stopTask(tsk);
				if(!tsk.isDisposed()) tsk.Dispose();
			}
			tasks.clear();
		}catch(Exception ex){
			// En cas de probleme, on reinitialise la liste de maniere un peu brutal
			tasks = new ArrayList<Task>(); 
		}
	}
	
	/* Start/Stop task */
	// Demarrage force (elle devient donc manuelle) d'une tache
	public void startTask(final Task tsk){
		startTask(tsk, true);
	}
	// Demarrage d'une tache
	public void startTask(final Task tsk, final boolean force){
		tsk.setAuto(!force); // Elle devient manuelle ou redevient automatique
		if(force || nb_task<max_tasks) tsk.Start(); // Si on force son demarrage ou si il n'y a pas max_tasks taches en cours, on peut la demarrer
	}
	// Arret d'une tache
	public static void stopTask(Task tsk){
		tsk.setAuto(false); // Elle devient manuelle
		tsk.Stop();
	}
	
	/* Start/Stop scheduler */
	// Demarrage de l'ordonnanceur
	public void Start(){
		if( !autoStart ) return; // Si on est pas en demarrage automatique, quitter
		
		// Tant qu'on peut demarrer une tache (c'est a dire qu'on a pas atteind le nombre maximum de taches simultanees et bien sur qu'il en reste), la demarrer
		Task tsk;
		while(nb_task < max_tasks && (tsk = getNextTask()) != null){
			startTask(tsk, false);
			nb_task++;
		}
	}
	// Arret de l'ordonnanceur (arret de toutes les taches, elles deviennent manuelles)
	public void Stop(){
		for(Task tsk : tasks)
			stopTask(tsk);
	}

	/* Get next task to start */
	// Recuperation de la prochaine tache a traiter
	Task getNextTask(){
		for(Task tsk : tasks) // Chercher dans les taches la prochaine qui n'est ni en travail, ni detruite, ni annulee, ni finie, et qui est non-manuelle
			if(!tsk.isWorking() && !tsk.isDisposed() && !tsk.isAborted() && !tsk.isFinished() && tsk.getAuto())
				return tsk; // Puis la retourner
		return null; // Aucune de trouvee, retourner null
	}

	/* Unarbort a task */
	// "De-annuler" une tache
	public static void unAbort(Task tsk){
		tsk.unAbort();
	}

	/* Call by a finishing task */
	// Procedure appelee par une tache (appartenant a cet ordonnanceur evidement) venant de se terminee
	public void taskFinished(Task tsk){
		nb_task--; // Nombre de tache en cours diminue de 1
		if(tsk.getAuto()) Start(); // Si il s'agissait d'une tache non-manuelle, alors on demande a en demarrer une autre
	}

}
