package model.article;

import java.util.*;

import javax.swing.tree.DefaultMutableTreeNode;

import model.Reference;
import model.gammeOperatoire.GammeOperatoire;



import controller.BaseDonnees;
import controller.GestionArticle;

/**
 * Objet technique article
 * @author Magic Penguins
 * @see controller.BaseDonnees#listeArticles
 */
public class Article implements java.io.Serializable{

	private static final long serialVersionUID = -2204027687435428609L;

	/**
	 * Designation de l'article
	 */
	protected String designation;
	/**
	 * Reference de l'article
	 */
	protected String reference;
	/**
	 * Delai de fabrication de l'article
	 */
	protected int delai;
	/**
	 * Stock de l'article
	 */
	protected int stock;
	/**
	 * Nomenclature de l'article
	 * Liste de composants dont le niveau de nomenclature est directement inferieura celui de l'article
	 * @see Nomenclature
	 */
	protected Vector<Nomenclature> nomenclature;
	/**
	 * Gamme de production de l'article
	 */
	protected GammeOperatoire gamme;

	/**
	 * Constructeur pour la creation d'un article
	 * @param designation
	 * Designation de l'article
	 * @param delai
	 * Delai de l'article
	 * @param stock
	 * Stock de l'article
	 */
	public Article(String designation, int delai, int stock){
		this.designation = designation;
		this.delai = delai;
		this.stock = stock;
		this.reference = Reference.genererReference("ART", BaseDonnees.cptArticles);
		this.gamme = null;
		BaseDonnees.cptArticles++;
		this.nomenclature = new Vector<Nomenclature>();
	}

	public String getDesignation() {
		return designation;
	}

	/**
	 * Modifie la designation de l'article
	 * Deux articles ne peuvent pas avoir la meme designation
	 * @param designation
	 * @return True si la modification a reussie, false sinon
	 */
	public boolean setDesignation(String designation) {
		for(int i=0;i<BaseDonnees.listeArticles.size();i++){
			if (designation.equals((String) BaseDonnees.listeArticles.get(i).getDesignation()))	return false;
		}
		this.designation = designation;
		return true;
	}

	public int getDelai() {
		return delai;
	}

	public void setDelai(int delai) {
		this.delai = delai;
	}

	public int getStock() {
		return stock;
	}

	public void setStock(int stock) {
		this.stock += stock;
	}

	public String getReference() {
		return reference;
	}

	public Vector<Nomenclature> getNomenclature() {
		return nomenclature;
	}

	public void setNomenclature(Vector<Nomenclature> nomenclature) {
		this.nomenclature = nomenclature;
	}

	public GammeOperatoire getGamme() {
		return gamme;
	}

	public void setGamme(GammeOperatoire gamme) {
		this.gamme = gamme;
	}

	/**
	 * toString d'un article
	 */
	public String toString(){
		return getDesignation()+" ("+getReference()+")";
	}

	/**
	 * Ajoute un lien de nomenclature a partir de la reference du composant a ajouter et de la quantite voulue
	 * @param reference
	 * Reference du composant
	 * @param quantite
	 * Quantite du composant dans la nomenclature de l'article
	 * @return True si l'ajout a reussie, false sinon
	 */
	public boolean ajouterNomenclature (String reference, int quantite){
		nomenclature.add(new Nomenclature(reference,quantite));
		return true;
	}

	/**
	 * Ajoute un lien de nomenclature a partir de la position du composant dans la liste d'articles et de la quantite voulue
	 * @param pos
	 * Position du composant
	 * @param quantite
	 * Quantite du composant dans la nomenclature de l'article
	 * @return True si l'ajout a reussie, false sinon
	 */
	public boolean ajouterNomenclature (int pos, int quantite){
		if (this.reference.equals(BaseDonnees.listeArticles.get(pos).getReference()) || quantite==0) return false;
		for (int i=0;i<nomenclature.size();i++){
			if (nomenclature.get(i).getArticle().getReference().equals(BaseDonnees.listeArticles.get(pos).getReference())) return false;
		}
		nomenclature.add(new Nomenclature(BaseDonnees.listeArticles.get(pos).getReference(),quantite));
		return true;
	}

	/**
	 * Supprime un lien de nomenclature a partir de la reference
	 * @param reference
	 * Reference du composant
	 * @return True si la suppression a reussie, false sinon
	 */
	public boolean supprimerNomenclature (String reference){
		for (int i=0;i<nomenclature.size();i++){
			if (nomenclature.get(i).getArticle().getReference().equals(reference)) {
				nomenclature.remove(i);
				return true;
			}
		}
		return false;
	}

	/**
	 * Supprime un lien de nomenclature a partir de la position
	 * @param pos
	 * Position du composant dans la liste
	 */
	public void supprimerNomenclature (int pos){
		nomenclature.remove(pos);
	}

	/**
	 * Renvoie un String contenant la nomenclature de l'article
	 * @return String contenant la nomenclature de l'article
	 */
	public String afficherNomenclature() {
		return recursionNomenclature(0,1);
	}
	protected String recursionNomenclature (int niveau, int quantite){
		String infoNomenclature = "";
		for (int i=0; i<niveau; i++) {
			infoNomenclature+="  ";
		}
		infoNomenclature+=this.designation+" ("+this.reference+") x"+quantite+"\n";
		niveau++;
		for (Nomenclature n : this.nomenclature){
			infoNomenclature+=GestionArticle.getArticle(n.getArticle().getReference()).recursionNomenclature(niveau, /*quantite**/n.getQuantite());
		}
		return infoNomenclature;
	}

	/**
	 * Renvoie la racine d'un arbre de la nomenclature de l'article
	 * @return la racine de l'arbre de la nomenclature de l'article
	 */
	public DefaultMutableTreeNode convertirArbre(){
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Nomenclature(reference,1));
		recursionArbre (root);
		return root;
	}
	protected void recursionArbre(DefaultMutableTreeNode root){
		for (int i=0;i<nomenclature.size();i++){
			root.add(new DefaultMutableTreeNode(nomenclature.get(i)));
			GestionArticle.getArticle(nomenclature.get(i).getArticle().getReference()).recursionArbre((DefaultMutableTreeNode) root.getLastChild());
		}	
	}

}
