/*
 * (c) Copyright: Artenum SARL, 101-103 Boulevard Mac Donald, 
 *                75019, Paris, France 2005.
 *                http://www.artenum.com
 *
 * License:
 *
 *  This program is free software; you can redistribute it 
 *  and/or modify it under the terms of the Q Public License; 
 *  either version 1 of the License.
 * 
 *  This program is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 *  PURPOSE. See the Q Public License for more details.
 * 
 *  You should have received a copy of the Q Public License 
 *  License along with this program;
 *  if not, write to:
 *    Artenum SARL, 101-103 Boulevard Mac Donald,
 *    75019, PARIS, FRANCE, e-mail: contact@artenum.com
 */

package com.artenum.cassandra.launcher;

import java.awt.BorderLayout;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuBar;

/**
 * Main launcher for Cassandra.
 * 
 * @author Sebastien Jourdain, Julien Forest, ARTENUM SARL
 * 
 * @version 2.0
 */
public class Run {

    public static final String CASSANDRA_HOME = "cassandra.home";
    public static final String CASSANDRA_PREF_PUGIN_DIR = "cassandra.pref.plugin.dir";
    public static final String CASSANDRA_PREF_VTK_FILE_DIR = "cassandra.pref.vtk.file.dir";
    public static final String CASSANDRA_PREF_IMG_SAVE_DIR = "cassandra.pref.image.save.dir";
    public static final String CASSANDRA_PREF_SCRIPT_DIR = "cassandra.pref.script.dir";
    public static final String CASSANDRA_PREF_AUTO_UPDATE = "cassandra.pref.auto.update";

    public static void main(final String[] args) throws Exception {
        System.out.println("Launcher starting... ");

        final ArrayList<String> inputFileList = new ArrayList<String>();

        // properties loading
        try {
            if (args.length > 0) {
                System.out.println("Loading properties file: " + args[0]);
                PropertyLoader.loadProperties(args[0]);
                int index = 1;
                String arg;

                while (index < args.length) {
                    arg = args[index];
                    System.out.println(arg);
                    inputFileList.add(arg);
                    index++;
                }
            } else {
                System.out.println("Given properties file not found. Try to load the default properties file.");
                PropertyLoader.loadProperties("./config.properties");
            }
        } catch (final Exception e) {
            System.err.println("Error impossible to load any property file.");
            e.printStackTrace();
        }

        // If nothing is set, we use the default Cassandra's project structure to set the
        // properties
        if (System.getenv().get("CASSANDRA_HOME") != null) {
            System.setProperty(CASSANDRA_HOME, System.getenv().get("CASSANDRA_HOME"));
            System.out.println("cassandra.hoem set from the sytem to: " + System.getenv().get("CASSANDRA_HOME"));
        } else if (System.getProperty(CASSANDRA_HOME) != null) {
            System.out.println("cassandra.home set from the properties fiel to: " + System.getProperty(CASSANDRA_HOME));
        } else {
            System.out.println("cassandra.home not pre-set. Set to user.dir");
            System.setProperty(CASSANDRA_HOME, System.getProperty("user.dir"));
            System.out.println("cassandra.home arbitrary set to: " + System.getProperty(CASSANDRA_HOME));
        }

        final HashMap<String, String> defaultPropertiesMap = new HashMap<String, String>();
        defaultPropertiesMap.put(CASSANDRA_PREF_PUGIN_DIR, System.getProperty(CASSANDRA_HOME) + File.separatorChar
                + "plugin");
        defaultPropertiesMap.put(CASSANDRA_PREF_VTK_FILE_DIR, System.getProperty(CASSANDRA_HOME) + File.separatorChar
                + "Data");
        defaultPropertiesMap.put(CASSANDRA_PREF_IMG_SAVE_DIR, System.getProperty(CASSANDRA_HOME) + File.separatorChar
                + "Views");
        defaultPropertiesMap.put(CASSANDRA_PREF_SCRIPT_DIR, System.getProperty(CASSANDRA_HOME) + File.separatorChar
                + "Script");
        defaultPropertiesMap.put(CASSANDRA_PREF_AUTO_UPDATE, "true");
        PropertyLoader.validateProperties(defaultPropertiesMap);

        final Iterator<String> iter = defaultPropertiesMap.keySet().iterator();
        String keyTmp;
        while (iter.hasNext()) {
            keyTmp = iter.next();
            System.out.println(keyTmp.toString() + "= " + System.getProperty(keyTmp));
        }

        // Management of the dynamic class paths
        // Load thirdpart
        final String pathSep = System.getProperty("path.separator");
        if (System.getProperty("java.class.path") != null) {
            final String[] classPath = System.getProperty("java.class.path").split(pathSep);
            File jarFile = null;
            for (int i = 0; i < classPath.length; i++) {
                System.out.println("Add to classpath= " + System.getProperty(CASSANDRA_HOME) + File.separatorChar
                        + classPath[i]);
                jarFile = new File(System.getProperty(CASSANDRA_HOME) + File.separatorChar + classPath[i]);
                DynamicClassLoader.getInstance().addJar(jarFile);
            }
        }

        // /////////////////////////////////////////////
        // Build the of the Main Cassandra Application
        // /////////////////////////////////////////////

        // instanciation of the Cassandra itself...
        final Class<?> cassandraClassLoader = DynamicClassLoader.getInstance().loadClass(
                "com.artenum.cassandra.Cassandra");
        final Object cassandra = cassandraClassLoader.newInstance();

        final JFrame f = new JFrame("Cassandra VTK viewer");
        f.setJMenuBar((JMenuBar) cassandraClassLoader.getMethod("getDefaultMenu", new Class[] {}).invoke(cassandra,
                new Object[] {}));

        // set the exit action of the frame itself
        // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        final Class<?> advancedWindowListenerClassLoader = DynamicClassLoader.getInstance().loadClass(
                "com.artenum.cassandra.action.AdvancedWindowsEventListener");
        final WindowListener winListener = (WindowListener) advancedWindowListenerClassLoader.newInstance();
        f.addWindowListener(winListener);

        f.getContentPane().add(
                (JComponent) cassandraClassLoader.getMethod("getDefaultToolBar", new Class[] {}).invoke(cassandra,
                        new Object[] {}), BorderLayout.NORTH);
        f.getContentPane().add(
                (JComponent) cassandraClassLoader.getMethod("getDefaultUI", new Class[] {}).invoke(cassandra,
                        new Object[] {}), BorderLayout.CENTER);

        // set the initial size of the application
        f.setSize(1024, 700);
        f.setLocationRelativeTo(null);

        // Loading of plug-ins
        if (System.getProperty(CASSANDRA_PREF_PUGIN_DIR) != null) {
            String plugInPath = "";
            if (System.getProperty(CASSANDRA_HOME) != null) {
                plugInPath = System.getProperty(CASSANDRA_HOME) + File.separatorChar;
            }
            plugInPath = plugInPath + System.getProperty(CASSANDRA_PREF_PUGIN_DIR);
            System.out.println("plugInPath =" + plugInPath);
            final File pluginDir = new File(plugInPath);
            if (pluginDir.exists()) {
                cassandraClassLoader.getMethod("loadPluginInDirectory", new Class[] { File.class }).invoke(cassandra,
                        new Object[] { pluginDir });
            }
        }

        // set preferences done in config file now...

        // set the preferences of Cassandra it-self
        cassandraClassLoader.getMethod("setPreference", new Class[] { String.class, Object.class }).invoke(cassandra,
                new Object[] { CASSANDRA_PREF_AUTO_UPDATE, System.getProperty(CASSANDRA_PREF_AUTO_UPDATE) });

        String imagePath = "";
        if (System.getProperty(CASSANDRA_HOME) != null) {
            imagePath = System.getProperty("cassandra.home") + File.separatorChar;
        }
        imagePath = imagePath + System.getProperty(CASSANDRA_PREF_IMG_SAVE_DIR);
        cassandraClassLoader.getMethod("setPreference", new Class[] { String.class, Object.class }).invoke(cassandra,
                new Object[] { CASSANDRA_PREF_IMG_SAVE_DIR, new File(imagePath) });

        // set the plug-ins directory path
        cassandraClassLoader.getMethod("setPreference", new Class[] { String.class, Object.class }).invoke(cassandra,
                new Object[] { CASSANDRA_PREF_PUGIN_DIR, new File(System.getProperty(CASSANDRA_PREF_PUGIN_DIR)) });

        // set the default dir for the loaded files
        cassandraClassLoader.getMethod("setPreference", new Class[] { String.class, Object.class })
                .invoke(cassandra,
                        new Object[] { CASSANDRA_PREF_VTK_FILE_DIR,
                                new File(System.getProperty(CASSANDRA_PREF_VTK_FILE_DIR)) });

        // set the scripts path
        String scriptPath = "";
        if (System.getProperty(CASSANDRA_HOME) != null) {
            scriptPath = System.getProperty(CASSANDRA_HOME) + File.separatorChar;
        }
        scriptPath = scriptPath + System.getProperty(CASSANDRA_PREF_SCRIPT_DIR);
        cassandraClassLoader.getMethod("setPreference", new Class[] { String.class, Object.class }).invoke(cassandra,
                new Object[] { CASSANDRA_PREF_SCRIPT_DIR, new File(scriptPath) });

        // Set the exit method for the Cassandra application it-self
        final Object cassandraActionManager = cassandraClassLoader.getMethod("getActionManager", new Class[] {})
                .invoke(cassandra, new Object[] {});

        // exit without confirmation
        // cassandraActionManager.getClass().getMethod("setExitAction",
        // new Class[] { DynamicClassLoader.getInstance().loadClass("com.artenum.cassandra.action.ExitAction")
        // }).invoke(cassandraActionManager,
        // new Object[] {
        // DynamicClassLoader.getInstance().loadClass("com.artenum.cassandra.action.SystemExit").newInstance() });

        // exit with confirmation
        cassandraActionManager
                .getClass()
                .getMethod(
                        "setExitAction",
                        new Class[] { DynamicClassLoader.getInstance().loadClass(
                                "com.artenum.cassandra.action.ExitAction") })
                .invoke(cassandraActionManager,
                        new Object[] { DynamicClassLoader.getInstance()
                                .loadClass("com.artenum.cassandra.action.ConfirmationSystemExit").newInstance() });

        // Show the application frame
        f.setVisible(true);
        // cassandra.gui.showPipeLine();

        final Iterator<String> iterFile = inputFileList.iterator();

        while (iterFile.hasNext()) {
            final String path = iterFile.next();
            System.out.println(path);
            final File fileIn = new File(path);
            try {
                if (fileIn.exists()) {
                    cassandraClassLoader.getMethod("addVtkFile", new Class[] { File.class }).invoke(cassandra,
                            new Object[] { fileIn });
                }

            } catch (final Exception e) {
                System.out.println(e);
            }
        }

    }
}
