package org.jcon.inspect;

import org.jcon.ui.WindowLib;
import org.jcon.ui.WindowMgr;
import org.jcon.util.Hub;
import org.jcon.util.msg.Message;
import org.jcon.util.msg.MessageListener;
import org.jcon.util.msg.MessageRouter;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import java.beans.*;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * The bean inspector VIEW.
 *
 * @author Jack Harich
 */
public class View implements
    ActionListener, WindowListener, MessageListener {

//---------- Private Fields ------------------------------
private Inspector       inspector;
private MessageRouter   router;
private JFrame          frame = new JFrame("Auto Inspector");
private JPanel          mainPanel = new JPanel();
private JLabel          classNameLbl = new JLabel();
private JPanel          buttonBar = new JPanel();
private BetterJButton   returnBtn;
private BetterJButton   tabBtn;
private BetterJButton   exploreClipboardBtn;
private boolean         isSplit = false; // Initially

private PropertySheet propertySheet = new PropertySheet();
private MethodSheet   methodSheet   = new MethodSheet();
private MessageSheet  messageSheet  = new MessageSheet(this);

//---------- Initialization ------------------------------
public View(Inspector inspector) {
    this.inspector = inspector;

    //----- Prepare frame
    WindowMgr.registerFrame((Frame)frame);
    frame.setBackground(Color.lightGray);
    frame.setSize(260, 500);
    WindowLib.center(frame);
    mainPanel.setLayout(new BorderLayout());
    Container contentPane = frame.getContentPane();
    // North
    contentPane.add("North",  classNameLbl);
    // Center
    contentPane.add("Center", mainPanel);
    // South
    createButton("Refresh", "Refresh", "Refreshes properties and messages");
    createButton("New",     "NewInspector", "Opens a new identical Inspector");
    returnBtn = createButton("Return", "ReturnFromProperty", "Returns to the container of this instance");
    returnBtn.setEnabled(false);
    // *** Swing bug - tabBtn = createButton("Tabs", "ToggleTabs", "Toggles between splitter and tabs");
    exploreClipboardBtn = createButton("IClip", "InspectClipboard", "Inspect Clipboard - Opens an Inspector on the clipboard instance");
    contentPane.add("South", buttonBar);

    prepareMainPanel();

    //----- Listeners
    frame.addWindowListener(this);
}
private void prepareMainPanel() {
    mainPanel.removeAll();
    if (isSplit) {
        // (no messageSheet in split version)
        // splitPane contains property and method sheet
        JSplitPane splitPane = new JSplitPane(JSplitPane.
            VERTICAL_SPLIT, propertySheet.getComponent(),
            methodSheet.getComponent());
        splitPane.setDividerLocation(150); // *** No effect
        mainPanel.add("Center", splitPane);
        // Set min size so user can move splitter anywhere
        propertySheet.getComponent().setMinimumSize(new Dimension(100, 0));
        methodSheet.getComponent().setMinimumSize(new Dimension(100, 0));
    } else {
        // *** Swing bug - switched if changed
        JTabbedPane tabbedPane = new JTabbedPane();
        mainPanel.add("Center", tabbedPane);
        // Prepare tabbedPane
        tabbedPane.addTab("Messages", messageSheet.getComponent());
        tabbedPane.addTab("Properties", propertySheet.getComponent());
        tabbedPane.addTab("Methods", methodSheet.getComponent());
        tabbedPane.setSelectedIndex(0); // Required to avoid bug, 0, 1 or 2 is okay
    }
    // *** disabled - tabBtn.setText(isSplit ? "Tabs" : "Split");
    mainPanel.validate();
}
//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
    String command = evt.getActionCommand();

    if (command.equals("ToggleTabs")) {
        setSplit(! isSplit);

    } else if (command.equals("Refresh")) {
        propertySheet.refresh();
        messageSheet.refresh();

    } else if (command.equals("ReturnFromProperty")) {
        router.fire(new Message(command), this);

    } else if (command.equals("NewInspector")) {
        router.fire(new Message(command), this);

    } else if (command.equals("InspectClipboard")) {
        router.fire(new Message(command), this);

    } else {
        print(".actionPerformed() - Unknown command " + command);
    }
}
//---------- WindowListener Implementaton ----------------
public void windowClosing(WindowEvent evt) {
    router.fire(new Message("CloseViewWindowRequest"), this);
}
public void windowClosed(WindowEvent evt) { }
public void windowDeiconified(WindowEvent evt) { }
public void windowIconified(WindowEvent evt) { }
public void windowOpened(WindowEvent evt) { }
public void windowActivated(WindowEvent evt) { }
public void windowDeactivated(WindowEvent evt) { }

//---------- MessageListener Implementation --------------
public void processMessage(Message message) {
    String event = message.getName();

    if (event.equals("UpdateViewReturnEnabled")) {
        returnBtn.setEnabled(message.isTrue("IsEnabled"));

    } else if (event.equals("RefreshProperties")) {
        propertySheet.refresh();
    }
}
public String[] loadMessageInterests() {
    return new String[] {"UpdateViewReturnEnabled",
        "RefreshProperties"};
}
//---------- Properties ----------------------------------
public void setHub(Hub hub) {
    router = hub.getRouter();
    propertySheet.setHub(hub);
    methodSheet.setHub(hub);
    messageSheet.setHub(hub);

    router.addListener("UpdateViewReturnEnabled", this);
    router.addListener("RefreshProperties", this);
}
public void setWindowPosition(int position) {
    WindowLib.position(frame, position);
}
//----- Title
public void setTitle(String title) {
    frame.setTitle(title);
}
public void setClassName(String className) {
    classNameLbl.setText(className);
}
//----- Visible
public void setVisible(boolean isVisible) {
    frame.setVisible(isVisible);
}
public boolean isVisible() {
    return frame.isVisible();
}
//----- Bounds
public Rectangle getBounds() {
    return frame.getBounds();
}
public void setBounds(int x, int y, int width, int height) {
    frame.setBounds(x, y, width, height);
}
//----- Split
public boolean isSplit() {
    return isSplit;
}
public void setSplit(boolean isSplit) {
    boolean oldIsSplit  = this.isSplit;
    this.isSplit = isSplit;
    if (this.isSplit != oldIsSplit) {
        buttonBar.validate();
        prepareMainPanel();
    }
}
//---------- Public Methods ------------------------------
public void close() {
    frame.setVisible(false);
    frame.dispose();
}
public void requestFocus() {
    frame.requestFocus();
}
public void loadBeanInfo(BeanInfo info, Object instance) {
    propertySheet.loadProperties(info.getPropertyDescriptors(), instance);
    methodSheet.loadMethods(info.getMethodDescriptors(), instance);
    messageSheet.load(instance);
}
public Vector loadSignalChain(String eventName, Object instance) {
    return inspector.loadSignalChain(eventName, instance);
}
//---------- Private Methods -----------------------------
private BetterJButton createButton(String text,
        String command, String toolTipText) {
    // BetterJButton has smaller left and right insets
    BetterJButton button = new BetterJButton(text);
    button.setActionCommand(command);
    button.addActionListener(this);
    button.setToolTipText(toolTipText);
    buttonBar.add(button);
    return button;
}
//--- Std
private static void print(String text) {
    System.out.println("View" + text);
}

} // End class
