package guiDomain;
import sharedInterfaces.*;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.text.*;


public class GuiFacade extends JFrame implements GuiFacadeInterface
{   // Handles on other domains
    private DataServerFacadeInterface database;
    private AbstractGraphicsFacade graph;
    private GraphOptions options = new GraphOptions();

    // Components for the menu
    private JMenuBar menuBar;

    private JMenu fileMenu;
    private JMenuItem fileConnectItem;
    private JMenuItem fileOpenItem;
    private JMenuItem fileExitItem;

    private JMenu graphMenu;
    private JMenuItem graphOptionsItem;

    // Components for the main window
    private JLabel description;

    // Dialogs
    private OpenDialog openD;
    private ConnectDialog connectD;
    private GraphOptionsDialog graphD;

    // file tree
    private JTree tree;

    public GuiFacade()
    {
        // Construct the menu
        menuBar = new JMenuBar();
        setJMenuBar( menuBar );

        fileMenu = new JMenu( "File" );
        menuBar.add( fileMenu );

        fileConnectItem = new JMenuItem( new ConnectAction() );
        fileMenu.add( fileConnectItem );

        fileOpenItem = new JMenuItem( new OpenAction() );
        fileMenu.add( fileOpenItem );

        fileMenu.addSeparator();

        fileExitItem = new JMenuItem( new ExitAction() );
        fileMenu.add( fileExitItem );

	// Graph Menu
	graphMenu = new JMenu( "Graph" );
	menuBar.add( graphMenu );
	graphOptionsItem = graphMenu.add( new GraphOptionsAction() );

        description = new JLabel();

        connectD = new ConnectDialog(this, "Enter Connection Details", true);
        openD = new OpenDialog(this, "Enter experiment and shot", true);
	graphD = new GraphOptionsDialog(this,options);
    }

    public void initialise(DataServerFacadeInterface _source,
			   AbstractGraphicsFacade _graph)
    {
        database = _source;
	graph = _graph;
	graph.setGraphOptions(options);

        tree=new JTree(new DefaultTreeModel(new DefaultMutableTreeNode("No experiment open")));
        tree.addTreeSelectionListener( new DataTreeSelectionListener() );
        JScrollPane treeScroll = new JScrollPane( tree );
        treeScroll.setMinimumSize( new Dimension( 150, 10 ) );

        JSplitPane rightPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT,
                        new JScrollPane( description ),graph);
        JSplitPane mainPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
                        treeScroll, rightPane );
        getContentPane().add( mainPane, "Center" );
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle( "No experiment opened" );
        this.setBounds( 200, 200, 800, 400 );
        this.setVisible(true);
    }

    public void graphPointUpdated(double x, double y, boolean inRange)
    {
	if (inRange)
	{
	    DecimalFormat decForm = new DecimalFormat("0.##E0");
            String xString = decForm.format(x);
            String yString = decForm.format(y);
            description.setText(" x= " + xString + "  y= " + yString);
        }
	else description.setText(" ");
    }


    public void applyGraphOptions()
    {
	graph.applyGraphOptions();
	graph.repaint();
    }

    // Private Inner Classes
    private class ExitAction extends AbstractAction
    {
        public ExitAction() {   super( "Exit" );}

        public void actionPerformed( ActionEvent event )
        {    System.exit( 0 );
        }
    }

    private class ConnectAction extends AbstractAction
    {
        public ConnectAction(){    super( "Connect ..." );}

        public void actionPerformed(ActionEvent event)
        {
            if (connectD.showDialog())
            {
                String server = connectD.getServer();
                try
                {
                    if (database.isConnected())
                    {
                        if (database.isOpen())
                        {
                            tree.setModel(new DefaultTreeModel(new
                                DefaultMutableTreeNode("No experiment open")));
                            GuiFacade.this.graph.resetGraphData();
                            description.setText(" ");
                            database.close();
                        }
                        database.disconnect();
                    }
                    database.connect(server);
                    String newTitle = "Connection made. No experiment opened";
                    GuiFacade.this.setTitle(newTitle);
                }
                catch (IOException e)
                {
                    JOptionPane.showMessageDialog(GuiFacade.this,
                                                  "Failed to connect to server",
                                                  "Error",
                                                  JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    private class OpenAction extends AbstractAction
    {
        public OpenAction(){ super( "Open ..." );}

        public void actionPerformed(ActionEvent event)
        {
            if (openD.showDialog())
            {
                String experiment = openD.getExperiment();
                int shot = openD.getShot();
                try
                {
                    if (database.isOpen())
                    {
                        tree.setModel(new DefaultTreeModel(new
                            DefaultMutableTreeNode("No experiment open")));
                        GuiFacade.this.graph.resetGraphData();
                        description.setText(" ");
                        database.close();
                    }
                    database.open(experiment, shot);
                    database.constructTree(tree);
                    String newTitle = " Opened experiment: "
                        + experiment + " shot: " + shot;
                    GuiFacade.this.setTitle(newTitle);
                }
                catch (IOException e)
                {
                    JOptionPane.showMessageDialog(GuiFacade.this,
                                                   "Failed to open " +
                                                   "experiment " + experiment +", shot " +shot + ": " +
                                                   e.getMessage(), "Error",
                                                   JOptionPane.ERROR_MESSAGE);
                 }
             }
         }
    }

    /**    Open the graph options dialog */
    private class GraphOptionsAction extends AbstractAction
    {
	public GraphOptionsAction(){    super( "Options" );}

	public void actionPerformed(ActionEvent event)
	{
            if (graphD == null)
                graphD = new GraphOptionsDialog(GuiFacade.this, options);
            graphD.setOptions();
            graphD.setVisible(true);
	    GuiFacade.this.applyGraphOptions();
	}
    }

    /**    Plots the graph and displays the path of the selected tree node */
    private class DataTreeSelectionListener implements TreeSelectionListener
    {
        public void valueChanged( TreeSelectionEvent e )
        {   // Get new data and plot it
            Object path[];
            path = e.getPath().getPath();
	    String shortFileAddress="";
            for ( int i = 1; i < path.length; i ++ )
            {
	        shortFileAddress = shortFileAddress + path[i].toString();
            }
	    if (!shortFileAddress.equals("")) // (Do not plot or display the "TOP" node)
	    {
	        GuiFacade.this.graph.setGraphData
                   (database.getPlotData(shortFileAddress));
                GuiFacade.this.graph.repaint(); //(prints a message if no data)
	    }
        }
    }


}
