package model.article;

import java.util.*;

import javax.swing.tree.DefaultMutableTreeNode;

import model.Reference;
import model.gammeOperatoire.GammeOperatoire;



import controller.GestionArticle;
import controller.GestionGamme;

public class Article implements java.io.Serializable{

	private static final long serialVersionUID = -2204027687435428609L;

	////////// Attributs //////////

	protected String designation;
	protected String reference;
	protected int delai;
	protected int stock;
	protected Vector<Nomenclature> nomenclature;
	protected GammeOperatoire gamme;

	////////// Constructeurs //////////

	// Constructeur pour creer un article via l'interface d'ajout d'article, le reference est genere aleatoirement
	public Article(String designation, int delai, int stock){
		this.designation = designation;
		this.delai = delai;
		this.stock = stock;
		this.reference = Reference.genererReference("ART", GestionArticle.cptArticles);
		if (GestionGamme.listeGammesProduction().isEmpty()) this.gamme = new GammeOperatoire("",true);
		else this.gamme = GestionGamme.listeGammesProduction().get(0);
		GestionArticle.cptArticles++;
		this.nomenclature = new Vector<Nomenclature>();
	}

	// Constructeur pour recreer un article via l'interface de deserialisation, le reference est extrait de la sauvegarde de l'article dans le fichier .ser
	public Article(String reference, String designation, int delai, int stock, Vector<Nomenclature> nomenclature, GammeOperatoire gamme){
		this.designation = designation;
		this.delai = delai;
		this.stock = stock;
		this.reference=reference;
		this.gamme = gamme;
		GestionArticle.cptArticles++;
		this.nomenclature = nomenclature;
	}

	////////// Getters et setters //////////

	public String getDesignation() {
		return designation;
	}

	public boolean setDesignation(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;
		}
		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;
	}
	
	// Creation d'un reference d'un article a partir des cinq premieres lettres de la designation et de 5 caracteres pris au hasard
	/*
	public boolean setReference(String designation){

		boolean check;
		String alphabet[] = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"};
		String tmpReference="";
		do{
			check = true;
			// Les cinq premiers caracteres du reference correspond aux cinq premieres lettres de la designation de l'article
			if (designation.length()>=5) tmpReference = designation.substring(0,5);
			else {
				tmpReference = designation.substring(0,designation.length());
				// Si la designation fait moins de 5 lettres cela sera complete par des ":"
				for (int i = 0;i<5-designation.length();i++) tmpReference += ":";
			}
			// Les cinq autres caracteres sont des caracteres aleatoires
			for(int i=0;i<5;i++){
				tmpReference += alphabet[(int) (Math.random()*36)];
			}
			// On verifie que le reference genere n'a pas deja ete affecte a un autre article
			for(int i=0;i<GestionArticle.listeArticles.size();i++){
				if (tmpReference.equals((String) GestionArticle.listeArticles.get(i).getReference())) check = false;
			}
		} while (check == false);
		reference = tmpReference;

	}
	 */
	////////// Methodes //////////

	// Renvoi d'un String contenant les informations d'un article, a afficher si besoin
	public String afficherArticle(){
		String infoArticle="";
		infoArticle += "Designation : "+getDesignation()+"\nReference : "+getReference()+"\nDelai : "+getDelai()+" euros\nStock : "+getStock()+"\n";
		return infoArticle;
	}

	public String toString(){
		return afficherArticle();
	}

	// Ajoute un lien de nomenclature a partir du reference du composant a ajouter et de la quantite voulue
	public boolean ajouterNomenclature (String reference, int quantite){
		// Un article ne peut pas avoir lui-meme comme lien de nomenclature, ou avoir un lien de nomenclature de quantite 0
		/*if (this.reference.equals(reference) || quantite==0) return false;
		for (int i=0;i<nomenclature.size();i++){
			// On ne peut pas ajouter deux fois le meme composant en lien de nomenclature
			if (nomenclature.get(i).getArticle().getReference().equals(reference)) return false;
		}*/
		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
	public boolean ajouterNomenclature (int pos, int quantite){
		// Un article ne peut pas avoir lui-meme comme lien de nomenclature, ou avoir un lien de nomenclature de quantite 0
		if (this.reference.equals(GestionArticle.listeArticles.get(pos).getReference()) || quantite==0) return false;
		for (int i=0;i<nomenclature.size();i++){
			// On ne peut pas ajouter deux fois le meme composant en lien de nomenclature
			if (nomenclature.get(i).getArticle().getReference().equals(GestionArticle.listeArticles.get(pos).getReference())) return false;
		}
		nomenclature.add(new Nomenclature(GestionArticle.listeArticles.get(pos).getReference(),quantite));
		return true;
	}

	// Supprime un lien de nomenclature a partir du reference
	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
	public void supprimerNomenclature (int pos){
		nomenclature.remove(pos);
	}

	/*
	public String afficherNomenclature() {
		return recursionNomenclature("", 0, 1);
	}

	protected String recursionNomenclature (int level, int qte){
		String tab = "	";
		String infoNomenclature = "";
		for (int i=0; i<level; i++) {
			infoNomenclature+=tab;
		}
		infoNomenclature+=this.designation+"("+this.reference+") : "+qte+"\n";
		level++;
		for (Nomenclature n : this.nomenclature)	{
			infoNomenclature+=GestionArticle.getArticle(n.getArticle().getReference()).recursionNomenclature(level, n.getQuantite());
		}
		return infoNomenclature;
	}
	 */
	// Renvoi d'un 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;
	}

	// Renvoi de la racine d'un 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());
		}	
	}

	// Acces aux getters et setters d'un lien de nomenclature de l'article a partir de sa position dans la liste

	public Article getNomenclatureArticle(int pos) {
		return nomenclature.get(pos).getArticle();
	}

	public void setNomenclatureArticle(int pos, Article article) {
		nomenclature.get(pos).setArticle(article);
	}

	public int getNomenclatureQuantite(int pos) {
		return nomenclature.get(pos).getQuantite();
	}

	public void setNomenclatureQuantite(int pos, int quantite) {
		nomenclature.get(pos).setQuantite(quantite);
	}

	public String afficherNomenclature(int pos) {
		String infoNomenclature = "";
		infoNomenclature += getNomenclatureArticle(pos).getDesignation()+" ("+getNomenclatureArticle(pos).getReference()+") x"+getNomenclatureQuantite(pos);
		return infoNomenclature;
	}

}
