package org.jcon.inspect;

import org.jcon.util.BeanLib;
import org.jcon.util.Hub;
import org.jcon.util.msg.Message;
import org.jcon.util.msg.MessageRouter;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.lang.reflect.Method;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

/**
 * The method sheet VIEW. Fires events to router.
 *
 * @author Jack Harich
 */
public class MethodSheetView implements MouseListener {

//---------- Private Fields ------------------------------
private MethodArgumentMgr argumentMgr = new MethodArgumentMgr();
private MessageRouter router;

private JPanel            mainPanel = new JPanel();
private JPanel            argPanel = new JPanel();
private MyTableModel tableModel = new MyTableModel();
private JTable            table = new JTable(tableModel);
private JScrollPane       tableScrollpane = new JScrollPane(table);
private Vector rows = new Vector(); // MethodRowData

// Label is not visible if no text when layout done
private JLabel     status1 = new JLabel(" Status1");
private JLabel     status2 = new JLabel(" Status2");

private int        currentIndex = -1;

//---------- Initialization ------------------------------
public MethodSheetView() {
    // Prepare table *** Exact Col widths LATER
    tableModel.addColumn("Method");
    tableModel.addColumn("Arguments");

    //--- Init argumentMgr
    argumentMgr.setMainPanel(mainPanel);
    argumentMgr.setArgPanel(argPanel);
    argumentMgr.setRows(rows);

    //--- Prepare table
    table.addMouseListener(this);
    table.setBackground(Color.lightGray);
    table.setAutoCreateColumnsFromModel(false);

    // Prepare statusPanel
    JPanel statusPanel = new JPanel();
    statusPanel.setBackground(Color.cyan);
    statusPanel.setLayout(new BorderLayout());
    statusPanel.add("North", status1);
    statusPanel.add("South", status2);

    // Layout mainPanel
    mainPanel.setLayout(new BorderLayout());
    mainPanel.add("North",  statusPanel);
    mainPanel.add("Center", tableScrollpane);
    mainPanel.add("South",  argPanel);
}
//---------- MouseListener Implementation ----------------
public void mouseClicked(MouseEvent evt) {
    // Assertions
    if (evt.getSource() != table) return;
    int rowIndex = table.getSelectedRow();
    if (rowIndex < 0) return; // No row selected

    // 1 or 2 clicks may have occurred
    setupArgumentFields(rowIndex);

    if (evt.getClickCount() == 2) {
        // Double click - Fire ExploreProperty event
        Message message = new Message("InvokeMethod");
        MethodRowData rowData = (MethodRowData)rows.elementAt(rowIndex);
        message.set("Method", rowData.getMethod());
        message.set("ArgumentList",
            argumentMgr.getArguments(currentIndex));
        router.fire(message, this);
    }
}
public void mousePressed(MouseEvent evt) { }
public void mouseReleased(MouseEvent evt) { }
public void mouseEntered(MouseEvent evt) { }
public void mouseExited(MouseEvent evt) { }

//---------- Public Methods ------------------------------
public void setHub(Hub hub) {
    router = hub.getRouter();
    argumentMgr.setHub(hub);
}
public JComponent getComponent() {
    return mainPanel;
}
public void emptyMethods() {
    while (tableModel.getRowCount() > 0) {
        tableModel.removeRow(0);
    }
    rows.removeAllElements();
    currentIndex = -1;
    argumentMgr.createArgTextFields(-1);
}
public void addMethod(Method method, String args) {
    String name = method.getName();
    String[] row = { " " + name, " " + args };
    tableModel.addRow(row);
    rows.addElement(new MethodRowData(method));
}
// If null no change
public void setStatus(String text1, String text2) {
    if (status1 != null) status1.setText(" " + text1);
    if (status2 != null) status2.setText(" " + text2);
}
//---------- Private Methods -----------------------------
private void setupArgumentFields(int rowIndex) {

    // Check for row change
    if (rowIndex == currentIndex) return; // No change

    // Preserve old values before changing row
    if (currentIndex >= 0) argumentMgr.saveRowArguments(currentIndex);

    // Change to selected row
    currentIndex = rowIndex; // <-----<<< set  in 2 places
    MethodRowData rowData = (MethodRowData)rows.elementAt(currentIndex);

    // Show return type
    Method method = rowData.getMethod();
    String returnType = BeanLib.extractFullDisplayTypeName(
        method.getReturnType());
    setStatus("Return type is:", returnType);

    // Populate text fields with values
    argumentMgr.populateTextFields(currentIndex);
}
//--- Std
private static void print(String text) {
    System.out.println("MethodSheetView" + text);
}
//========== Inner Classes ===============================
// Implemented solely because there is no property setEditable(false)
// This is poor design
class MyTableModel extends DefaultTableModel {
    // ----- Superclass Overrides -----
    public boolean isCellEditable(int row, int col) {
        return false;
    }

} // End inner class

} // End outer class
