package controller;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;

import javax.swing.tree.DefaultMutableTreeNode;


import model.article.Article;
import model.article.Nomenclature;
import model.gammeOperatoire.GammeOperatoire;



public class GestionArticle {

	////////// Attribut //////////

	// Liste statique des articles
	public static Vector<Article> listeArticles;
	public static int cptArticles;

	////////// Constructeur //////////

	// Constructeur pour l'initialisation de la liste d'articles
	public GestionArticle() {
		listeArticles = new Vector<Article>();
		cptArticles = 1;
	}

	////////// Methodes //////////

	// Renvoi d'un String contenant les informations de tous les articles de la liste, a afficher si besoin
	public static String afficherArticles(){
		Article tmpArticle;
		String infoArticle="";
		for (int i=0;i<listeArticles.size();i++){
			tmpArticle = listeArticles.get(i);
			infoArticle += "Designation : "+tmpArticle.getDesignation()+"\nReference : "+tmpArticle.getReference()+"\nDelai : "+tmpArticle.getDelai()+" euros\nStock : "+tmpArticle.getStock()+"\n";
		}
		return infoArticle;
	}

	// Recherche et renvoi d'un article dans la liste a partir de son reference
	public static Article getArticle(String reference){
		for (int i=0;i<listeArticles.size();i++){
			if (reference.equals(listeArticles.get(i).getReference())) return listeArticles.get(i);
		}
		return null;
	}

	// Serialisation de l'ensemble des articles dans un fichier "articles.ser" a la racine du projet
	/*
	public static void sauvegarderArticles(){
		try {
			FileOutputStream fichier = new FileOutputStream("articles.ser");
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
			for (int i=0;i<listeArticles.size();i++){
				oos.writeObject(listeArticles.get(i));
			}
			oos.flush();
			oos.close();
		}
		catch (java.io.IOException e) {
			e.printStackTrace();
		}
	}
	 */
	public static void sauvegarderArticles(){
		try {
			FileOutputStream fichier = new FileOutputStream("articles.ser");
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
			oos.writeObject(listeArticles);
			oos.writeObject(cptArticles);
			oos.flush();
			oos.close();
		}
		catch (java.io.IOException e) {
			e.printStackTrace();
		}
	}
	// Deserialisation des objets a partir du fichier "articles.ser" situe a la racine du projet
	/*
	public static void restaurerArticles(){
		try {
			FileInputStream fichier = new FileInputStream ("articles.ser");
			ObjectInputStream ois = new ObjectInputStream (fichier);
			Object tmp1;
			Article tmp2;
			while((tmp1 = (Article)ois.readObject()) != null ){
				tmp2 = (Article) tmp1;
				creerArticle(tmp2.getReference(),tmp2.getDesignation(),tmp2.getDelai(),tmp2.getDelais(),tmp2.getStock(),tmp2.getNomenclature());
			}
			ois.close();
		}
		catch (java.io.IOException e) {
			// Fin de la deserialisation
			// e.printStackTrace();
		}
		catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	 */
	@SuppressWarnings("unchecked")
	public static void restaurerArticles(){
		try {
			FileInputStream fichier = new FileInputStream ("articles.ser");
			ObjectInputStream ois = new ObjectInputStream (fichier);
			listeArticles = (Vector<Article>) ois.readObject();
			cptArticles = (Integer) ois.readObject();
			ois.close();
		}
		catch (java.io.IOException e) {
			// Fin de la deserialisation
			// e.printStackTrace();
		}
		catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	// Recherche et renvoi un String contenant les informations de l'article recherche a partir de son reference
	public static String afficherArticle(String reference){
		for(int i=0;i<listeArticles.size();i++){
			if (reference.equals((String) listeArticles.get(i).getReference())){
				Article tmpArticle = listeArticles.get(i);
				String infoArticle="";
				infoArticle += "\nDesignation : "+tmpArticle.getDesignation()+"\nReference : "+tmpArticle.getReference()+"\nDelai : "+tmpArticle.getDelai()+" euros\nStock : "+tmpArticle.getStock()+"\n";
				return infoArticle;
			}
		}
		return "\nArticle non trouve\n";
	}

	// Recherche et renvoi un String contenant les informations de l'article recherche a partir de sa position dans la liste
	public static String afficherArticle(int pos){
		if (pos<listeArticles.size()){
			Article tmpArticle = listeArticles.get(pos);
			String infoArticle="";
			infoArticle += "\nDesignation : "+tmpArticle.getDesignation()+"\nReference : "+tmpArticle.getReference()+"\nDelai : "+tmpArticle.getDelai()+" euros\nStock : "+tmpArticle.getStock()+"\n";
			return infoArticle;
		}
		else return "\nArticle non trouve\n";
	}

	// Cree un article a partir des infos fournies
	public static boolean creerArticle(String designation, int delai, int stock){
		// On ne peut pas avoir deux articles ayant la meme designation
		for(int i=0;i<listeArticles.size();i++){
			if (designation.equals((String) listeArticles.get(i).getDesignation()))	return false;
		}
		listeArticles.add(new Article(designation,delai,stock));
		return true;
	}

	// Recree un article a partir des infos fournies (utilise lors de la deserialisation)
	public static void creerArticle(String reference, String designation, int delai, int stock, Vector<Nomenclature> nomenclature, GammeOperatoire gamme){
		listeArticles.add(new Article(reference,designation,delai,stock,nomenclature,gamme));
	}

	// Supprime un article a partir d'un reference
	public static boolean supprimerArticle(String reference){
		for(int i=0;i<listeArticles.size();i++){
			if (reference.equals((String) listeArticles.get(i).getReference())){
				for (int j=0;j<listeArticles.size();j++){
					for (int k=0;k<listeArticles.get(j).getNomenclature().size();k++){
						if (listeArticles.get(j).getNomenclature().get(k).getArticle().getReference().equals(reference)) listeArticles.get(j).supprimerNomenclature(k);
					}
				}
				listeArticles.remove(i);
				return true;
			}
		}
		return false;
	}

	// Supprime un article a partir de sa position dans la liste
	public static boolean supprimerArticle(int pos){
		if (pos<listeArticles.size()){
			for (int j=0;j<listeArticles.size();j++){
				for (int k=0;k<listeArticles.get(j).getNomenclature().size();k++){
					if (listeArticles.get(j).getNomenclature().get(k).getArticle().getReference().equals(listeArticles.get(pos).getReference())) listeArticles.get(j).supprimerNomenclature(k);
				}
			}
			listeArticles.remove(pos);
			return true;
		}
		else return false;
	}

	public static boolean actualiserArticleNomenclature(Article article){
		for (int i=0;i<listeArticles.size();i++){
			if (listeArticles.get(i).getReference().equals(article.getReference())) {
				listeArticles.get(i).setNomenclature(article.getNomenclature());
				return true;
			}
		}
		return false;
	}

	public static void actualiserArticleNomenclature(Vector<Article> articles){
		for (int j=0;j<articles.size();j++){
			for (int i=0;i<listeArticles.size();i++){
				if (listeArticles.get(i).getReference().equals(articles.get(j).getReference())) {
					listeArticles.get(i).setNomenclature(articles.get(j).getNomenclature());
				}
			}
		}
	}

	// Met a jour la liste des articles a aprtir des informations d'un arbre (root et ses fils)
	public static void convertirListe(DefaultMutableTreeNode root){
		Vector<Nomenclature> newNomenclature = new Vector<Nomenclature>();
		for (int i=0;i<root.getChildCount();i++){
			newNomenclature.add((Nomenclature)((DefaultMutableTreeNode)root.getChildAt(i)).getUserObject());
			convertirListe((DefaultMutableTreeNode) root.getChildAt(i));
		}
		if (!newNomenclature.isEmpty()) GestionArticle.getArticle(((Nomenclature)root.getUserObject()).getArticle().getReference()).setNomenclature(newNomenclature);
	}

	// Renvoi d'une liste de tous les fils et sous-fils d'un noeud
	public static Vector<String> trouverNoeudsFils(DefaultMutableTreeNode root){
		return recursionNoeudsFils(root,new Vector<String>());
	}
	protected static Vector<String> recursionNoeudsFils(DefaultMutableTreeNode root,  Vector<String> liste){
		for (int i=0;i<root.getChildCount();i++){
			liste.add( ((Nomenclature)((DefaultMutableTreeNode)root.getChildAt(i)).getUserObject()).getArticle().getReference() );
			liste = recursionNoeudsFils((DefaultMutableTreeNode)root.getChildAt(i),liste);
		}
		return liste;
	}

	// Renvoi d'une liste de tous les fils et sous-fils d'un noeud
	public static Vector<String> trouverNoeudsPeres(DefaultMutableTreeNode root){
		Vector<String> liste = new Vector<String>();
		while (!root.isRoot()){
			liste.add( ((Nomenclature)((DefaultMutableTreeNode)root.getParent()).getUserObject()).getArticle().getReference());
			root = (DefaultMutableTreeNode)root.getParent();
		}
		return liste;
	}

	// Acces aux getters et setters d'un article a partir de sa position dans la liste
	// ( On ecrit par exemple GestionArticle.getArticleDesignation(i); au lieu de GestionArticle.listeArticles.get(i).getDesignation(); )

	public static String getArticleDesignation(int pos) {
		return listeArticles.get(pos).getDesignation();
	}

	public static boolean setArticleDesignation(int pos, String designation) {
		// On ne peut pas avoir deux articles ayant la meme designation
		for(int i=0;i<GestionArticle.listeArticles.size();i++){
			if (designation.equals((String) GestionArticle.listeArticles.get(i).getDesignation()))	return false;
		}
		listeArticles.get(pos).setDesignation(designation);
		return true;
	}

	public static float getArticleDelai(int pos) {
		return listeArticles.get(pos).getDelai();
	}

	public static void setArticleDelai(int pos, int delai) {
		listeArticles.get(pos).setDelai(delai);
	}

	public static int getArticleStock(int pos) {
		return listeArticles.get(pos).getStock();
	}

	public static void setArticleStock(int pos, int stock) {
		listeArticles.get(pos).setStock(listeArticles.get(pos).getStock()+stock);
	}

	public static String getArticleReference(int pos) {
		return listeArticles.get(pos).getReference();
	}

	public static Vector<Nomenclature> getArticleNomenclature(int pos) {
		return listeArticles.get(pos).getNomenclature();
	}

	// Recherche et renvoi de la position dans la liste de l'article ayant ce reference
	public static int getArticlePos(String reference){
		for (int i=0;i<listeArticles.size();i++){
			if (listeArticles.get(i).getReference().equals(reference)) return i;
		}
		return -1;
	}

	// Acces aux getters et setters d'un article a partir de son reference
	// ( On ecrit par exemple GestionArticle.getArticleDesignation(reference); )

	public static String getArticleDesignation(String reference) {
		return listeArticles.get(getArticlePos(reference)).getDesignation();
	}

	public static boolean setArticleDesignation(String reference, String designation) {
		// On ne peut pas avoir deux articles ayant la meme designation
		for(int i=0;i<GestionArticle.listeArticles.size();i++){
			if (designation.equals((String) GestionArticle.listeArticles.get(i).getDesignation()))	return false;
		}
		listeArticles.get(getArticlePos(reference)).setDesignation(designation);
		return true;
	}

	public static float getArticleDelai(String reference) {
		return listeArticles.get(getArticlePos(reference)).getDelai();
	}

	public static void setArticleDelai(String reference, int delai) {
		listeArticles.get(getArticlePos(reference)).setDelai(delai);
	}

	public static int getArticleStock(String reference) {
		return listeArticles.get(getArticlePos(reference)).getStock();
	}

	public static void setArticleStock(String reference, int stock) {
		listeArticles.get(getArticlePos(reference)).setStock(listeArticles.get(getArticlePos(reference)).getStock()+stock);
	}

	public static Vector<Nomenclature> getArticleNomenclature(String reference) {
		return listeArticles.get(getArticlePos(reference)).getNomenclature();
	}
}
