// $Id: JGTestFrame.java,v 1.10 2002/03/01 15:56:52 martin Exp $ ; $Name:  $
//import rsdesigner.javagateway.*;
import rsdesigner.design.*;
import rsdesigner.component.*;
/*
    component.{Component|Shape} need to be imported
    explicitly because the AWT uses Component and Shape for
    other objects and I don't want to have to specify them using
    the fully-qualified name
*/
import rsdesigner.component.Component;
import rsdesigner.component.Shape;

import javax.swing.table.AbstractTableModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.util.Iterator;

class MyWindowAdapter extends WindowAdapter
{
    public void windowClosing (WindowEvent we)
    {
        System.out.println ("Closing");
    }
}

/**
    This class is used as a separate thread to update the list of blocks in the system.
*/
class RefreshThread extends Thread
{
    JGTestFrame testFrame;
    int delay;
    RefreshThread (JGTestFrame jgtf, String name)
    {
        super (name);
        //now make a note of the test frame that
        //we're going to refresh
        testFrame = jgtf;
        delay = 30;
    }
    public void run ()
    {
        for (;;)
        {
            System.out.println ("Refresh thread: refreshing in " + delay + " seconds");
            try
            {
                sleep (delay * 1000);
                if (testFrame.isShowing ())
                {
                    testFrame.refreshList_actionPerformed ();
                    //testFrame.toFront ();
                }
            }
            catch (InterruptedException ie)
            {
            }
        }
    }
}

class SelectPreFilter implements SelectFilter
{
    public Boolean filter (PropertySet pset)
    {
        boolean allow = true;
        try {
            System.out.println ("SelectPreFilter.filter " + pset.getStringProperty ("name", null));
        }
        catch (Exception e)
        {
        }
        //we are only interested in artifacts at the moment
        if (pset instanceof Artifact)
        {
            allow = true;
        }
        else
        {
            System.out.println ("SelectPreFilter.filter disallowing object");
            allow = false;
        }
        return new Boolean (allow);
    }
}

class SelectPostFilter implements SelectFilter
{
    public Boolean filter (PropertySet pset)
    {
        try {
            System.out.println ("SelectPostFilter.filter " + pset.getStringProperty ("name", null));
        }
        catch (Exception e)
        {
        }
        return new Boolean (true);
    }
}

class ArtifactTableModel extends AbstractTableModel {
    String[] columnNames = {};
    final Vector data = new Vector ();

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.size();
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        Object[] rowList = (Object[]) data.get (row);
        return rowList[col];
    }

    public void clear ()
    {
        data.clear ();
    }

    public void add (Object[] row)
    {
        if (row.length != getColumnCount ())
        {
            System.out.println ("Invalid row list");
            return;
        }
        for (int i = 0; i < row.length; i++)
        {
            if (row[i] == null)
            {
                System.out.println ("Invalid data in row list at pos " + i);
                return;
            }
        }
        data.add (row);
    }

    public void setColumnNames (String[] newColumnNames)
    {
        columnNames = newColumnNames;
        clear ();
    }

    /*
     * JTable uses this method to determine the default renderer/
     * editor for each cell.  If we didn't implement this method,
     * then the last column would contain text ("true"/"false"),
     * rather than a check box.
     */
    public Class getColumnClass(int c) {
        Object obj = getValueAt(0, c);
        if (obj != null)
        {
            return obj.getClass();
        }
        return null;
    }
}

public class JGTestFrame extends JFrame
{
    JButton refreshList = new JButton ("Refresh list");
    JCheckBox sortBox = new JCheckBox ("Ascending sort on 'sheets'", true);
    JCheckBox fibresOnly = new JCheckBox ("Fibres only", false);
    JCheckBox genderFemale = new JCheckBox ("gender IS FEMALE", false);
    ArtifactTableModel artifactTableModel = new ArtifactTableModel();
    JTable blockTable = new JTable(artifactTableModel);
    /*
    TableSorter sorter = new TableSorter(artifactTableModel); //ADDED THIS
    JTable blockTable = new JTable(sorter);             //NEW
    sorter.addMouseListenerToHeaderInTable (blockTable); //ADDED THIS
    */
    JLabel listLabel = new JLabel ("Artifacts in the Database");
    BorderLayout layout1 = new BorderLayout ();
    MyWindowAdapter windowAdapter = new MyWindowAdapter ();
    Box buttonPanel = new Box (BoxLayout.X_AXIS);
    Thread refreshThread = null;

    public JGTestFrame ()
    {
        try
        {
            jbInit();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    private void jbInit() throws Exception
    {
        JScrollPane listPane = new JScrollPane (blockTable);
        getContentPane().setLayout(layout1);
        getContentPane().add (listLabel, "North");
        getContentPane().add (listPane, "Center");
        getContentPane().add (buttonPanel, "South");
        buttonPanel.add (refreshList);
        buttonPanel.add (sortBox);
        buttonPanel.add (fibresOnly);
        buttonPanel.add (genderFemale);

        refreshList.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                refreshList_actionPerformed();
            }
        });
        addWindowListener (windowAdapter);
        this.pack ();

        //now create the refresh frame that will update the list of blocks
        //refreshThread = new RefreshThread (this, "RefreshThread");
        //refreshThread.start ();
    }

    public static JFrame get_instance()
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception ex)
        {
            System.out.println(ex);
        }
        return new JGTestFrame ();
    }

    public static void openTestFrame(String param1)
    {
        JFrame jf = JGTestFrame.get_instance();

        System.out.println("Received " + param1 + ". Now opening window");

        jf.setSize(600, 200);
        jf.setTitle("RSDesigner Java Console");
        jf.setVisible(true);
        jf.toFront ();
    }

    synchronized void refreshList_actionPerformed ()
    {
        System.out.println ("Refreshing list box");

        Object[] argList= new Object[10];
        synchronized (Design.getSynchronizeObject ())
        {
            /*
                we need to synchronize on the VM because we (or a trail file!) may end
                up closing the design between the obtaining of the design and looping
                over the elements in the design
            */
            //we need the design object so we can then get the list of blocks
            //System.out.println ("get the design class");
            Design design = Design.getCurrentDesign ();
            artifactTableModel.clear ();
            if (design == null)
            {
                System.out.println ("No design open");
                return;
            }
            System.out.println ("Now testing the DBItem stuff");
            try
            {
                /*
                    set up the table's column names, but only do it
                    once, seeing as we'll be using the same settings later on
                */
                String[] columnNames = new String [] { "Name",
                                                    "Class",
                                                    "Type",
                                                    "Sheets"};
                if (artifactTableModel.getColumnCount () != columnNames.length)
                {
                    artifactTableModel.setColumnNames (columnNames);
                    blockTable.createDefaultColumnsFromModel ();
                }

                //run a query on the design
                Condition[] conditionList;
                if (genderFemale.isSelected())
                {
                    conditionList = new Condition [] {new SimpleCondition ("gender", "eq", "FEMALE")};
                }
                else
                {
                    conditionList = new Condition [] {new SimpleCondition ("name", "any", "*")};
                }
                SortSpec[] sortSpecList = new SortSpec [] {new SortSpec ("sheets", sortBox.isSelected ())};

                String[] classList = null;
                if (fibresOnly.isSelected ())
                {
                    classList = new String[] {"fibre"};
                }
                else
                {
                    /*
                    * exclude ports, because they are usually plentiful and uninteresting (except
                    * when members of Components) and will slow the search down lots
                    */
                    classList = new String[] {"component"};
                }
                SelectFilter sf1 = new SelectPreFilter ();
                SelectFilter sf2 = new SelectPostFilter ();

                //now perform the actual select operation
                Iterator selectResults = design.select (conditionList, sortSpecList, classList, sf1, sf2);


                //work through the results of the select query
                int count = 0;
                while (selectResults.hasNext ())
                {
                    Object nextObj = selectResults.next ();
                    if (nextObj instanceof Artifact)
                    {
                        count++;

                        Artifact artifact = (Artifact) nextObj;

                        /*now get the information to insert into the table*/
                        //get the 'sheets' property first, because it may be null
                        Object sheets = artifact.getStringProperty ("sheets", "");
                        if (sheets == null)
                        {
                            sheets = "*No Sheet*";
                        }
                        Object[] rowList = {artifact.getStringProperty ("name", ""), artifact.getClassString (),
                            artifact.getType (), sheets};

                        //now insert the details into the table
                        artifactTableModel.add (rowList);

                        /*
                            let's test some of the Component API
                        */
                        String artName = artifact.getName();
                        System.out.println ("Found artifact " + artName);

                        if (artifact instanceof Component)
                        {
                            Component component = (Component) artifact;
                            Iterator ports = component.getPorts();
                            while (ports.hasNext())
                            {
                                Object[] portList = (Object[]) ports.next();
                                Port port = (Port) portList[0];
                                System.out.println ("  port " + port.getName());

                                //get the list of ports this port is connected to (of any diagram type)
                                Iterator connPorts = port.getConnectedPorts(0);
                                while (connPorts.hasNext())
                                {
                                    Port connPort = (Port) connPorts.next();
                                    System.out.println ("    connected port " + connPort.getName());
                                }
                                //get the list of ports this port is connected to (of diagram type 3)
                                Iterator connPorts3 = port.getConnectedPorts(3);
                                while (connPorts3.hasNext())
                                {
                                    Port connPort = (Port) connPorts3.next();
                                    System.out.println ("    connected port (dt 3) " + connPort.getName());
                                }

                                //get the list of ports this port is connected to because its
                                //parent is internally connected
                                Iterator intConnPorts = component.getConnectedPorts(port, 0);
                                while (intConnPorts.hasNext())
                                {
                                    Port connPort = (Port) intConnPorts.next();
                                    System.out.println ("    internally connected port " + connPort.getName());
                                }

                            }
                            //only Fibres have a diagram type
                            if (artifact instanceof Fibre)
                            {
                                Fibre f = (Fibre) artifact;

                                System.out.println("  fibre diagram type " + f.getDiagramType());
                            }
                            //Groups have members
                            if (artifact instanceof Group)
                            {
                                Group group = (Group) artifact;

                                Iterator members = group.getMembers();
                                while (members.hasNext())
                                {
                                    Object[] memberList = (Object[]) members.next();
                                    Artifact member = (Artifact) memberList[0];
                                    Object index = memberList[1];
                                    Object varindex = memberList[2];
                                    System.out.println ("  has member " + member.getName() +
                                        " at index " + index +
                                        " at varindex " + varindex);
                                }
                            }
                        }
                        /*
                            and test some more of the Component API
                        */
                        Iterator shapes = artifact.getShapes();
                        while (shapes.hasNext())
                        {
                            Shape shape = (Shape) shapes.next();
                            System.out.println ("  has shape " + shape);
                            if (shape instanceof ComponentShape)
                            {
                                ComponentShape cShape = (ComponentShape) shape;
                                Iterator portShapes = cShape.getPortShapes();
                                while (portShapes.hasNext())
                                {
                                    PortShape pShape = (PortShape) portShapes.next();
                                    System.out.println ("   has portshape " + pShape);

                                    Iterator connPortShapes = pShape.getConnectedPortShapes();
                                    while (connPortShapes.hasNext())
                                    {
                                        System.out.println ("     has connected portshape " + connPortShapes.next());
                                    }
                                }

                                if (shape instanceof GroupShape)
                                {
                                    GroupShape gShape = (GroupShape) shape;
                                    Iterator memberShapes = gShape.getMembers();
                                    while (memberShapes.hasNext())
                                    {
                                        Object[] memberList = (Object[]) memberShapes.next();
                                        Shape member = (Shape) memberList[0];
                                        Object index = memberList[1];
                                        System.out.println ("   has membershape " + member +
                                                    " at index " + index);
                                    }
                                }

                                Shape container = shape.getContainer();
                                System.out.println ("    has container " + container);
                                Shape tlc = shape.getTopLevelContainer();
                                System.out.println ("    has top level container " + tlc);
                                int diagType = cShape.getDiagramType();
                                System.out.println ("    has diagram type " + diagType);
                            }
                        }

                    }
                    else
                    {
                        System.out.println("Found non-Artifact " + nextObj);
                    }
                }
                System.out.println("Found " + count + " artifacts");

                /*
                //get a list of all the design objects
                Iterator[] artifacts = new Iterator[4];
                artifacts[0] = design.getBlocks (true, false);
                artifacts[1] = design.getFibres (true, false);
                artifacts[2] = design.getGroups (true, false);
                artifacts[3] = design.getPorts (true, false);
                for (int i = 0; i < artifacts.length; i++)
                {
                    Iterator iter = artifacts[i];
                    while (iter.hasNext ())
                    {
                        Object[] objList = (Object[]) iter.next();
                        Artifact block = (Artifact) objList[0];
                        Object[] rowList = {block.getStringProperty ("name", ""), block.getClassString (),
                            block.getType (), block.getStringProperty ("sheets", "")};
                        artifactTableModel.add (rowList);
                    }
                }
                */
                artifactTableModel.fireTableDataChanged ();
            }
            catch (RSDException rse)
            {
                System.out.println ("Exception " + rse);
                rse.printStackTrace();
            }
        }
        System.out.println ("Refreshing complete");

    }
}
