/*
 * COPYRIGHT (c) 1998-1999 Jan-Henrik Haukeland, http://www.tildeslash.com/
 */

package ts;

import java.awt.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.*;

import ts.config.*;
import ts.biff.*;
import ts.mail.*;
import ts.ui.*;


/** 
 * The main class. The class will load default- and user configuration
 * that determins the setup of the application, and then glue together
 * the main application window and show it.
 *
 * @author  Jan-Henrik Haukeland &lt;hauk@tildeslash.com&gt;
 * @version $Id: Arch.java,v 1.30 2001/08/13 12:48:26 hauk Exp $
 */
public class Arch 
{

  {
    
    Util.setUniversalFont(Font.decode("SansSerif-normal-12"));
    
  }


  private Config               config;
  private Biff                 biff;
  private TerminateController  safe;
  private FetchAgent           agent;
  private Model                model;
  private View                 view;
  private Controller           controller;
  private Splash               splash;


  /** The prime mover */
  public static void main(String[] args) { new Arch(); }



  /**
   * Instantiate the application
   */
  public Arch() 
  {
    try {
      
      safe= TerminateController.createController();

      splash= createSplash();

      splash.print("tsbiff version "+Constant.VERSION);
      try { Thread.sleep(2500); }catch(InterruptedException ie){}


      splash.print("Loading configuration..");
      try { Thread.sleep(1000); }catch(InterruptedException ie){}

      config= Config.getInstance();
     
      loadUserConfiguration();

      setUI();

      try { Thread.sleep(1000); }catch(InterruptedException ie){}

      splash.print("Reading mail...");

      biff= createBiff();

      biff.setVisible(true);

      splash.close();

    }
    catch (Exception e) {
      initializerError(e);
    }

  }      


  /**
   * Create a new instance of the Biff frame.
   */
  public void createNewBiff()
  {
      SwingUtilities.invokeLater(new NewBiff());
  }



  protected class NewBiff implements Runnable 
  {
    public void run()
    {
      controller.removeMailListener(biff);
      controller.removeMailListener(model);
      controller.terminate();
      controller= null;

      view.terminate();
      safe.remove(agent);

      agent=  null;
      model=  null;
      view=   null;

      biff.close();
      biff=  null;
      
      System.gc();
      
      try {
	setUI();
	biff= createBiff();
	biff.setVisible(true);
      } catch (ConfigException ce) {
	initializerError(ce);
      }
    }
  }




  /**
   * Print an Exception message and exit the application
   * @param e Exception to print
   */
  protected void initializerError(Exception e)
  {
    String msg= "Failed to initialize program"+
	"\nReason: "+e.getMessage();
    
    Util.showError(msg);
    
    System.err.println("\n\n"+msg);
    System.exit(1);
  }
  



  /**
   * Create the splash window and show it
   */
  protected Splash createSplash() 
  {
    Splash p= Splash.createSplash();
    p.setFont(Font.decode("helvetica-bold-12"));
    p.setTextColor(Color.black);
    p.show();
    return p;
  }




  /**
   * Assembly the Main application window and return it.
   * @return The main application window
   * @exception ConfigException On error
   */
  protected Biff createBiff() throws ConfigException
  {
    agent=      MailUtil.getFetchAgent();
    model=      new Model();
    view=       new View();
    controller= new Controller(agent);

    // Make agent safe terminate
    safe.add(agent);

    // Glue together the mvc-triad
    controller.addMailListener(model);
    view.setModel(model);
    
    // Set column titles in view
    model.setTitles(MailUtil.getTableTitles());

    // Make a hidden column for Mail-id
    model.setHiddenColumns(1); 

    // Dont paint table titles if it's turned off in Config
    if ( Config.getboolean("mail.table.hidetitles") ) {
      view.getTableHeader().setUI(Util.getNullTableHeaderUI());
    }
   
    // Create the window, and set it as the callback object for the table
    Biff biff= new Biff(this, view, controller);
    view.setCallBack(biff);
    

    return biff;
  }
    



  /** 
   * Load the users local control file into Config. If the file is
   * not found, create a new one with default values and start the 
   * user-configuration dialog to let the user change settings.
   * @exception ConfigException On error
   */
  protected void loadUserConfiguration() throws ConfigException
  {
    File conf= Util.getUserConfigFile();

    if ( conf == null ) {

      config.save(Constant.USER_CONTROL_FILE);
      Configure c= Configure.getInstance();

      if ( splash != null )
	  splash.close();
      
      Util.
	  showInfo("A dialog for configuring the program will\n"+
		   "be displayed when you click the OK button.\n"+
		   "Be careful to configure how you want to \n"+
		   "fetch mail.");

      c.showConfigure();

    } else {
      config.load(conf);
    }
  }




  /**
   * Set the Pluggable Look and Feel and default UI properties. The 
   * method uses the swing class UIManager to set application universial 
   * properties. 
   * @exception ConfigException On error
   */
  protected void setUI() throws ConfigException
  {
    String plaf= null;
    
    try {
	plaf= Config.get("plaf");
	UIManager.setLookAndFeel(plaf);
  
	UIManager.put("TableHeader.font", 
		      Config.getFont("mail.table.header.font"));
	UIManager.put("Table.font", Config.getFont("mail.table.font"));
	UIManager.put("Table.foreground", 
		      Config.getColor("mail.table.fgcolor"));
	UIManager.put("Table.background", 
		      Config.getColor("mail.table.bgcolor"));
	UIManager.put("Table.scrollPaneBorder", 
		      Config.getColor("mail.table.bgcolor"));

    }
    catch ( UnsupportedLookAndFeelException e ) {
      throw new ConfigException("The Look & Feel ("+plaf+") is not \n"+
                     "supported on this platform.\nProgram Terminated");
    }
    catch ( IllegalAccessException e ) {
      throw new ConfigException("The Look & Feel ("+plaf+") could not "+
                                    "be accessed.\n Program Terminated");
    }
    catch ( ClassNotFoundException e ) {
      throw new ConfigException("The Look & Feel ("+plaf+") not found.\n"+
			                             "Program Terminated");
    }   
    catch ( InstantiationException e ) {
      throw new ConfigException("The Look & Feel ("+plaf+") could not be "+
 			              "instantiated.\n Program Terminated");
    }
    catch ( Exception e ) {
      throw new ConfigException("Unexpected error. \nProgram Terminated");
    }
  }


	
}
