package controller;

import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

import model.article.Article;
import model.gammeOperatoire.GammeOperatoire;

/**
 * GestionCommande contient les attributs et methodes de gestion d'une commande, et les methodes de calcul de delai
 * @author Magic Penguins
 * @see BaseDonnees#listeGammes
 */
public class GestionCommande {

	/**
	 * Liste des gammes operatoires de la commande
	 * Les gammes operatoires proviennent de la liste des gammes operatoires dans la classe BaseDonnees
	 * @see BaseDonnees#listeGammes
	 */
	public static Vector<GammeOperatoire> listeCommande;
	/**
	 * Liste des articles en rupture de stock lors de la commande
	 * Ils doivent etre fabriques ou commandes au fournisseur
	 */
	public static Vector<Article> listeRupture;
	/**
	 * Resultat du calcul deterministe de delai de la commande
	 * @see GestionCommande#calculerDelaiDeterministe()
	 */
	public static int delaiDeterministe;
	/**
	 * Resultat du calcul stochastique de delai de la commande
	 * @see GestionCommande#delaiStochastique
	 */
	public static double delaiStochastique;


	/**
	 * Recherche et renvoi d'une gamme operatoire dans la commande a partir de sa reference
	 * @param reference
	 * Reference de la gamme operatoire
	 * @return La gamme operatoire recherchee, null si non trouve
	 */
	public static GammeOperatoire getGamme(String reference){
		for (int i=0;i<listeCommande.size();i++){
			if (reference.equals(listeCommande.get(i).getReference())) return listeCommande.get(i);
		}
		return null;
	}

	/**
	 * Ajoute une gamme operatoire dans la commande a partir d'une gamme existante
	 * @param gamme
	 * Gamme operatoire existante
	 */
	public static void ajouterGamme(GammeOperatoire gamme){
		listeCommande.add(gamme);
	}

	/**
	 * Ajoute une gamme operatoire dans la commande a partir de la position de celle-ci dans la liste des gammes operatoires
	 * @param pos
	 * Position de la gamme operatoire dans la liste des gammes operatoires
	 * @return True si l'ajout a reussie, false sinon
	 */
	public static boolean ajouterGamme(int pos){
		if (pos<BaseDonnees.listeGammes.size()) {
			listeCommande.add(BaseDonnees.listeGammes.get(pos));
			return true;
		}
		return false;
	}

	/**
	 * Ajoute une gamme operatoire dans la commande a partir de la reference de celle-ci
	 * @param reference
	 * Reference de la gamme operatoire
	 * @return True si l'ajout a reussie, false sinon
	 */
	public static boolean ajouterGamme(String reference){
		for(int i=0;i<BaseDonnees.listeGammes.size();i++){
			if (reference.equals((String) BaseDonnees.listeGammes.get(i).getReference())){
				listeCommande.add(BaseDonnees.listeGammes.get(i));
				return true;
			}
		}
		return false;
	}

	/**
	 *  Supprime une gamme operatoire a partir d'une reference
	 * @param reference
	 * Reference de la gamme operatoire
	 * @return True si la suppression a reussie, false sinon
	 */
	public static boolean supprimerGamme(String reference){
		for(int i=0;i<listeCommande.size();i++){
			if (reference.equals((String) listeCommande.get(i).getReference())){
				listeCommande.remove(i);
				return true;
			}
		}
		return false;
	}

	/**
	 * Supprime une gamme a partir de sa position dans la commande
	 * @param pos
	 * Position de la gamme operatoire dans la liste
	 * @return True si la suppression a reussie, false sinon
	 */
	public static boolean supprimerGamme(int pos){
		if (pos<listeCommande.size()){
			listeCommande.remove(pos);
			return true;
		}
		else return false;
	}

	/**
	 * Ajoute un article dans la liste des articles en rupture de stock
	 * @param article
	 * Article a ajouter
	 */
	public static void ajouterRupture(Article article){
		GestionCommande.listeRupture.add(article);
	}

	/**
	 * Calcul le delai d'une commande de facon deterministe
	 * Modifie les attributs listeRupture et delaiDeterministe
	 * @see GestionCommande#listeRupture
	 * @see GestionCommande#delaiDeterministe
	 */
	public static void calculerDelaiDeterministe(){
		int tmpDuree = 0;
		for (int i=0;i<listeCommande.size();i++){
			tmpDuree += listeCommande.get(i).calculerDuree();
		}
		delaiDeterministe = tmpDuree;
		Set<Article> set = new HashSet<Article>() ;
		set.addAll(listeRupture) ;
		listeRupture = new Vector<Article>(set) ;
	}

	/**
	 * Calcul le delai d'une commande de facon stochastique a partir du delai deterministe
	 * Modifie les attributs listeRupture et delaiStochastique
	 * @see GestionCommande#listeRupture
	 * @see GestionCommande#delaiStochastique
	 */
	public static void calculerDelaiStochastique(){
		calculerDelaiDeterministe();
		int lambda = delaiDeterministe;
		double sum=0;
		for (int i=0;i<1000;i++){
			double U=Math.random(); // nombre aleatoire
			double A = Math.log(1 - U)*(-lambda);
			sum+=A;

		}
		delaiStochastique = sum/1000;
	}
}
