import java.util.*;
import java.io.*;

/**
 * Article vendu dans le magasin
 * L'article peut être un lot d'articles
 *
 * @see Classe Lot
 * @author Richard Grin
 * @version 1.0 10/10/97
 */

public class Article {
  private String reference;
  private String nom;
  private String marque;
  /** prix unitaire */
  private float pu;
  /**
   * Contient les articles référencés
   * Une clé est une référence d'article
   * Elle référence un article
   */
  private static Hashtable articles = new Hashtable();

  /**
   * Crée un article et l'ajoute dans la liste des articles.
   * Les articles ne seront alors plus désignés que par leur référence,
   * en particulier pour modifier leurs caractéristiques.
   */
  public Article(final String uneReference, final String unNom,
                 final String uneMarque, final float unPu)
    throws RefDoubleException {
    reference = uneReference;
    nom = unNom;
    marque = uneMarque;
    pu = unPu;
    ajoute();
  }

  /*
   * Ajoute un article à la liste autorisée des articles
   * On vérifie que la référence n'est pas déjà attribuée à un autre article
   */
  private void ajoute() throws RefDoubleException {
    if (articles.containsKey(reference))
      throw new RefDoubleException(reference);
    else
      articles.put(reference, this);
  }

  public String getReference() {
    return reference;
  }

  public String getNom() {
    return nom;
  }

  /** Retourne la marque de l'objet */
  public String getMarque() {
    return marque;
  }

  public float getPu() { // sera redéfini par Lot
    return pu;
  }

  public String toString() {
    return "Réf. " + reference + " Nom :" + nom + " (" + marque + ") "
           + "PU : " + pu;
  }

  /**
   * Donne un article à partir de sa référence.
   * Ce sera la seule façon de récupérer un article.
   * Renvoie null si aucun article n'a cette référence.
   */
  public static Article getArticle(final String uneRefArticle)
           throws RefExistePasException {
    Article article = (Article)articles.get(uneRefArticle);
    if (article == null)
      throw new RefExistePasException(uneRefArticle);
    else
      return article;
  }

  /** Enregistre tous les articles dans le fichier */
  public static void enregistreArticles(File fichier)
      throws IOException {
    FileOutputStream fos = new FileOutputStream(fichier);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    DataOutputStream dos = new DataOutputStream(bos);
    Article a;
    for (Enumeration e = articles.elements() ; e.hasMoreElements() ;) {
      // Enregistrement d'un article
      a = (Article)(e.nextElement());
      a.enregistreToi(dos);
    }
    dos.close();
  }

  /*
   * Enregistrement de l'article sur le DataOutputStream
   * Sera redéfini dans les sous-classes */
  protected void enregistreToi(String leType, DataOutputStream dos)
       throws IOException {
     dos.writeUTF(leType); // type de l'article pour la lecture
     dos.writeUTF(reference);
     dos.writeUTF(nom);
     dos.writeUTF(marque);
     dos.writeFloat(pu);
  }

  public static void litArticles(File fichier)
      throws IOException, RefExistePasException,
             RefDoubleException {
    FileInputStream fis = new FileInputStream(fichier);
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    String type, reference, nom, marque;
    float pu;
    for (;;) {
      try {
        type = dis.readUTF();
        reference = dis.readUTF();
        nom = dis.readUTF();
        marque = dis.readUTF();
        pu = dis.readFloat();
        if (type.equals("Stylo")) {
          String couleur = dis.readUTF();
          Stylo s = new Stylo(reference, nom, marque, pu, couleur);
        }
        else if (type.equals("Ramette")) {
          float grammage = dis.readFloat();
          Ramette r = new Ramette(reference, nom, marque, pu, grammage);
        }
        else if (type.equals("Lot")) {
          String refArticle = dis.readUTF();
          float quantite = dis.readFloat();
          Lot l = new Lot(reference, refArticle, quantite);
        }
        else
          System.err.println("Type " + type + " inconnu");
      } catch (EOFException e) {
        break; // sortie de la boucle
      }
    }
  }

  protected void enregistreToi(DataOutputStream dos)
       throws IOException {
    enregistreToi("Article", dos);
  }

  /** Donne tous les articles */
  public static Enumeration articles() {
    return articles.elements();
  }

  /** Donne toutes les références d'articles */
  public static Enumeration refArticles() {
    return articles.keys();
  }

  /**
   * Les méthodes suivantes modifient les caractéristiques
   * d'un article.
   * Impossible de modifier une référence.
   */
  public void setNom(final String unNom) {
    nom = unNom;
  }

  public void setMarque(final String uneMarque) {
    marque = uneMarque;
  }

  public void setPu(final float unPu) {
    pu = unPu;
  }
}

