package mambo;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.tree.TreePath;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import java.awt.event.*;
import java.awt.*;
import java.sql.SQLException;

import fr.soleil.TangoHdb.HdbApi.*;
import fr.esrf.tangoatk.widget.util.chart.JLChart;

public class MainPanel extends JFrame {

  private String appVersion = "Mambo 1.0";
  private HdbDataBase theDB;
  private boolean runningFromShell = false;
  private JPanel innerPanel;

  // Tree stuff
  private JTree mainTree = null;
  private DefaultTreeModel mainTreeModel;
  private DefaultMutableTreeNode rootNode;
  private MouseListener treeMousellistemner;
  private MouseListener valueMousellistemner;
  private TreeSelectionListener treeSelectionlistemner;
  private JScrollPane treeView;
  private JPopupMenu treeMenu;
  private JMenuItem[] treeMenuItem;
  private HdbTreeNodeRenderer renderer;


  //Trend
  JLChart theGraph;

  //Main menu
  private JMenuBar mainMenu;

  MainPanel() {
    initComponents();
  }

  public void initComponents() {

    // Create a Handle to the DataBase
    theDB = new HdbDataBase(HdbConfigConst.default_db_type, HdbConfigConst.default_host, "extractor", "extractor", HdbConfigConst.default_bd);
    try {
      theDB.connect();
    } catch (SQLException e) {
      showError("Cannot connect to HDB\n" + e.getMessage());
      exitForm();
    }
    setTitle(appVersion + " [ Connected on " + theDB.getHost() + "." + theDB.getName() + "]");

    // Build the GUI
    getContentPane().setLayout(new GridLayout(1, 0));
    innerPanel = new JPanel();
    getContentPane().add(innerPanel);
    innerPanel.setLayout(new BorderLayout());

    // Trend stuff
    theGraph = new JLChart();
    theGraph.setBorder(new javax.swing.border.EtchedBorder());
    theGraph.setBackground(new java.awt.Color(180, 180, 180));
    theGraph.getY1Axis().setAutoScale(true);
    theGraph.getY2Axis().setAutoScale(true);
    theGraph.getXAxis().setAutoScale(true);
    innerPanel.add(theGraph, BorderLayout.CENTER);

    // HDB Tree Sutff
    treeMousellistemner = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        innerPanel.revalidate();
        TreePath selPath = mainTree.getPathForLocation(e.getX(), e.getY());
        int selRow = mainTree.getRowForLocation(e.getX(), e.getY());
        if (selRow != -1) {
          if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON3) {
            if (selPath != null) {

              // Force single selection on right click
              mainTree.setSelectionPath(selPath);
              HdbTreeNode n = (HdbTreeNode) selPath.getLastPathComponent();
              boolean[] menuState = n.getAction();
              if (menuState != null) {
                for (int i = 0; i < menuState.length; i++) {
                  treeMenuItem[i].setEnabled(menuState[i]);
                  //treeMenuItem[i].setVisible(menuState[i]);
                }
                treeMenu.show(mainTree, e.getX(), e.getY());
              }

            }
          }
        }
      }
    };

    treeSelectionlistemner = new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
      }
    };

    createMainTree();
    innerPanel.add(treeView, BorderLayout.WEST);

    // Item popup menu
    treeMenu = new JPopupMenu();
    treeMenuItem = new JMenuItem[HdbTreeNode.nbAction];

    for (int i = 0; i < HdbTreeNode.nbAction; i++) {
      treeMenuItem[i] = new JMenuItem();
      treeMenuItem[i].setText(HdbTreeNode.ItemAction[i]);
      treeMenuItem[i].setEnabled(false);

      treeMenuItem[i].addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          execMenuAction(evt);
        }
      });
    }

    for (int i = 0; i < HdbTreeNode.nbAction; i++) {
      treeMenu.add(treeMenuItem[i]);
    }

    // main menu
    mainMenu = new JMenuBar();
    JMenu m1 = new JMenu("File");
    JMenu m2 = new JMenu("Options");
    JMenu m3 = new JMenu("Query");

    JMenuItem m11 = new JMenuItem("Exit");
    m11.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        exitForm();
      }
    });

    JMenuItem m21 = new JMenuItem("Graph settings");
    m21.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        showGraphOption();
      }
    });

    JCheckBoxMenuItem m22 = new JCheckBoxMenuItem("View " + theDB.getName() + " tree");
    m22.setSelected(true);
    m22.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        JCheckBoxMenuItem m = (JCheckBoxMenuItem)evt.getSource();
        if( !m.isSelected() ) {
          innerPanel.remove(treeView);
          m.setSelected(false);
        } else {
          innerPanel.add(treeView,BorderLayout.WEST);
          m.setSelected(true);
        }
        innerPanel.revalidate();
      }
    });

    JMenuItem m31 = new JMenuItem("Request data");
    m31.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        TreePath[] selPath = mainTree.getSelectionPaths();
        if (selPath != null) {
          if (selPath.length > 0) {
            executeRequest(selPath);
            mainTree.repaint();
            return;
          }
        }
        showError("No item selected.");
      }
    });

    m1.add(m11);
    m2.add(m21);
    m2.add(m22);
    m3.add(m31);
    mainMenu.add(m1);
    mainMenu.add(m2);
    mainMenu.add(m3);
    setJMenuBar(mainMenu);

    // Componenent listeners
    addComponentListener(new ComponentListener() {
      public void componentHidden(ComponentEvent e) {
        exitForm();
      }

      public void componentMoved(ComponentEvent e) {
      }

      public void componentResized(ComponentEvent e) {
      }

      public void componentShown(ComponentEvent e) {
      }
    });


    centerWindow();
    setVisible(true);
  }

  public void showGraphOption() {
    theGraph.showOptionDialog();
  }

  public void executeRequest(TreePath[] selPath) {
    HdbQueryDlg dlg;

    if (selPath.length == 1) {
      HdbTreeNode n = (HdbTreeNode) selPath[0].getLastPathComponent();
      if (!n.isLeaf()) return;
      dlg = new HdbQueryDlg("Resquesting data for " + n.getAttributeName(), this);
    } else {
      dlg = new HdbQueryDlg("Resquesting data for " + selPath.length + " attributes", this);
    }

    QueryInfo qi = dlg.showDlg();

    if (qi != null) {
      String errAll = null;
      this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

      for (int i = 0; i < selPath.length; i++) {
        HdbTreeNode n = (HdbTreeNode) selPath[i].getLastPathComponent();
        if (n.isLeaf()) {
          String err = n.retrieveData(qi, theDB);
          if (err != null) {
            if( errAll==null )  {
              errAll = err;
            } else  {
              if( errAll.endsWith("\n") )
                errAll = errAll + "----------------------------------------\n" + err;
              else
                errAll = errAll + "\n----------------------------------------\n" + err;
            }
          }
        }
      }

      this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

      if (errAll!=null) showError(errAll);
    }

  }

  public void execMenuAction(ActionEvent evt) {

    JMenuItem sel = (JMenuItem) evt.getSource();
    int i = 0;
    boolean found = false;
    while (i < HdbTreeNode.nbAction && !found) {
      found = (sel == treeMenuItem[i]);
      if (!found) i++;
    }

    if (!found) return;

    HdbTreeNode n = (HdbTreeNode) mainTree.getSelectionPath().getLastPathComponent();

    switch (i) {

      case 0: //Request data
        TreePath[] p = new TreePath[1];
        p[0] = mainTree.getSelectionPath();
        executeRequest(p);
        break;

      case 1: //Plot on Y1
        n.setSelected(HdbTreeNode.SELY1);
        break;

      case 2: //Plot on Y2
        n.setSelected(HdbTreeNode.SELY2);
        break;

      case 3: //Set on X axis
        n.setSelected(HdbTreeNode.SELX);
        break;

      case 4: //Unselect
        n.setSelected(HdbTreeNode.SELNONE);
        break;

      case 5: //Settings
        n.showOptions(this);
        break;

    }

    mainTree.repaint();

  }

  // create the main tree
  private void createMainTree() {
    renderer = new HdbTreeNodeRenderer();
    rootNode = new HdbTreeNode(theDB.getName(), 0, theGraph);
    mainTreeModel = new DefaultTreeModel(rootNode);
    mainTree = new JTree(mainTreeModel);
    mainTree.setEditable(false);
    mainTree.setCellRenderer(renderer);
    mainTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
    mainTree.setShowsRootHandles(true);
    mainTree.setBorder(BorderFactory.createLoweredBevelBorder());
    treeView = new JScrollPane(mainTree);
    mainTree.addMouseListener(treeMousellistemner);
    mainTree.addTreeSelectionListener(treeSelectionlistemner);
  }

  // Center the window
  public void centerWindow() {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Dimension scrsize = toolkit.getScreenSize();
    Dimension appsize = new Dimension(750, 500);
    int x = (scrsize.width - appsize.width) / 2;
    int y = (scrsize.height - appsize.height) / 2;
    setBounds(x, y, appsize.width, appsize.height);
  }

  public void exitForm() {
    if (runningFromShell) {
      System.exit(0);
    } else {
      setVisible(false);
      dispose();
    }
  }

  public void showError(String msg) {
    JOptionPane.showMessageDialog(this, msg, "Mambo error", JOptionPane.ERROR_MESSAGE);
  }

  public static void main(String args[]) {
    final MainPanel m = new MainPanel();
  }

}