package netmatch;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

import cytoscape.*;
import cytoscape.view.CytoscapeDesktop;
import cytoscape.view.cytopanels.CytoPanel;
import cytoscape.view.cytopanels.CytoPanelState;
import cytoscape.data.CyAttributes;
import cytoscape.task.ui.JTaskConfig;
import cytoscape.task.util.TaskManager;
import netmatch.qtool.QToolFrame;
import netmatch.qtool.IQueryRecipient;
import netmatch.algorithm.Common;
import netmatch.algorithm.netMatch;
import netmatch.algorithm.GraphLoader;
import netmatch.help.netMatchHelp;
import netmatch.wizard.WizardForm;

public class netMatchPanel extends JPanel implements ActionListener,IQueryRecipient,PropertyChangeListener{
  private static final int WIDTH = 250;
  private static final int MINIMUM_WIDTH = 200;
  public ImageIcon[] icons;
  public ImageIcon[] structures;
  public ImageIcon[] menu;
  private static final String aboutImage = "bannerImage.jpg";
  private static final String selgimp = "select_gimp.gif";
  private static final String selmove = "select_move.gif";
  private static final String nodegimp = "node.gif";
  private static final String loopgimp = "loop_gimp.gif";
  private static final String edgegimp = "edge_gimp.gif";
  private static final String pathgimp = "path_gimp.gif";
  private static final String zoomin = "zoomin_gimp.gif";
  private static final String zoomout = "zoomout_gimp.gif";
  private static final String bi_fan = "bi_fan.gif";
  private static final String bi_parallel = "bi_parallel.gif";
  private static final String feed_forward_loop = "feed_forward_loop.gif";
  private static final String three_chain = "three_chain.gif";
  private static final String nuovo = "new.gif";
  private static final String load = "load.gif";
  private static final String save = "save.gif";
  private static final String change = "change.gif";
  private static final String pass = "pass.gif";
  private static final String exit = "exit.gif";
  private static final String clear = "clear.gif";
  private static final String nuovo16 = "new16.gif";
  private static final String load16 = "load16.gif";
  private static final String save16 = "save16.gif";
  private static final String change16 = "change16.gif";
  private static final String pass16 = "pass16.gif";
  private static final String exit16 = "exit16.gif";
  private static final String clear16 = "clear16.gif";
  private static final String draw16 = "draw16.gif";
  private static final String xedit16 = "xedit.png";
  private static final String h = "h.gif";
  private static final String a = "a.png";
  private static final String wiz = "wizard.gif";
  private static final String mton_fan = "mton_fan.gif";
  private static final String quickHelp = "help.gif";
  private static final String about16 = "about16.gif";
  private static final String path = "images/";

  private JTextArea log;
  private JComboBox query;
  private JComboBox target;
  private JCheckBox labeled;
  private JCheckBox directed;
  private JComboBox qea, tea, qna, tna;

  private QToolFrame qEditor;
  private boolean isEditorOpen;  // tracks if editor is open
  private boolean isQueryApproximate;
  private Vector qpaths;
  public HashMap queries;
  protected WizardForm  wizardForm;
  public ArrayList listOfNodeAttributes;
  public ArrayList listOfEdgeAttributes;
  netMatchPluginAction trigger;
  netMatchHelp help;
  JAboutDialog aboutbox;

  public netMatchPanel(netMatchPluginAction trigger) {
    help = null;
    aboutbox = null;
    this.trigger = trigger;
    setLayout(new BorderLayout());
    icons = new ImageIcon[9];
    icons[0] = createImageIcon(path + aboutImage);
    icons[1] = createImageIcon(path + selgimp);
    icons[2] = createImageIcon(path + selmove);
    icons[3] = createImageIcon(path + nodegimp);
    icons[4] = createImageIcon(path + loopgimp);
    icons[5] = createImageIcon(path + edgegimp);
    icons[6] = createImageIcon(path + pathgimp);
    icons[7] = createImageIcon(path + zoomin);
    icons[8] = createImageIcon(path + zoomout);
    structures = new ImageIcon[5];
    structures[0] = createImageIcon(path + three_chain);
    structures[1] = createImageIcon(path + feed_forward_loop);
    structures[2] = createImageIcon(path + bi_parallel);
    structures[3] = createImageIcon(path + bi_fan);
    structures[4] = createImageIcon(path + mton_fan);
    menu = new ImageIcon[21];
    menu[0] = createImageIcon(path + nuovo);
    menu[1] = createImageIcon(path + load);
    menu[2] = createImageIcon(path + save);
    menu[3] = createImageIcon(path + change);
    menu[4] = createImageIcon(path + pass);
    menu[5] = createImageIcon(path + exit);
    menu[6] = createImageIcon(path + clear);
    menu[7] = createImageIcon(path + nuovo16);
    menu[8] = createImageIcon(path + load16);
    menu[9] = createImageIcon(path + save16);
    menu[10] = createImageIcon(path + change16);
    menu[11] = createImageIcon(path + pass16);
    menu[12] = createImageIcon(path + exit16);
    menu[13] = createImageIcon(path + clear16);
    menu[14] = createImageIcon(path + draw16);
    menu[15] = createImageIcon(path + xedit16);
    menu[16] = createImageIcon(path + h);
    menu[17] = createImageIcon(path + a);
    menu[18] = createImageIcon(path + wiz);
    menu[19] = createImageIcon(path + quickHelp);
    menu[20] = createImageIcon(path + about16);
    
    JPanel principale = new JPanel();
    principale.setLayout(new BorderLayout());

    JToolBar menuBar = createMenuBar();
    principale.add(menuBar,BorderLayout.NORTH);

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
    JScrollPane scroller = new JScrollPane();
    scroller.getViewport().add(panel);
    

    JPanel panel4q = new JPanel();
    panel4q.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel4q.setMaximumSize(new Dimension(WIDTH,180));
    panel4q.setPreferredSize(new Dimension(WIDTH,180));
    panel4q.setMinimumSize(new Dimension(MINIMUM_WIDTH,180));
    panel4q.setLayout(new GridLayout(6,1,5,5));
    panel4q.setBorder(new TitledBorder(new EtchedBorder(), "Query Properties", TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION,null, Color.BLACK));
    //JPanel pp = new JPanel();
    //pp.setLayout(new BoxLayout(pp,BoxLayout.LINE_AXIS));
    JLabel lab = new JLabel("Query:");
    //pp.add(lab);
    //pp.add(Box.createHorizontalGlue());
    //JButton drawQuery = new JButton("Draw a query...");
    //drawQuery.addActionListener(this);
    //drawQuery.setToolTipText("Open query editor to draw a query.");
    //pp.add(drawQuery);
    panel4q.add(lab);
    //panel4q.add(Box.createVerticalGlue());
    query = new JComboBox();
    query.setEditable(false);
    query.setEnabled(false);
    query.setBorder(new EtchedBorder());
    query.addActionListener(this);
    query.setToolTipText("Select a query.");
    panel4q.add(query);
    JLabel lab3 = new JLabel("Query Node Attributes:",JLabel.LEFT);
    panel4q.add(lab3);
    qna = new JComboBox();
    qna.setEnabled(false);
    qna.setToolTipText("<html>Select query node attributes.<br> If \"" + Strings.DEFAULT_ATTRIBUTES + "\" is selected,<br> nodes's names are the default attributes.</html>");
    panel4q.add(qna);
    JLabel lab4 = new JLabel("Query Edge Attributes:",JLabel.LEFT);
    panel4q.add(lab4);
    qea = new JComboBox();
    qea.setEnabled(false);
    qea.setToolTipText("Select query edge attributes.");
    panel4q.add(qea);
    panel.add(panel4q);

    JPanel panel4t = new JPanel();
    panel4t.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel4t.setMaximumSize(new Dimension(WIDTH,180));
    panel4t.setPreferredSize(new Dimension(WIDTH,180));
    panel4t.setMinimumSize(new Dimension(MINIMUM_WIDTH,180));
    panel4t.setLayout(new GridLayout(6,1,5,5));
    panel4t.setBorder(new TitledBorder(new EtchedBorder(), "Network Properties", TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION, null, Color.BLACK));
    JLabel lab2 = new JLabel("Network:",JLabel.LEFT);
    panel4t.add(lab2);
    target = new JComboBox();
    target.setEditable(false);
    target.setEnabled(false);
    target.setBorder(new EtchedBorder());
    target.addActionListener(this);
    target.setToolTipText("Select a network.");
    panel4t.add(target);
    JLabel lab6 = new JLabel("Network Node Attributes:",JLabel.LEFT);
    panel4t.add(lab6);
    tna = new JComboBox();
    tna.setEnabled(false);
    tna.addActionListener(this);
    tna.setToolTipText("<html>Select network node attributes.<br> If \"" + Strings.DEFAULT_ATTRIBUTES + "\" is selected,<br> nodes's names are the default attributes.</html>");
    panel4t.add(tna);
    JLabel lab66 = new JLabel("Network Edge Attributes:",JLabel.LEFT);
    panel4t.add(lab66);
    tea = new JComboBox();
    tea.setEnabled(false);
    tea.addActionListener(this);
    tea.setToolTipText("Select network edge attributes.");
    panel4t.add(tea);
    panel.add(panel4t);

    JPanel panel7 = new JPanel(new GridLayout(1,2,2,2));
    panel7.setMaximumSize(new Dimension(WIDTH,70));
    panel7.setPreferredSize(new Dimension(WIDTH,70));
    panel7.setMinimumSize(new Dimension(MINIMUM_WIDTH,70));

    JPanel panel2 = new JPanel();
    panel2.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel2.setLayout(new BoxLayout(panel2,BoxLayout.Y_AXIS));
    panel2.setBorder(new TitledBorder(new EtchedBorder(), "Graph Properties", TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION, null, Color.BLACK));
    labeled = new JCheckBox("Labeled");
    labeled.setSelected(true);
    labeled.addActionListener(this);
    labeled.setToolTipText("If not checked, all nodes and edges are supposed unlabeled.");
    panel2.add(labeled);
    panel2.add(Box.createHorizontalGlue());
    directed = new JCheckBox("Directed");
    directed.setSelected(true);
    directed.addActionListener(this);
    directed.setToolTipText("If not checked, all edges are supposed undirected.");
    panel2.add(directed);
    panel7.add(panel2);

    JPanel panel5 = new JPanel();
    panel5.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel5.setLayout(new GridLayout(2,1,5,5));
    panel5.setBorder(new TitledBorder(new EtchedBorder(), "Options", TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION, null, Color.BLACK));
    //JButton choose = new JButton("Acquire Data");
    //choose.setAlignmentX(Component.CENTER_ALIGNMENT);
    //choose.addActionListener(this);
    //choose.setToolTipText("<html>Press this button to update queries and<br>networks loaded in the cytoscape main window.</html>");
    //panel5.add(choose);
    JButton go = new JButton("Go");
    go.setAlignmentX(Component.CENTER_ALIGNMENT);
    go.addActionListener(this);
    go.setToolTipText("Start matching.");
    panel5.add(go);
    JButton reset = new JButton("Reset");
    reset.setAlignmentX(Component.CENTER_ALIGNMENT);
    reset.addActionListener(this);
    reset.setToolTipText("Reset queries and networks.");
    panel5.add(reset);
    panel7.add(panel5);
    panel.add(panel7);

    JPanel panel6 = new JPanel(new BorderLayout());
    panel6.setAlignmentX(Component.CENTER_ALIGNMENT);
    log = new JTextArea();
    log.setEditable(false);
    log.setBackground(Color.WHITE);
    log.setBorder(new TitledBorder(new EtchedBorder(), "Log", TitledBorder.RIGHT, TitledBorder.DEFAULT_JUSTIFICATION, null, Color.BLACK));
    JScrollPane scroller2 = new JScrollPane();
    scroller2.getViewport().add(log);
    panel6.add(scroller2,BorderLayout.CENTER);

    JSplitPane splitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT,scroller,panel6);
    splitPane2.setOneTouchExpandable(true);
    splitPane2.setContinuousLayout(true);
    splitPane2.setDividerLocation(440);

    principale.add(splitPane2, BorderLayout.CENTER);
    add(principale,BorderLayout.CENTER);

    queries = new HashMap();
    isEditorOpen = false;
    isQueryApproximate = false;
    qpaths = new Vector();
    listOfNodeAttributes = null;
    listOfEdgeAttributes = null;
    
    if(!Cytoscape.getNetworkSet().isEmpty())
      acquireData("");

    // Creates the wizard frame, initially invisible.
    wizardForm = new WizardForm(this);
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    wizardForm.setLocation(screenSize.width / 2 - (wizardForm.getWidth() / 2), screenSize.height / 2 - (wizardForm.getHeight() / 2));
    wizardForm.setResizable(false);
    wizardForm.setVisible(false); // not necessary
    wizardForm.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(Cytoscape.NETWORK_LOADED,this);
    Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(Cytoscape.NETWORK_CREATED,this);
    Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(Cytoscape.NETWORK_MODIFIED,this);
    Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(Cytoscape.NETWORK_DESTROYED,this);
  }

  /*
  private void initListeners() {
    // to catch network create/destroy/focus events
    //Cytoscape.getDesktop().getSwingPropertyChangeSupport().addPropertyChangeListener(this);
    Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(this);
    //  to catch network modified events
    //NetworkChangeListener networkChangeListener = new NetworkChangeListener(this);
    //Cytoscape.getPropertyChangeSupport().addPropertyChangeListener(networkChangeListener);
  }*/

  /**
   * Property change listener - to get network/network view destroy events.
   *
   * @param event PropertyChangeEvent
   */
  public void propertyChange(PropertyChangeEvent event) {
    //if(event.getPropertyName() != null) {
    if(event.getPropertyName().equals(Cytoscape.NETWORK_MODIFIED) ||
        event.getPropertyName().equals(Cytoscape.NETWORK_LOADED) ||
        event.getPropertyName().equals(Cytoscape.NETWORK_CREATED))
      acquireData("");
    else if(event.getPropertyName().equals(Cytoscape.NETWORK_DESTROYED))
      acquireData((String)event.getNewValue());
  }

  private ImageIcon createImageIcon(String filename) {
    return new ImageIcon(getClass().getResource(filename));
  }

  public boolean isEditorOpen() {
    return isEditorOpen;
  }

  // Used for update combobox when "classical mode" is selected in wizard
  public void setDataFromWizard(String t,String q,String tnas,String teas,String qnas,String qeas,boolean lab,boolean dir) {
    ArrayList nodeTemp = null,edgeTemp = null;
    if(tnas.equals(Strings.LIST_ATTRIBUTES_CHANGED) && listOfNodeAttributes != null)
      nodeTemp = new ArrayList(listOfNodeAttributes);
    else {
      nodeTemp = new ArrayList();
      nodeTemp.add(tnas);
    }
    if(teas.equals(Strings.LIST_ATTRIBUTES_CHANGED) && listOfEdgeAttributes != null)
      edgeTemp = new ArrayList(listOfEdgeAttributes);
    else {
      edgeTemp = new ArrayList();
      edgeTemp.add(teas);
    }
    acquireData("");
    setAttrList(nodeTemp,true);
    setAttrList(edgeTemp,false);
    Common.LABELED = lab;
    Common.DIRECTED = dir;
    labeled.setSelected(lab);
    directed.setSelected(dir);
    target.setSelectedItem(t);
    tna.removeActionListener(this);
    tea.removeActionListener(this);
    tna.setSelectedItem(tnas);
    tea.setSelectedItem(teas);
    tna.addActionListener(this);
    tea.addActionListener(this);
    query.setSelectedItem(q);
    qna.setSelectedItem(qnas);
    qea.setSelectedItem(qeas);
  }

  public void actionPerformed(ActionEvent e) {
    String command = e.getActionCommand();
    Object o = e.getSource();
    if(o == tna) {
      if(((JComboBox)o).getSelectedItem().toString().equals(Strings.LIST_ATTRIBUTES) ||
         ((JComboBox)o).getSelectedItem().toString().equals(Strings.LIST_ATTRIBUTES_CHANGED)) {
        multipleAttrChoice m = new multipleAttrChoice(this,"Multiple Node Attributes",((JComboBox)o),true);
        m.setVisible(true);
      }
      else {
        listOfNodeAttributes = new ArrayList();
        listOfNodeAttributes.add(tna.getSelectedItem());
      }
    }
    else if(o == tea) {
      if(((JComboBox)o).getSelectedItem().toString().equals(Strings.LIST_ATTRIBUTES) ||
         ((JComboBox)o).getSelectedItem().toString().equals(Strings.LIST_ATTRIBUTES_CHANGED)) {
        multipleAttrChoice m = new multipleAttrChoice(this,"Multiple Edge Attributes",((JComboBox)o),false);
        m.setVisible(true);
      }
      else {
        listOfEdgeAttributes = new ArrayList();
        listOfEdgeAttributes.add(tea.getSelectedItem());
      }
    }
    if(command.equals("Exit")) {
      //processEvent(new WindowEvent(this, 201));
      close();
    }
    else if(command.equals("About...")) {
      aboutbox = new JAboutDialog(this, icons[0]);
      aboutbox.setVisible(true);
    }
    else if(command.equals("Documentation")) {
      help = new netMatchHelp("NetMatch Help",menu[20]);
      help.setVisible(true);
    }
    else if(command.equals("Switch to wizard mode")){
      Set s = Cytoscape.getNetworkSet();
      if(s.isEmpty()) {
        JOptionPane.showMessageDialog(Cytoscape.getDesktop(), "Cytoscape workspace is empty. Please Load at least one Network!", "NetMatch", JOptionPane.INFORMATION_MESSAGE);
      }
      else {
        this.setVisible(false);
        acquireData("");
        wizardForm.init();
        wizardForm.acquire();
        wizardForm.setVisible(true);
      }
    }
    else if(command.equals("Reset")) {
      log.setText("");
      query.removeActionListener(this);
      target.removeActionListener(this);
      tea.removeActionListener(this);
      tna.removeActionListener(this);
      query.removeAllItems();
      query.setEnabled(false);
      target.removeAllItems();
      target.setEnabled(false);
      qea.removeAllItems();
      qea.setEnabled(false);
      qna.removeAllItems();
      qna.setEnabled(false);
      tea.removeAllItems();
      tea.setEnabled(false);
      tna.removeAllItems();
      tna.setEnabled(false);
      //result.clear();
      query.addActionListener(this);
      target.addActionListener(this);
      tea.addActionListener(this);
      tna.addActionListener(this);
      labeled.setSelected(true);
      directed.setSelected(true);
      queries.clear();
      listOfNodeAttributes = null;
      listOfEdgeAttributes = null;
      System.gc();
      Set s = Cytoscape.getNetworkSet();
      if(!s.isEmpty())
        acquireData("");
    }
    else if(command.equals("Draw...") || command.equals("Draw a query...")) {
      if(!isEditorOpen) {
        qEditor = new QToolFrame("NetMatch Query Editor", this, icons, structures,menu);
        qEditor.setVisible(true);
        qEditor.setResizable(true);
        isEditorOpen = true;
      }
      else
        qEditor.toFront();
    }
    /*else if(command.equals("Acquire Data")) {
      Set s = Cytoscape.getNetworkSet();
      if(s.isEmpty())
        JOptionPane.showMessageDialog(Cytoscape.getDesktop(), "Cytoscape workspace is empty. Please Load at least one Network!", "NetMatch", JOptionPane.INFORMATION_MESSAGE);
      else
        acquireData("");
    }*/
    else if(command.equals("Go")) {
      if(!query.isEnabled() || !target.isEnabled()) {
        JOptionPane.showMessageDialog(Cytoscape.getDesktop(), "Please Select a Network and a Query First!", "NetMatch", JOptionPane.INFORMATION_MESSAGE);
      }
      else if(!areValidAttributes()) {
        JOptionPane.showMessageDialog(Cytoscape.getDesktop(), "Map Attributes can't be used in NetMatch!", "NetMatch", JOptionPane.ERROR_MESSAGE);
      }
      else {
        String t = (String)target.getSelectedItem();
        String q = (String)query.getSelectedItem();
        boolean isUsingQE = false;
        CyNetwork tnetwork = Cytoscape.getNetwork(t.substring(0, t.indexOf('-')));
        String nn = q.substring(0, q.indexOf('-'));
        if(nn.equals("QE"))
          isUsingQE = true;
        CyNetwork qnetwork = null;
        if(!isUsingQE)
          qnetwork = Cytoscape.getNetwork(nn);
        if(tnetwork == null || tnetwork.getNodeCount() < 1 || (qnetwork == null && !isUsingQE) || (qnetwork != null && qnetwork.getNodeCount() < 1))
          JOptionPane.showMessageDialog(Cytoscape.getDesktop(), "Please Select a Network and Query (not empty) First!", "NetMatch Error", JOptionPane.ERROR_MESSAGE);
        else {
          Common.LABELED = labeled.isSelected();
          Common.DIRECTED = directed.isSelected();
          log.setText("Start Matching...\n");
          netMatch netmatch;
          JTaskConfig config = new JTaskConfig();
          config.displayCancelButton(true);
          config.displayStatus(true);
          netMatchResultsDialog result;
          if(!isUsingQE)
            netmatch = new netMatch(this, tnetwork, listOfEdgeAttributes, listOfNodeAttributes, qnetwork, (String)qea.getSelectedItem(), (String)qna.getSelectedItem());
          else
            netmatch = new netMatch(this, tnetwork, listOfEdgeAttributes, listOfNodeAttributes, (GraphLoader)queries.get(q.substring(q.indexOf('-') + 1, q.length())),isQueryApproximate,qpaths);
          TaskManager.executeTask(netmatch, config);
          if(netmatch.isCompletedSuccessfully()) {
            ArrayList l2 = netmatch.getArrayDest();
           // ArrayList l1 = netmatch.getArraySource();
            if(!l2.isEmpty()) {
              //if(!isUsingQE)
              //printMatch(l1, qnetwork, l2, tnetwork);
              //else
              //printMatch(l1,l2,tnetwork);
              netMatchResultsTableModel tab = null;
              if(l2.size() < 500) {
                tab = new netMatchResultsTableModel(tnetwork,l2,true,!isQueryApproximate);
                TaskManager.executeTask(tab,config);
              }
              else {
                int r = chooseHowToShow(l2.size());
                if(r == 0) {// SHOW ALL
                  tab = new netMatchResultsTableModel(tnetwork,l2,true,!isQueryApproximate);
                  TaskManager.executeTask(tab,config);
                }
                else if(r == 1) {// SHOW ONLY TEXT
                  tab = new netMatchResultsTableModel(tnetwork,l2,false,!isQueryApproximate);
                  TaskManager.executeTask(tab,config);
                }
              }
              if(tab != null && tab.isCompletedSuccessfully()) {
                CytoscapeDesktop desktop = Cytoscape.getDesktop();
                CytoPanel cytoPanel = desktop.getCytoPanel(SwingConstants.EAST);
                result = new netMatchResultsDialog();
                if(!isUsingQE)
                  result.set(l2,tnetwork,tab,false,null);
                else
                  result.set(l2,tnetwork,tab,isQueryApproximate,netmatch.getApproximatePaths());
                cytoPanel.add("",menu[20], result,"NetMatch Results");
                int index = cytoPanel.indexOfComponent(result);
                cytoPanel.setSelectedIndex(index);
                cytoPanel.setState(CytoPanelState.DOCK);
              }
            }
            log.append("Found " + l2.size() + " matches!\r\n");
          }
          else
            log.setText("");
        }
      }
    }
    else if(o == query) {
      Object oldQea = qea.getSelectedItem();
      Object oldQna = qna.getSelectedItem();
      qea.removeAllItems();
      qna.removeAllItems();
      String qu = (String)query.getSelectedItem();
      String nn = qu.substring(0, qu.indexOf('-'));
      if(nn.equals("QE")) {
        qea.setEnabled(true);
        qna.setEnabled(true);
        qna.addItem(qu + " - Nodes Attributes");
        qea.addItem(qu + " - Edges Attributes");
      }
      else {
        CyAttributes nodesAttributes = Cytoscape.getNodeAttributes();
        CyAttributes edgesAttributes = Cytoscape.getEdgeAttributes();
        String attrs[] = edgesAttributes.getAttributeNames();
        for(String attr : attrs)
          if(edgesAttributes.getType(attr) != CyAttributes.TYPE_SIMPLE_LIST && edgesAttributes.getType(attr) != CyAttributes.TYPE_SIMPLE_MAP)
            qea.addItem(attr);
        attrs = nodesAttributes.getAttributeNames();
        for(String attr1 : attrs)
          if(nodesAttributes.getType(attr1) != CyAttributes.TYPE_SIMPLE_LIST && nodesAttributes.getType(attr1) != CyAttributes.TYPE_SIMPLE_MAP)
            qna.addItem(attr1);
        qna.addItem(Strings.DEFAULT_ATTRIBUTES);
        if(oldQea != null) {
          for(int i = 0;i < qea.getItemCount();i++) {
            Object o1 = qea.getItemAt(i);
            if(o1.equals(oldQea)) {
              qea.setSelectedItem(oldQea);
              break;
            }
          }
        }
        if(oldQna != null) {
          for(int i = 0;i < qna.getItemCount();i++) {
            Object o1 = qna.getItemAt(i);
            if(o1.equals(oldQna)) {
              qna.setSelectedItem(oldQna);
              break;
            }
          }
        }
      }
    }
  }

  private boolean areValidAttributes() {
    CyAttributes nodesAttributes = Cytoscape.getNodeAttributes();
    CyAttributes edgesAttributes = Cytoscape.getEdgeAttributes();
    if(nodesAttributes.getType((String)qna.getSelectedItem()) == CyAttributes.TYPE_SIMPLE_MAP ||
       nodesAttributes.getType((String)tna.getSelectedItem()) == CyAttributes.TYPE_SIMPLE_MAP)
      return false;
    if(edgesAttributes.getType((String)qea.getSelectedItem()) == CyAttributes.TYPE_SIMPLE_MAP ||
       edgesAttributes.getType((String)tea.getSelectedItem()) == CyAttributes.TYPE_SIMPLE_MAP)
      return false;
    return true;
  }

  private int chooseHowToShow(int matches) {
    Object[] message = new Object[4];
    message[0] = "The number of matches is " + matches + ". Choose one of the following options:";
    ButtonGroup g = new ButtonGroup();
    JRadioButton c1 = new JRadioButton("Show results in text and graphic mode.", false);
    JRadioButton c2 = new JRadioButton("Show results in text mode.", true);
    JRadioButton c3 = new JRadioButton("Don't show results.", false);
    g.add(c1);
    g.add(c2);
    g.add(c3);
    message[1] = c1;
    message[2] = c2;
    message[3] = c3;
    String[] options = {"Ok"};

    JOptionPane.showOptionDialog(Cytoscape.getDesktop(),      // the parent that the dialog blocks
        message,                         // the dialog message array
        "NetMatch",                      // the title of the dialog window
        JOptionPane.DEFAULT_OPTION,      // option type
        JOptionPane.INFORMATION_MESSAGE, // message type
        null,                            // optional icon, use null to use the default icon
        options,                         // options string array, will be made into buttons
        options[0]                       // option that should be made into a default button
    );
    if(c1.isSelected())
      return 0;
    else if(c2.isSelected())
      return 1;
    else
      return 2;
  }

  public void acquireData(String networkDestroyed) {
    query.removeActionListener(this);
    target.removeActionListener(this);
    tea.removeActionListener(this);
    tna.removeActionListener(this);

    Object oldQuery = query.getSelectedItem();
    Object oldTarget = target.getSelectedItem();
    Object oldQea = qea.getSelectedItem();
    Object oldQna = qna.getSelectedItem();
    Object oldTea = tea.getSelectedItem();
    Object oldTna = tna.getSelectedItem();

    query.removeAllItems();
    target.removeAllItems();
    qea.removeAllItems();
    qna.removeAllItems();
    tea.removeAllItems();
    tna.removeAllItems();

    query.setEnabled(false);
    target.setEnabled(false);
    tea.setEnabled(false);
    tna.setEnabled(false);
    qea.setEnabled(false);
    qna.setEnabled(false);

    Set s = Cytoscape.getNetworkSet();
    for(Object value : s) {
      CyNetwork n = (CyNetwork) value;
      if(!n.getIdentifier().equals(networkDestroyed)) {
        query.addItem(n.getIdentifier() + "-" + n.getTitle());
        target.addItem(n.getIdentifier() + "-" + n.getTitle());
      }
    }
    for(Object o1 : queries.keySet()) {
      Object o = "QE-" + o1;
      query.addItem(o);
      qea.addItem(o + " - Edges Attributes");
      qna.addItem(o + " - Nodes Attributes");
    }

    CyAttributes nodesAttributes = Cytoscape.getNodeAttributes();
    CyAttributes edgesAttributes = Cytoscape.getEdgeAttributes();
    String attrs[] = edgesAttributes.getAttributeNames();
    if(query.getItemCount() >0) {
      query.setEnabled(true);
      if(oldQuery != null) {
        for(int i = 0;i < query.getItemCount();i++) {
          Object o = query.getItemAt(i);
          if(o.equals(oldQuery)) {
            query.setSelectedItem(oldQuery);
            break;
          }
        }
      }
      String qu = (String)query.getSelectedItem();
      String nn = qu.substring(0, qu.indexOf('-'));
      if(!nn.equals("QE")) {
        for(int i = 0;i < attrs.length;i++)
          if(edgesAttributes.getType(attrs[i]) != CyAttributes.TYPE_SIMPLE_LIST && edgesAttributes.getType(attrs[i]) != CyAttributes.TYPE_SIMPLE_MAP)
            qea.addItem(attrs[i]);
        attrs = nodesAttributes.getAttributeNames();
        for(int i = 0;i < attrs.length;i++)
          if(nodesAttributes.getType(attrs[i]) != CyAttributes.TYPE_SIMPLE_LIST && nodesAttributes.getType(attrs[i]) != CyAttributes.TYPE_SIMPLE_MAP)
            qna.addItem(attrs[i]);
        qna.addItem(Strings.DEFAULT_ATTRIBUTES);
      }
      if(oldQea != null) {
        for(int i = 0;i < qea.getItemCount();i++) {
          Object o = qea.getItemAt(i);
          if(o.equals(oldQea)) {
            qea.setSelectedItem(oldQea);
            break;
          }
        }
      }
      if(oldQna != null) {
        for(int i = 0;i < qna.getItemCount();i++) {
          Object o = qna.getItemAt(i);
          if(o.equals(oldQna)) {
            qna.setSelectedItem(oldQna);
            break;
          }
        }
      }
      qna.setEnabled(true);
      qea.setEnabled(true);
    }

    listOfNodeAttributes = new ArrayList();
    listOfEdgeAttributes = new ArrayList();
    if(target.getItemCount() >0) {
      target.setEnabled(true);
      if(oldTarget != null) {
        for(int i = 0;i < target.getItemCount();i++) {
          Object o = target.getItemAt(i);
          if(o.equals(oldTarget)) {
            target.setSelectedItem(oldTarget);
            break;
          }
        }
      }
      attrs = edgesAttributes.getAttributeNames();
      for(int i = 0;i < attrs.length;i++)
        tea.addItem(attrs[i]);
      tea.addItem(Strings.LIST_ATTRIBUTES);
      attrs = nodesAttributes.getAttributeNames();
      for(int i = 0;i < attrs.length;i++)
        tna.addItem(attrs[i]);
      tna.addItem(Strings.DEFAULT_ATTRIBUTES);
      tna.addItem(Strings.LIST_ATTRIBUTES);

      if(oldTea != null) {
        for(int i = 0;i < tea.getItemCount();i++) {
          Object o = tea.getItemAt(i);
          if(o.equals(oldTea)) {
            tea.setSelectedItem(oldTea);
            break;
          }
        }
      }
      if(oldTna != null) {
        for(int i = 0;i < tna.getItemCount();i++) {
          Object o = tna.getItemAt(i);
          if(o.equals(oldTna)) {
            tna.setSelectedItem(oldTna);
            break;
          }
        }
      }
      tea.setEnabled(true);
      tna.setEnabled(true);
      listOfNodeAttributes.add(tna.getSelectedItem());
      listOfEdgeAttributes.add(tea.getSelectedItem());
    }
    query.addActionListener(this);
    target.addActionListener(this);
    tna.addActionListener(this);
    tea.addActionListener(this);
  }

  private JToolBar createMenuBar() {
    JToolBar toolBar = new JToolBar();
    JButton i;
    i = new JButton(menu[12]);
    i.setToolTipText("Close Netmatch");
    i.addActionListener(this);
    i.setActionCommand("Exit");
    toolBar.add(i);
    toolBar.addSeparator();
    i = new JButton(menu[14]);
    i.setToolTipText("Draw a Query");
    i.addActionListener(this);
    i.setActionCommand("Draw...");
    toolBar.add(i);
    i = new JButton(menu[18]);
    i.setToolTipText("Switch to wizard mode");
    i.addActionListener(this);
    i.setActionCommand("Switch to wizard mode");
    toolBar.add(i);
    toolBar.addSeparator();
    i = new JButton(menu[17]);
    i.setToolTipText("About...");
    i.addActionListener(this);
    i.setActionCommand("About...");
    toolBar.add(i);
    i = new JButton(menu[16]);
    i.setToolTipText("Documentation");
    i.addActionListener(this);
    i.setActionCommand("Documentation");
    toolBar.add(i);
    return toolBar;
  }

  /*private void printMatch(ArrayList s, CyNetwork q, ArrayList d, CyNetwork t) {
    for(int i = 0;i < s.size();i++) {
      int tmp1[] = (int[])s.get(i);
      int tmp2[] = (int[])d.get(i);
      log.append("**** Match " + (i + 1) + "\n");
      for(int j = 0;j < tmp1.length;j++)
        log.append(q.getNode(tmp1[j]).getIdentifier() + " matches " + t.getNode(tmp2[j]).getIdentifier() + "\n");
    }
    log.append("************\n");
  }

  private void printMatch(ArrayList s, ArrayList d, CyNetwork t) {
    for(int i = 0;i < s.size();i++) {
      int tmp1[] = (int[])s.get(i);
      int tmp2[] = (int[])d.get(i);
      log.append("**** Match " + (i + 1) + "\n");
      for(int j = 0;j < tmp1.length;j++)
        log.append(tmp1[j] + " matches " + t.getNode(tmp2[j]).getIdentifier() + "\n");
    }
    log.append("************\n");
  }*/

  public void addQueryStructure(String name, GraphLoader g) {
    if(!queries.containsKey(name)) {
      query.addItem("QE-" + name);
      query.setSelectedItem("QE-" + name);
      query.setEnabled(true);
    }
    queries.put(name,g);
    if(wizardForm.isVisible())
      wizardForm.editorDone("QE-" + name);
  }

  public void deattachRecipient() {
    isEditorOpen = false;
  }

  public void setQueryApproximate(boolean value) {
    isQueryApproximate = value;
  }

  public void addQPath(String path) {
    qpaths.add(path);
  }

  public void clearPaths() {
    qpaths.removeAllElements();
  }

  public void setAttrList(ArrayList attrs,boolean isNodeAttr) {
    JComboBox c = isNodeAttr ? tna : tea;
    c.removeActionListener(this);
    if(attrs == null) {
      c.removeItem(Strings.LIST_ATTRIBUTES);
      c.removeItem(Strings.LIST_ATTRIBUTES_CHANGED);
      c.addItem(Strings.LIST_ATTRIBUTES);
      c.setSelectedIndex(0);
      if(isNodeAttr)
        listOfNodeAttributes = null;
      else
        listOfEdgeAttributes = null;
    }
    else {
      c.removeItem(Strings.LIST_ATTRIBUTES);
      c.removeItem(Strings.LIST_ATTRIBUTES_CHANGED);
      c.addItem(Strings.LIST_ATTRIBUTES_CHANGED);
      c.setSelectedItem(Strings.LIST_ATTRIBUTES_CHANGED);
      if(isNodeAttr)
        listOfNodeAttributes = attrs;
      else
        listOfEdgeAttributes = attrs;
    }
    c.addActionListener(this);
  }

  public void printArrayList(ArrayList l) {
    for(Iterator iterator = l.iterator();iterator.hasNext();) {
      Object o = iterator.next();
      System.out.print(o+" ");
    }
    System.out.println();
  }

  public void close() {
    if(isEditorOpen)
      qEditor.exit();
    if(wizardForm.isEnabled())
      wizardForm.dispose();
    if(help != null) {
      help.setVisible(false);
      help.dispose();
    }
    if(aboutbox != null) {
      aboutbox.setVisible(false);
      aboutbox.dispose();
    }

    CytoscapeDesktop desktop = Cytoscape.getDesktop();
    boolean resultsClosed = true;

    CytoPanel cytoPanel = desktop.getCytoPanel(SwingConstants.EAST);
    for (int c = cytoPanel.getCytoPanelComponentCount() - 1; c >= 0; c--) {
      cytoPanel.setSelectedIndex(c);
      Component component = cytoPanel.getSelectedComponent();
      if (component instanceof netMatchResultsDialog)
        cytoPanel.remove(component);
      else
        resultsClosed = false;
    }
    if (cytoPanel.getCytoPanelComponentCount() == 0)
      cytoPanel.setState(CytoPanelState.HIDE);
    if(resultsClosed) {
      cytoPanel = desktop.getCytoPanel(SwingConstants.WEST);
      cytoPanel.remove(this);
      trigger.setOpened(false);
    }
  }
}

/*class NetworkChangeListener implements PropertyChangeListener {
  netMatchPanel p;

  NetworkChangeListener(netMatchPanel p) {
    this.p = p;
  }*/

  /**
   * Property change listener - to get network modified events.
   *
   * @param event PropertyChangeEvent
   */
 /* public void propertyChange(PropertyChangeEvent event) {
    if(event.getPropertyName() != null) {
      if(event.getPropertyName().equals(Cytoscape.NETWORK_MODIFIED) ||
         event.getPropertyName().equals(Cytoscape.NETWORK_LOADED) ||
          event.getPropertyName().equals(Cytoscape.NETWORK_DESTROYED) ||
          event.getPropertyName().equals(Cytoscape.NETWORK_CREATED)) {
        System.out.println("EVENT CHANGE NETWORK 2:"+Cytoscape.getNetworkSet().isEmpty());
        p.acquireData();
        System.out.println("EVENT CHANGE NETWORK 2:"+Cytoscape.getNetworkSet().isEmpty());
      }
    }
	}
} */
