package org.jcon.inspect;

import org.jcon.util.ArraySorter;
import org.jcon.util.BeanLib;
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.util.Hashtable;
import java.util.Vector;
import java.beans.MethodDescriptor;
import java.lang.reflect.Method;

import javax.swing.JComponent;

/**
 * Allows method display and invocation. CONTROLLER.
 *
 * @author Jack Harich
 */
public class MethodSheet implements
    MessageListener, ArraySorter.Comparer {

//---------- Private Fields ------------------------------
private MessageRouter   router;
private MethodSheetView view = new MethodSheetView();
private MethodInvoker   methodInvoker = new MethodInvoker();
private Object          instance;

//---------- Initialization ------------------------------
public MethodSheet() {
    methodInvoker.setView(view);
}
//---------- MessageListener Implementation --------------
public void processMessage(Message message) {
    if (message.getName().equals("InvokeMethod")) {
        // Invoke
        Method method = (Method)message.get("Method");
        MethodArgument[] argList = (MethodArgument[])message.get("ArgumentList");
        methodInvoker.invoke(method, argList);
        // Refresh properties
        router.fire("RefreshProperties", this);
    }
}
public String[] loadMessageInterests() {
    return new String[] {"InvokeMethod"};
}
//---------- ArraySorter.Comparer Implementation ---------
public int compare(Object a, Object b) {
    // Sort MethodDescriptor[] by getName(). This should be in BeanInfo or...
    MethodDescriptor da = (MethodDescriptor)a;
    MethodDescriptor db = (MethodDescriptor)b;

    String aName = da.getName();
    String bName = db.getName();

    return aName.compareTo(bName);
}
//---------- Public Methods ------------------------------
public void setHub(Hub hub) {
    view.setHub(hub);
    methodInvoker.setHub(hub);
    router = hub.getRouter();
    router.addListener("InvokeMethod", this);
}
public JComponent getComponent() {
    return view.getComponent();
}
public void loadMethods(MethodDescriptor[] mds, Object instance) {
    this.instance = instance;
    view.emptyMethods();
    view.setStatus("", "");
    methodInvoker.setInstance(instance);
    ArraySorter.sort(mds, this);
    for (int i = 0; i < mds.length; i++) {
        MethodDescriptor md = mds[i];
        Method method = md.getMethod();
        String name = method.getName();

        // Screen out Object methods
        if (method.getDeclaringClass() == Object.class) continue;

        // Build arguments description
        Class[] argTypes = method.getParameterTypes();
        String argDescription = ""; // No arguments
        for (int j = 0; j < argTypes.length; j++) {
            argDescription += BeanLib.extractDisplayTypeName(argTypes[j]);
            if (j < argTypes.length - 1) argDescription += ", ";
        }
        // Add to view
        view.addMethod(method, argDescription);
    }
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("MethodSheet" + text);
}

} // End class
