/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.framework.management.http;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.jfox.framework.ComponentName;
import org.jfox.framework.Registry;
import org.jfox.framework.extra.ManagementInfo;
import org.jfox.framework.extra.ManagementOperationInfo;
import org.jfox.framework.util.Classes;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class InvokeComponentCommand implements Command {

    public String doGet(Registry registry, Properties queryMap) throws Exception {
        String compName = queryMap.getProperty("compname");
        ComponentName componentName = ComponentName.parseString(compName, registry.getClassLoaderRepository());

        String operHashCode = queryMap.getProperty("operHashCode");
        ManagementInfo minfo = registry.getComponentMeta(componentName).getManagementInfo();
        ManagementOperationInfo operInfo = minfo.getManagementOperationInfo(operHashCode);
        Method method = operInfo.getMethod();
        Class[] paramTypes = method.getParameterTypes();
        String[] _values = new String[paramTypes.length];
        for(int i = 0; i < paramTypes.length; i++) {
            String _value = queryMap.getProperty(operInfo.getName() + "_" + i);
            if(_value == null) _value = "";
            _values[i] = _value.trim();
        }

        Object result = null;
        try {
            Object[] values = createObjects(_values, paramTypes);
            result = method.invoke(registry.getComponentInstance(componentName), values);
        }
        catch(Exception e) {
            e.printStackTrace();
            result = e;
        }

        StringBuffer sb = new StringBuffer();
        sb.append(PageUtil.head("result view"));
        sb.append(PageUtil.banner("Result View"));
        sb.append(mxOperInfoTable(operInfo, result));
        sb.append(linkTable(compName));
        sb.append(PageUtil.foot());
        return sb.toString();

    }

    private static String mxOperInfoTable(ManagementOperationInfo operInfo, Object result) {
        Class[] paramInfo = operInfo.getMethod().getParameterTypes();
        String paramString = "";
        for(int j = 0; j < paramInfo.length; j++) {
            paramString += paramInfo[j].getName();
            if(j < paramInfo.length - 1) {
                paramString += ",";
            }
        }

        StringBuffer sb = new StringBuffer();
        sb.append("<table width=\"760\" align=\"center\">\n" +
                "  <tr>\n" +
                "    <td width=\"180\" align=\"right\"><b>Operation Name: </b></td><td>")
                .append(operInfo.getName())
                .append("</td>\n" +
                "  </tr>\n" +

                "  <tr>\n" +
                "    <td width=\"180\" align=\"right\"><b>Operation Description: </b></td><td>")
                .append(operInfo.getDescription())
                .append("</td>\n" +
                "  </tr>\n" +
                "  <tr>\n" +
                "    <td width=\"180\" align=\"right\"><b>Operation ReturnType: </b></td><td>")
                .append(operInfo.getReturnType())
                .append("</td>\n" +
                "  <tr>\n" +
                "    <td width=\"180\" align=\"right\"><b>Operation Signature: </b></td><td>")
                .append(paramString)
                .append("</td>\n" +
                "  </tr>\n" +
                "  <tr>\n" +
                "    <td width=\"180\" align=\"right\" valign=\"top\"><b>Operation Result: </b></td><td>")
                .append(dump(result))
                .append("</td>\n" +
                "  </tr>\n" +

                "  </tr>\n" +
                "\n" +
                "</table><br>\n" +
                "");
        return sb.toString();

    }

    private Object[] createObjects(String[] values, Class[] signatures) {
        Object[] objects = new Object[values.length];
        for(int i = 0; i < objects.length; i++) {
            Object obj = Classes.newObject(signatures[i], values[i]);
            objects[i] = obj;
        }
        return objects;
    }

    private static String dump(Object obj) {
        String result = "null";
        if(obj == null) return result;
        if(obj instanceof Exception) {
            result = dumpException((Exception) obj);
        }
        else if(obj.getClass().isArray()) {
            Object[] array = (Object[]) obj;
            result = dumpArray(array);
        }
        else if(obj instanceof List) {
            result = dump(((List) obj).toArray());
        }
        else if(obj instanceof Map) {
            result = dumpMap((Map) obj);
        }
        else {
            result = obj.toString();
        }
        return result;
    }

    private static String dumpException(Exception e) {
        CharArrayWriter caw = new CharArrayWriter();
        e.printStackTrace(new PrintWriter(caw));
        char[] charArray = caw.toCharArray();
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < charArray.length; i++) {
            if(charArray[i] == '\n') {
                sb.append("<br>");
            }
            else if(charArray[i] == ' ') {
                sb.append("&nbsp;");
            }
            else if(charArray[i] == '\t') {
                sb.append("&nbsp;&nbsp;&nbsp;&nbsp;");
            }
            else {
                sb.append(charArray[i]);
            }
        }
        return sb.toString();
    }

    private static String dumpArray(Object[] array) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < array.length; i++) {
            sb.append(array[i].toString()).append("<br>\n");
        }
        return sb.toString();
    }

    private static String dumpMap(Map map) {
        StringBuffer sb = new StringBuffer();
        for(Iterator it = map.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            sb.append(entry.getKey().toString())
                    .append(" => ")
                    .append(entry.getValue().toString())
                    .append("<br>\n");
        }
        return sb.toString();
    }

    private static String linkTable(String compName) {
        StringBuffer sb = new StringBuffer();
        sb.append("<table width=\"760\" align=\"center\">\n" +
                "  <tr>\n" +
                "    <td>")
                .append("<a href=\"?action=ViewComponent&compname=")
                .append(compName).append("\"> &lt;&lt;Return To Component View</a>")
                .append("</td>\n" +
                "  </tr>\n" +
                "</table>\n");
        return sb.toString();
    }

    public static void main(String[] args) {

    }
}

