package edu.sc.seis.gee;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import javax.swing.JFrame;
import javax.swing.JWindow;
import javax.swing.UIManager;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Category;
import edu.iris.Fissures.AuditInfo;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.xml.DataSet;
import edu.sc.seis.fissuresUtil.xml.DataSetToXML;
import edu.sc.seis.gee.configurator.ConfigurationException;
import edu.sc.seis.gee.configurator.Configure;
import edu.sc.seis.gee.task.LoadSacFile;

/**
 * Start.java Created: Tue May 15 11:46:26 2001
 * 
 * @author <a href="mailto: "Philip Crotwell </a>
 * @version
 */
public class Start extends JFrame {

    public Start(String name) throws ConfigurationException {
        super(name);
        CommonAccess common = CommonAccess.getCommonAccess();
        splashWin.toFront();
        // load configuration information
        Configure config = common.getConfigure();
        try {
            String filename = System.getProperties()
                    .getProperty("edu.sc.seis.gee.configuration");
            String schemaFilename = "edu/sc/seis/gee/configurator/geeconfigurator.xsd";
            config.load(getReader(filename), true, schemaFilename);
            if(common.getInitialActivity() != null) {
                config.setActivity(common.getInitialActivity());
            }
            logger.debug("finished loading configuration");
        } catch(Exception e) {
            if(e instanceof ConfigurationException) {
                throw (ConfigurationException)e;
            }
            throw new ConfigurationException("Problem loading configuration", e);
        } // end of try-catch
    } // end of start ()

    public static Reader getReader(String filename) throws IOException {
        InputStream in;
        if(filename.startsWith("http:") || filename.startsWith("ftp:")
                || filename.startsWith("file:")) {
            java.net.URL url = new java.net.URL(filename);
            java.net.URLConnection conn = url.openConnection();
            in = conn.getInputStream();
        } else {
            ClassLoader classLoader = Start.class.getClassLoader();
            in = classLoader.getResourceAsStream(filename);
            if(in == null) {
                File f = new File(filename);
                if(!f.exists()) {
                    throw new IOException("Unable to read " + filename);
                }
                in = new FileInputStream(f);
            }
        } // end of else
        return new BufferedReader(new InputStreamReader(in));
    }

    public static void loadDefaultsIntoSystemProperties() {
        GlobalExceptionHandler.registerWithAWTThread();
        if((Start.class).getClassLoader() == null) {
            throw new RuntimeException("Unable to get classloader to load default properties");
        }
        Properties defaultProps = new Properties();
        String defaults = "edu/sc/seis/gee/data/conf/gee.prop";
        try {
            defaultProps.load((Start.class).getClassLoader()
                    .getResourceAsStream(defaults));
        } catch(IOException e) {
            throw new RuntimeException("Could not load defaults. ", e);
        }
        // only override system properties with defaults if they do not
        // already exist
        Enumeration names = defaultProps.propertyNames();
        Properties sysProps = System.getProperties();
        while(names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if(!sysProps.containsKey(key)) {
                sysProps.put(key, defaultProps.get(key));
            }
        } // end of while ()
    }

    public static void main(String[] args) {
        BasicConfigurator.configure();
        try {
            loadDefaultsIntoSystemProperties();
            showSplash();
            CommonAccess common = CommonAccess.getCommonAccess();
            String lafClassname =  UIManager.getSystemLookAndFeelClassName();
            if (!lafClassname.endsWith("GTKLookAndFeel")){
                UIManager.setLookAndFeel(lafClassname);
            }
            common.init(args);
            final Start window = new Start("Global Earthquake Explorer");
            initAppleOnly(window);
            // clean args to remove -props propfile if it is there
            ArrayList<String> cleanArgs = new ArrayList<String>(args.length);
            for(int i = 0; i < args.length; i++) {
                if(args[i].equals("-props") || args[i].equals("-p")
                        || args[i].equals("-config") 
                        || args[i].equals("-activity")) {
                    i++;// eat next arg as well
                } else {
                    cleanArgs.add(args[i]);
                }
            }
            // test to detect MS Windows - SBH
            initMSOnly(cleanArgs, window);
            logger.debug("LOADED FILES: " + loadedFiles);
            if(cleanArgs.size() == 0 && !loadedFiles) {
                common.resetActivity();
                logger.info("After reset");
            } else {
                logger.info("Not doing reset due to: cleanArgs="+cleanArgs.size()+"  loadedFiles="+loadedFiles);
                for (String s : cleanArgs) {
                    logger.info("   cleanArg: "+s);
                }
            }
        } catch(Throwable e) {
            logger.error("Exception in main!:", e);
            GlobalExceptionHandler.handle("A problem occured while starting GEE.",
                                          e);
        } finally {
            if(splashWin != null) {
                splashWin.dispose();
            }
        } // end of try-catch
    }

    private static boolean loadedFiles = false;

    /**
     * Handles open file events that may be sent from the OS at startup This
     * forwards the filenames to handleOpenFile, but performs initialization
     * first.
     */
    public void handleOpenApplication(String[] filenames) {
        logger.debug("handleOpenApplication ");
        if(!loadedFiles) {
            loadedFiles = true;
            CommonAccess ca = CommonAccess.getCommonAccess();
            try {
                logger.debug("opening doSeisDisplay activity");
                ca.resetActivity("SeisDisplay", false);
            } catch(Exception ex) {
                GlobalExceptionHandler.handle("Problem starting SeisDisplay task",
                                              ex);
            }
        }
        for(int i = 0; i < filenames.length; i++) {
            logger.debug("opening file " + filenames[i]);
            handleOpenFile(filenames[i]);
        }
    }

    /**
     * Handles open file events that may be sent from the OS at startup or
     * during program execution. If a sac or dsml file, then these are loaded
     * into the dataset.
     */
    public void handleOpenFile(String filename) {
        logger.debug("handleOpenFile " + filename);
        if(filename == null) {
            return;
        }
        try {
            File file = new File(filename);
            if(filename.endsWith(".dsml")) {
                AuditInfo[] audit = new AuditInfo[1];
                audit[0] = new AuditInfo("load dataset from " + filename,
                                         System.getProperty("user.name"));
                DataSet ds = DataSetToXML.load(file.toURI().toURL());
                CommonAccess.getCommonAccess().getOrganizer().addDataSet(ds,
                                                                         audit);
                try {
                    CommonAccess.getCommonAccess()
                            .getTaskAction("DisplayAllSeismograms")
                            .getTask()
                            .invoke();
                } catch(Exception ex) {
                    GlobalExceptionHandler.handle("Problem starting DisplayAllSeismograms task",
                                                  ex);
                }
            } else {
                LoadSacFile.load(file, true);
            }
        } catch(Exception ex) {
            GlobalExceptionHandler.handle("Problem loading " + filename, ex);
        }
    }

    /**
     * Method showSplash
     */
    public static void showSplash() {
        Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
        Dimension screen = toolkit.getScreenSize();
        Splash splash = new Splash();
        java.awt.Dimension splashDim = splash.getPreferredSize();
        splash.setSize(splashDim);
        splashWin = new JWindow();
        splashWin.getContentPane().add(splash);
        splashWin.setSize(splashDim);
        splashWin.setLocation(screen.width / 2 - (splashDim.width / 2),
                              screen.height / 2 - (splashDim.height / 2));
        try {
            splashWin.show();
            splashWin.toFront();
        } catch(Exception e) {
            // oh well
            logger.warn("problem showing splash", e);
        }
    }

    /**
     * try to initialize apple only extensions, this should only happen on a
     * mac.
     */
    protected static void initAppleOnly(Start gee) {
        if(System.getProperty("mrj.version") != null) {
            try {
                Class appleClass = Class.forName("edu.sc.seis.gee.macOnly.AppleOnly");
                Class[] startClass = {Start.class};
                Constructor c = appleClass.getConstructor(startClass);
                Object[] param = {gee};
                c.newInstance(param);
            } catch(Throwable e) {
                // oh well, not on a mac
                logger.warn("Error loading apple only extensions.", e);
            } // end of try-catch
        }
    }

    /** try to initialize Microsoft only items */
    protected static void initMSOnly(ArrayList cleanArgs, Start window) {
        String osName = System.getProperty("os.name");
        if(osName == null) {
            return;
        }
        if(osName.startsWith("Windows")) {
            try {
                // if this fails then registry.jar is not in classpath,
                // and so we should not try to use ProxySteeings
                Class.forName("com.ice.jni.registry.Registry");
                ProxySettings ps = new ProxySettings();
                if(ps.usesProxy()) {
                    System.setProperty("http.proxyHost", ps.getProxyServer());
                    System.setProperty("http.proxyPort", "" + ps.getProxyPort());
                }
                logger.debug(ps);
            } catch(Throwable e) {
                // oh well, not on a windows pc
                logger.warn("Error loading windows only extensions.", e);
            } // end of try-catch
            if(cleanArgs.size() > 0) {
                // switch to advanced mode and load data
                window.handleOpenApplication((String[])cleanArgs.toArray(new String[0]));
            }
        }
    }

    protected static JWindow splashWin = null;

    static Category logger = Category.getInstance(Start.class.getName());
}// Start
