/*
 * (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;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;

import com.artenum.cassandra.action.CassandraActionListener;
import com.artenum.cassandra.action.SystemExit;
import com.artenum.cassandra.action.menu.AddArrow;
import com.artenum.cassandra.action.menu.AddCone;
import com.artenum.cassandra.action.menu.AddCube;
import com.artenum.cassandra.action.menu.AddLookupTable;
import com.artenum.cassandra.action.menu.AddScalarBar;
import com.artenum.cassandra.action.menu.AddTxtActor;
import com.artenum.cassandra.launcher.DynamicClassLoader;
import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.pipeline.SimplePipeLineManager;
import com.artenum.cassandra.plugin.PluginManager;
import com.artenum.cassandra.renderer.vtk.CassandraView;
import com.artenum.cassandra.ui.CassandraGUI;
import com.artenum.cassandra.ui.CassandraMenu;
import com.artenum.cassandra.ui.CassandraToolBar;

import com.artenum.cassandra.action.PluginActionListener;

/**
 * <pre>
 * <b>Project ref           :</b> CASSANDRA project
 * <b>Copyright and license :</b> See relevant sections
 * <b>Status                :</b> under development
 * <b>Creation              :</b> 04/03/2005
 * <b>Modification          :</b>
 *      - 21/04/2005: Add the SkinLF part
 *      - 17/05/2005: Add runtime configuration file
 * 
 * <b>Description  :</b> Launch and set the default components for Cassandra. This is the main file of the application.
 * 
 * </pre>
 * <table cellpadding="3" cellspacing="0" border="1" width="100%">
 * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
 * <td><b>Version number</b></td>
 * <td><b>Author (name, e-mail)</b></td>
 * <td><b>Corrections/Modifications</b></td>
 * </tr>
 * <tr>
 * <td>0.1</td>
 * <td>Sebastien Jourdain, jourdain@artenum.com</td>
 * <td>Creation</td>
 * </tr>
 * </table>
 * 
 * @author Sebastien Jourdain, Julien Forest, Benoit Thiebault, Jeremie Turbet
 * @version 1.2
 */
public class Cassandra {
    private  CassandraGUI gui;
    private  CassandraMenu menu;
    private  PipeLineManager pipeLineManager;
    private  PluginManager pluginManager;
    private  CassandraActionListener actionListener;
    private  CassandraToolBar toolBar;
    private  Hashtable<String, Object> preferences;
    private  ArrayList<PreferenceListener> prefListener;
    
    

    /**
     * Main constructor
     * 
     * @throws Exception
     */
    public Cassandra() throws Exception {
    	initComponents(true);
    }
    
    public Cassandra(boolean activateJyConsole) throws Exception {
    	initComponents(activateJyConsole);
    }

    private void initComponents( boolean activateJyConsole) {
        this.preferences = new Hashtable<String, Object>();
        this.prefListener = new ArrayList<PreferenceListener>();
        this.pipeLineManager = new SimplePipeLineManager();
        this.pluginManager = new PluginManager();
        
        this.gui = new CassandraGUI(this.pipeLineManager, this.pluginManager, activateJyConsole);
        this.actionListener = new CassandraActionListener(this.gui, this.pipeLineManager, this.pluginManager);
        this.menu = new CassandraMenu(this.actionListener);
        this.toolBar = new CassandraToolBar(this.actionListener);
        this.menu.setMainToolBar(this.toolBar);
        this.actionListener.reloadPlugings();
        this.gui.update();

        // register preference listener
        addPreferenceListener(this.actionListener);
        addPreferenceListener(this.gui);

        // init view
        this.gui.hideConsole();

        // to see the instance of the current cassandra in the JyConsole
        if(this.gui.getPyConsole() != null){
            this.gui.getPyConsole().getPythonInterpreter().set("cassandra", this);
        }

        // Add action menu
        this.menu.addToolMenuComponent(new AddLookupTable("Add a Lookup Table", this.pipeLineManager));
        this.menu.addToolMenuComponent(new AddScalarBar("Add a ScalarBar", this.pipeLineManager));
        this.menu.addSourceMenuComponent(new AddCone("Add a cone", this.pipeLineManager));
        this.menu.addSourceMenuComponent(new AddCube("Add a cube", this.pipeLineManager));
        // menu.addSourceMenuComponent(new AddPlaque("Add a plane", pipeLineManager));
        this.menu.addSourceMenuComponent(new AddArrow("Add a arrow", this.pipeLineManager));
        this.menu.addSourceMenuComponent(new AddTxtActor("Add a text", this.pipeLineManager));

        // Set default properties
        File tmpFile = null;
        if (System.getProperty(CassandraActionListener.PREF_IMAGE_SAVE_DIR) != null) {
            tmpFile = new File(System.getProperty(CassandraActionListener.PREF_IMAGE_SAVE_DIR));
            if (tmpFile.exists()) {
                setPreference(CassandraActionListener.PREF_IMAGE_SAVE_DIR, tmpFile);
            }
        }

        if (System.getProperty(CassandraActionListener.PREF_PLUGIN_OPEN_DIR) != null) {
            tmpFile = new File(System.getProperty(CassandraActionListener.PREF_PLUGIN_OPEN_DIR));
            if (tmpFile.exists()) {
                setPreference(CassandraActionListener.PREF_PLUGIN_OPEN_DIR, tmpFile);
            }
        }

        if (System.getProperty(CassandraActionListener.PREF_VTK_FILE_OPEN_DIR) != null) {
            tmpFile = new File(System.getProperty(CassandraActionListener.PREF_VTK_FILE_OPEN_DIR));
            if (tmpFile.exists()) {
                setPreference(CassandraActionListener.PREF_VTK_FILE_OPEN_DIR, tmpFile);
            }
        }

        setPreference(CassandraActionListener.PREF_AUTO_UPDATE_VTK_FILE_OPEN_DIR, false);

        if (System.getProperty(CassandraGUI.PREF_SCRIPT_DIR) != null) {
            tmpFile = new File(System.getProperty(CassandraGUI.PREF_SCRIPT_DIR));
            if (tmpFile.exists()) {
                setPreference(CassandraGUI.PREF_SCRIPT_DIR, tmpFile);
            }
        }
        
        
        //for test purpose
//        this.getPluginManager().addPluginActionListener(new PluginActionListener() {
//			
//			@Override
//			public void actionPerformed(ActionEvent e) {
//
//				System.out.println("Action performed in PluginActionListener");
//				System.out.println("Source: " + e.getSource().toString());
//				System.out.println("Command: "+ e.getActionCommand());
//				
//			}
//		});
    }

    public CassandraGUI getDefaultUI() {
        return this.gui;
    }

    public CassandraMenu getDefaultMenu() {
        return this.menu;
    }

    public PipeLineManager getPipeLineManager() {
        return this.pipeLineManager;
    }

    public CassandraView getRendererPanel() {
        return this.pipeLineManager.getCassandraView();
    }

    /**
     * Get the pipelines editors of the presente instance of Cassandra. 
     * @return - the tabbed pane containing the pipeline editors.
     */
    public JTabbedPane getPipelineEditor(){
    	return this.gui.getPipelineEditor();
    }
    
    public CassandraToolBar getDefaultToolBar() {
        return this.toolBar;
    }

    public PluginManager getPluginManager() {
        return this.pluginManager;
    }

    public CassandraActionListener getActionManager() {
        return this.actionListener;
    }

    public void loadPluginInDirectory(final File pluginDir) {
        DynamicClassLoader.getInstance().loadDirectory(pluginDir);
        this.actionListener.reloadPlugings();
    }

    public void addPreferenceListener(final PreferenceListener pl) {
        pl.setPreferences(getPreferences());
        this.prefListener.add(pl);
    }

    public void removePreferenceListener(final PreferenceListener pl) {
        this.prefListener.remove(pl);
    }

    /**
     * Set the preference (i.e property) given in argument.
     * 
     * @param key
     * @param value
     */
    public void setPreference(final String key, final Object value) {
        this.preferences.put(key, value);
        notifyPreferenceListener();
    }

    public Hashtable<String, Object> getPreferences() {
        return this.preferences;
    }

    public void notifyPreferenceListener() {
        for (final Iterator<PreferenceListener> i = this.prefListener.iterator(); i.hasNext();) {
            i.next().preferenceChanged();
        }
    }

    public void addVtkFile(final File file) {
        this.pipeLineManager.getCassandraView().lock();
        this.pipeLineManager.addVtkFile(file);
        this.pipeLineManager.getCassandraView().unlock();
    }


    
    
    
    
    public static void main(final String[] args) throws Exception {
        /*
         * if ((System.getProperty("cassandra.skin") != null) && new
         * File(System.getProperty("cassandra.skin")).exists()) { try { File f = new
         * File(System.getProperty("cassandra.skin")); if (f.exists()) { // first tell SkinLF which theme to use Skin
         * theSkinToUse = SkinLookAndFeel.loadThemePack(f.getAbsolutePath()); SkinLookAndFeel.setSkin(theSkinToUse); } }
         * catch (Exception e) { JOptionPane.showMessageDialog(null, "Skin error: " + e.getMessage()); } }
         */
        // final Properties props = System.getProperties();
        // String key = null;
        // for (final Enumeration e = props.keys(); e.hasMoreElements();) {
        // key = (String) e.nextElement();
        // }

        final Cassandra cassandra = new Cassandra();

        // Build the JFrame
        final JFrame f = new JFrame("Cassandra VTK viewer");
        f.setJMenuBar(cassandra.getDefaultMenu());
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(cassandra.getDefaultToolBar(), BorderLayout.NORTH);
        f.getContentPane().add(cassandra.getDefaultUI(), BorderLayout.CENTER);
        f.setSize(800, 600);
        f.setLocationRelativeTo(null);
        //
        if (args.length == 1) {
            cassandra.loadPluginInDirectory(new File(args[0]));
        } else if (System.getProperty("cassandra.plugin.dir") != null) {
            final File pluginDir = new File(System.getProperty("cassandra.plugin.dir"));
            if (pluginDir.exists()) {
                cassandra.loadPluginInDirectory(pluginDir);
            } else {
                System.out.println("No plug-in found. Please check your preferences settings.");
            }
        }

        // set preferences done in config file now...
        /*
         * File localDir = new File("."); cassandra.setPreference(CassandraActionListener.PREF_IMAGE_SAVE_DIR,
         * localDir); cassandra.setPreference(CassandraActionListener.PREF_PLUGIN_OPEN_DIR, new File(localDir,
         * "plugin")); cassandra.setPreference(CassandraActionListener.PREF_VTK_FILE_OPEN_DIR, new File(localDir,
         * "data")); cassandra.setPreference(CassandraGUI.PREF_SCRIPT_DIR, new File(localDir, "script"));
         */

        // default exit method, generally overloaded through the setExitAction
        // method the the CassandraActionListener
        cassandra.getActionManager().setExitAction(new SystemExit());

        //
        f.setVisible(true);
        cassandra.gui.showPipeLine();
    }

}
