import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.*;

public class GestioneMagazzino extends Applet
{
    /* NUOVO: numero di pezzi minimo */
    private static final int MINIMO = 10;

    /* il magazzino che viene gestito */
    private Magazzino magazzino;

    /* file per leggere e scrivere il magazzino */
    private String fileName;

    /* bottoni sull'applet  */ 
    private Button nuovoB=new Button("Nuovo articolo");
    private Button entraB=new Button("Movimento entrata");
    private Button esceB=new Button("Movimento uscita");
    private Button scaricaB=new Button("Scarica articolo");

    /* finestre ausiliarie di dialogo */
    private Dialog4 entraD;
    private Dialog4 esceD;
    private Dialog2 nuovoD;
    private Dialog3 scaricaD;
    private Dialog1 errorD;

    /* COSTRUTTORI */

    public GestioneMagazzino()
    {  magazzino = new Magazzino();  }

    public GestioneMagazzino(String fileName)
    {
	try
        {
	    FileInputStream fis = new FileInputStream(fileName);
	    ObjectInputStream ois = new ObjectInputStream(fis);
	    magazzino = (Magazzino)ois.readObject();
	    ois.close();
            fis.close();
	}
	catch(Exception e)
        {
	    System.out.println(e.getMessage());
	    magazzino = new Magazzino();
	}
	this.fileName=fileName;
    }

    /* INIT */

    public void init()
    {
      /* finestra di dialogo modale per errori */
      errorD=new Dialog1(getFrame(),"Errore",true);
      errorD.addOkListener(new HideListener(errorD));

      /* finestra di dialogo modale per nuovo articolo */
      nuovoD = new Dialog2(getFrame(),"Nuovo articolo",true);
      nuovoD.addOkListener(new EseguiNuovo());
      nuovoD.addClearListener(new ClearListener(nuovoD));
      nuovoD.addDismissListener(new HideListener(nuovoD));

      /* finestra di dialogo modale per entrata */
      entraD = new Dialog4(getFrame(),"Movimento entrata",true);
      entraD.addOkListener(new EseguiEntrata());
      entraD.addClearListener(new ClearListener(entraD));
      entraD.addDismissListener(new HideListener(entraD));
      entraD.addInfoListener(new InfoListener(entraD));

      /* finestra di dialogo modale per uscita */
      esceD = new Dialog4(getFrame(),"Movimento uscita",true);
      esceD.addOkListener(new EseguiUscita());
      esceD.addClearListener(new ClearListener(esceD));
      esceD.addDismissListener(new HideListener(esceD));
      esceD.addInfoListener(new InfoListener(esceD));

      /* finestra di dialogo modale per scarica articolo */
      scaricaD = new Dialog3(getFrame(),"Scarica articolo",true);
      scaricaD.addOkListener(new EseguiScarica());
      scaricaD.addClearListener(new ClearListener(scaricaD));
      scaricaD.addDismissListener(new HideListener(scaricaD));
      scaricaD.addInfoListener(new InfoListener(scaricaD));

      /* Bottoni presenti sull'applet */
      setLayout(new FlowLayout());
      nuovoB.addActionListener(new ShowListener(nuovoD));
      entraB.addActionListener(new ShowListener(entraD));
      esceB.addActionListener(new ShowListener(esceD));
      scaricaB.addActionListener(new ShowListener(scaricaD));  
      add(nuovoB);
      add(entraB);
      add(esceB);
      add(scaricaB);
    }

    /* cerca il Frame in cui e' inserito l'applet e lo ritorna */
    private Frame getFrame()
    {
	Component c=this;
	while (c.getParent()!=null)  c = c.getParent();
	return (Frame) c;
    }

    /* prepara la finestra di dialogo degli errori prima di mostrarla */
    void prepareErrorDialog(String msg)
    {
      Panel p = new Panel(new BorderLayout());
      Label l = new Label(msg);
      p.add(l,BorderLayout.CENTER);
      errorD.addCenter(p);
    }

    /* ACTION LISTENER DEI QUATTRO BOTTONI SULL'APPLET */

    class EseguiNuovo implements ActionListener
    {
	public void actionPerformed(ActionEvent event)
        {
	  try
          {
	    if (nuovoD.scritto1().equals(""))
		    throw new Exception("Inserire descrizione");
            magazzino.nuovoArticolo(nuovoD.scritto1());
            nuovoD.clear();
            nuovoD.setVisible(false);
	  }
	  catch(Exception e)
          { // e.printStackTrace();
             prepareErrorDialog(e.getMessage());
 	     errorD.setVisible(true);    
          }
	}
    }

    class EseguiEntrata implements ActionListener
    {
	public void actionPerformed(ActionEvent event)
        {
	  try
          {
	    if (entraD.scritto1().equals(""))
                    throw new Exception("Inserire codice articolo");
            if (entraD.scritto2().equals(""))
                    throw new Exception("Inserire numero pezzi");
            magazzino.entraArticolo(Integer.parseInt(entraD.scritto2()),
                                    Integer.parseInt(entraD.scritto1()));
            entraD.clear();
            entraD.setVisible(false);
	  }
	  catch(Exception e)
          { // e.printStackTrace();
             prepareErrorDialog(e.getMessage());
 	     errorD.setVisible(true);    
          }
	}
    }

    class EseguiUscita implements ActionListener
    {
	public void actionPerformed(ActionEvent event)
        {
	  try
          {
	    if (esceD.scritto1().equals(""))
		    throw new Exception("Inserire codice articolo");
	    if (esceD.scritto2().equals(""))
		    throw new Exception("Inserire numero pezzi");
            magazzino.esceArticolo(Integer.parseInt(esceD.scritto2()),
                                   Integer.parseInt(esceD.scritto1()));
            /* NUOVO: controlla quanti pezzi son rimasti */
            int codiceArt = Integer.parseInt(esceD.scritto1());
            if (magazzino.articoloPerCodice(codiceArt).numeroPezzi()
                < MINIMO)
            { 
              prepareErrorDialog("Numero di pezzi < " + MINIMO);
              errorD.setVisible(true);
            }
            /* FINE DEL NUOVO */ 
            esceD.clear();
            esceD.setVisible(false);
	  }
	  catch(Exception e)
          { // e.printStackTrace();
             prepareErrorDialog(e.getMessage());
 	     errorD.setVisible(true);    
          }
	}
    }

    class EseguiScarica implements ActionListener
    {
	public void actionPerformed(ActionEvent event)
        {
	  try
          {
	    if (scaricaD.scritto1().equals(""))
		    throw new Exception("Inserire codice articolo");
            magazzino.scaricaArticolo(Integer.parseInt(scaricaD.scritto1()));
            scaricaD.clear();
            scaricaD.setVisible(false);
	  }
	  catch(Exception e)
          { // e.printStackTrace();
             prepareErrorDialog(e.getMessage());
 	     errorD.setVisible(true);    
          }
	}
    }

    /* ACTION LISTENER GENERALI PER GESTIRE LE FINESTRE */

    class ShowListener implements ActionListener
    {
	private Dialog1 dialog;
	public ShowListener(Dialog1 dialog)
	{  this.dialog=dialog;  }
	public void actionPerformed(ActionEvent event)
        {  dialog.setVisible(true);  }
    }

    class HideListener implements ActionListener
    {
	private Dialog1 dialog;
	public HideListener(Dialog1 dialog)
	{ this.dialog=dialog;  }
	public void actionPerformed(ActionEvent event)
        {  dialog.clear(); dialog.setVisible(false);  }
    }

    class ClearListener implements ActionListener
    {
	private Dialog2 dialog;
	public ClearListener(Dialog2 dialog)
	{  this.dialog=dialog;  }
	public void actionPerformed(ActionEvent event)
        {   dialog.clear();  }
    }

    class InfoListener implements ActionListener
    {
        private Dialog3 dialog;
        public InfoListener(Dialog3 dialog)
        {  this.dialog=dialog;  }
        public void actionPerformed(ActionEvent event)
        { 
          int n = -1;
          try 
          {  n  = Integer.parseInt(dialog.scritto1());  }
          catch (NumberFormatException e)
          { // e.printStackTrace();
             prepareErrorDialog(e.getMessage());
             errorD.setVisible(true);
          }
          Articolo presente = magazzino.articoloPerCodice(n);
          String ss1, ss2;
          if (presente!=null)
          {  ss1 = presente.descrizione(); 
             /* NUOVO: la stringa e' diversa se e' sotto il minimo */
             if (presente.numeroPezzi() < MINIMO) 
                ss2 = "*** " + presente.numeroPezzi();
             else  ss2 = "" + presente.numeroPezzi();
          }
          else {  ss1 = ""; ss2 = "";  }
          dialog.info(ss1,ss2);
        }
    }

    /* MAIN (per far girare l'applet come applicazione) */

    public static void main(String[] args)
    {
	Frame frame = new Frame("Gestione magazzino");
	final GestioneMagazzino app;
        if (args.length>0) app=new GestioneMagazzino(args[0]);
	else app=new GestioneMagazzino();
	frame.add(app);
	app.init();
        // nota: prima aggiungere app al frame e poi fare init perche'
        // init ha bisogno del frame per costruire i dialoghi
	frame.pack();
        WindowListener frameListener = new WindowAdapter()
        {
          public void windowClosing(WindowEvent event)
          {
            if (app.fileName==null) app.fileName = "magazzino.txt";
            try
            {
              FileOutputStream fos = new FileOutputStream(app.fileName);
              ObjectOutputStream oos = new ObjectOutputStream(fos);
              oos.writeObject(app.magazzino);
              oos.close();
              fos.close();
            }
            catch(Exception e) {}
            System.exit(0);
          }
        };
	frame.addWindowListener(frameListener);
	frame.setVisible(true); 
    } 
}

/* CLASSI AUSILIARIE PER LE FINESTRE DI DIALOGO */

/* dialogo con solo un bottone ok */
class Dialog1 extends Dialog
{
  protected Button okButton;
  protected Panel lowerPart;
  protected Panel centerPart;

  protected void costruisci()
  {
    setLayout(new BorderLayout());
    okButton = new Button("ok");
    lowerPart = new Panel();
    lowerPart.setLayout(new FlowLayout());
    lowerPart.add(okButton);
    add(lowerPart,BorderLayout.SOUTH);
    centerPart = null;
  }
  public Dialog1(Frame f, String title, boolean modal)
  {
    super(f,title,modal);
    costruisci();
    pack();
  }
  public void addOkListener(ActionListener l)
  {  okButton.addActionListener(l);  }
  public void addCenter(Panel p)
  {  if (centerPart!=null) remove(centerPart);
     add(p,BorderLayout.CENTER);
     centerPart = p;
     pack();
  } 
  public void clear() {}
}

/* dialogo con tre bottoni ok, clear, dismiss e campo di testo per 
   chiedere una stringa (usato qui per descrizione del nuovo articolo,
   ma nella sottoclasse Dialog3 sara' usato per codice dell'articolo
   da scaricare), il campo di testo e' accompagnato da un'etichetta 
   esplicativa)  */
class Dialog2 extends Dialog1
{
  protected Button clearButton;
  protected Button dismissButton;
  protected TextField stringF;   // campo da scrivere

  protected String dicitura() {  return "Descrizione articolo: ";  }
  protected int righe() { return 1; }
  protected void costruisci()
  {
    super.costruisci();
    clearButton = new Button("clear");
    dismissButton = new Button("dismiss");
    lowerPart.add(clearButton);
    lowerPart.add(dismissButton);
    centerPart = new Panel(new GridLayout(righe(),2));
    centerPart.add(new Label(dicitura()));
    centerPart.add(stringF = new TextField(""));
    add(centerPart,BorderLayout.CENTER);
  }

  public Dialog2(Frame f, String title, boolean modal)
  {
    super(f,title,modal);
  }
  public void clear()
  {  stringF.setText("");  }
  public void addClearListener(ActionListener l)
  {  clearButton.addActionListener(l);  }
  public void addDismissListener(ActionListener l)
  {  dismissButton.addActionListener(l);  }
  public void addInfoListener(ActionListener l)
  {  stringF.addActionListener(l);  }
  public String scritto1()
  {  String s = stringF.getText(); s.trim(); return s;  }
}

/* dialogo con tre bottoni ok, clear, dismiss, campo di testo per
   chiedere codice dell'articolo da scaricare e due etichette per
   mostrare descrizione e numero di pezzi di tale articolo; il
   campo di testo e le due etichette sono accompagnati ciascuno da
   un'etichetta esplicativa */
class Dialog3 extends Dialog2
{
  protected Label descrL;   // descrizione articolo
  protected Label numL;     // numero pezzi presenti

  protected String dicitura() {  return "Codice articolo: ";  }
  protected int righe() { return 3; }
  protected void costruisci()
  {
    super.costruisci();
    centerPart.add(new Label("Descrizione: "));
    centerPart.add(descrL = new Label(""));
    centerPart.add(new Label("Pezzi presenti: "));
    centerPart.add(numL = new Label(""));
  }
  public Dialog3(Frame f, String title, boolean modal)
  {
    super(f,title,modal);
  }
  public void clear()
  {  super.clear(); descrL.setText(""); numL.setText("");  }
  public void info(String s1, String s2)
  {  descrL.setText(s1);  numL.setText(s2);  }
}

/* dialogo con tre bottoni ok, clear, due campi di testo per 
   chiedere codice articolo e numero pezzi da far entrare / uscire,
   nonche' due etichette per mostrare descrizione e numero di
   pezzi presenti; i due campi di testo e le due etichette sono
   accompagnati ciascuno da un'etichetta esplicativa */
class Dialog4 extends Dialog3
{
  protected TextField numF;   // numero pezzi da far entrare / uscire

  protected int righe() { return 4; }
  protected void costruisci()
  {
    super.costruisci();
    centerPart.add(new Label("Pezzi da movimentare: "));
    centerPart.add(numF = new TextField(""));
  }
  public Dialog4(Frame f, String title, boolean modal)
  {
    super(f,title,modal);
  }
  public void clear()
  {  super.clear(); numF.setText("");  }
  public String scritto2()
  {  String s = numF.getText(); s.trim(); return s;  }
}