package org.jcon.inspect;

import org.jcon.util.DataLib;
import org.jcon.util.Hub;
import org.jcon.util.GenLib;
import java.lang.reflect.Method;

/**
 * Invokes methods in the MethodSheet.
 *
 * @author Jack Harich
 */
public class MethodInvoker {

//---------- Private Fields ------------------------------
private Hub             hub;
private MethodSheetView view;  // For setStatus()
private Object          instance;

//---------- Properties ----------------------------------
public void setView(MethodSheetView view) {
    this.view = view;
}
public void setInstance(Object instance) {
    this.instance = instance;
}
public void setHub(Hub hub) {
    this.hub = hub;
}
//---------- Public Methods ------------------------------
public void invoke(Method method, MethodArgument[] argList) {
    Class[]  argTypes = method.getParameterTypes();
    Object[] args = new Object[argTypes.length];
    // Assert correct number arguments
    if (argTypes.length != argList.length) {
        String status2 = "Expected " +
            argTypes.length + " args but received " + argList.length;
        print(".invoke() - " + status2);
        GenLib.beep();
        view.setStatus("Error - Incorrect number arg types.",status2);
        return;
    }
    // Build args
    for (int i = 0; i < args.length; i++) {
        if (argList[i].isString()) {
            String argument = (String)argList[i].getValue();
            // This modifies args[i]
            if (buildStringArgument(i, args, argTypes[i],
                    argument) == false) {
                return;
            }
        } else {
            //GenLib.beep();
            //view.setStatus("Not String argument.", "");
            //return;
            args[i] = argList[i].getValue();
        }
    }
    // Invoke method
    try {
        Object result = method.invoke(instance, args);
        String status = "";
        //print(" - method.getReturnType() " + method.getReturnType());
        if (method.getReturnType() == Void.TYPE) {
            status = "Result = void";
        } else if (result == null) {
            status = "Result is null";
        } else {
            status = "Result = " + result.toString();
            InspectClipboard.postMethodArgument(hub,
                result, method.getReturnType() );
            // ***putOnClipboard(result, method.getReturnType() );
        }
        view.setStatus(method.getName()
            + "  invoked.", status);

    } catch(Exception ex) {
        GenLib.beep();
        view.setStatus("Exception:", ex.getClass().getName());

        print(".invokeMethod() - no arg\n");
        ex.printStackTrace();
    }
}
//---------- Private Methods -----------------------------
/** private void putOnClipboard(Object result, Class type) {
    InspectClipboard clipboard = (InspectClipboard)
        hub.getNaming().get("Clipboard");
    MethodArgument argument;
    // String or Reference
    if (result.getClass().getName().equals("java.lang.String") ) {
        argument = new MethodArgument((String)result);
    } else {
        argument = new MethodArgument(result, type);
    }
    clipboard.setValue(argument);
} */
private boolean buildStringArgument(int i, Object[] args,
    Class argType, String argument) {

    argument = argument.trim(); // In a few cases this is undesirable

    if (argType == String.class) {
        // Single String arg
        args[i] = argument;

    } else if (argType == Integer.TYPE) {
        // Single int arg
        if (DataLib.isInt(argument)) {
            args[i] = Integer.valueOf(argument);
        } else {
            GenLib.beep();
            view.setStatus("int argument "
                + "required.", "'" + argument + "' is not an int.");
            return false;
        }
    } else if (argType == Boolean.TYPE) {
        // Single boolean arg
        if (DataLib.isBoolean(argument)) {
            args[i] = Boolean.valueOf(argument);
        } else {
            GenLib.beep();
            view.setStatus("boolean argument "
                + "required.", "'" + argument + "' is not 'true' or 'false'.");
            return false;
        }
    } else {
        GenLib.beep();
        view.setStatus("Not supported.", "Only String, int, boolean implemented.");
        return false;
    }
    return true;
}
//--- Std
private static void print(String text) {
    System.out.println("MethodInvoker" + text);
}

} // End class
