package org.freehep.jaco.generator;
import java.io.*;
import org.freehep.jaco.rtti.*;

/**
 * @author Tony Johnson
 * @version $Id: JNIStubImplementation.java,v 1.1.1.1 2004/05/31 05:08:51 kuromaru Exp $
 */

public class JNIStubImplementation extends JNIStub
{
    public JNIStubImplementation() {
        super();
    }

	public String filename(IClass clazz)
	{

        return getName(clazz)+".cpp";
    }
    public boolean print(PrintWriter out, IClass clazz)
	{
		this.out = out;

		warning();

		out.println("#include \"jaco.h\"");
		out.println("#include \""+getName(clazz)+".h\"");
		out.println("#include \""+clazz.getName()+".h\"");
		out.println();

		// Constructors first

		IConstructor[] constructors = clazz.getConstructors();
		for (int i=0; i<constructors.length; i++)
		{
			printConstructorHeader(constructors,i,true);
			out.println();
			out.println("{");
			out.print("   "+clazz.getName()+"* result = new "+clazz.getName()+"(");
			INamedType[] parameterTypes = constructors[i].getParameterTypes();
			for (int j=0; j<parameterTypes.length; j++)
			{
				if (j>0) out.print(", ");
				out.print("p"+j);
			}
			out.println(");");
			out.println("   return jaco->ProxyFor(result,env,\""+clazz.getPackageName(packagePrefix).replace('.','/')+"/"+clazz.getName()+"Proxy\");");
			out.println("}");
		}

		// Other methods

		IMethod[] methods = clazz.getMethods();
        for (int i=0; i<methods.length; i++)
		{
            if (!methods[i].isStatic())
			{
				printMethodHeader(methods,i,true);
				out.println();
				out.println("{");
				// Unlike the .h file, here we need an implementation!
				// First convert the handle to a C++ object

				out.println("   "+clazz.getName()+"* cpp = ("+clazz.getName()+"*) jaco->ClassForHandle(handle);");
				// TODO: Any non-primitive arguments need conversion too.

				// What is the return type

				IType returnType = methods[i].getReturnType();
				if      (returnType.equals("void")) out.print("   ");
				else if (returnType.isPrimitive())  out.print("   return ");
				else out.print("   "+returnType+" result = ");

				// Now call the C++ method

				out.print("cpp->"+methods[i].getName()+"(");
				INamedType[] parameterTypes = methods[i].getParameterTypes();
				for (int j=0; j<parameterTypes.length; j++)
				{
					if (j>0) out.print(", ");
					out.print("p"+j);
				}
				out.println(");");

				// Convert the output back to a JavaProxy?
				if (!returnType.isPrimitive())
				{
					out.println("   return jaco->ProxyFor(result,env,\""+clazz.getPackageName(packagePrefix).replace('.','/')+"/"+returnType.getName()+"Proxy\");");
				}
				out.println("}");
			}
        }
		// Finally the CPPUtil methods

		out.println("JNIEXPORT void JNICALL Java_"+name+"_deleteNative");
		out.println("   (JNIEnv *env, jobject obj, jint handle)");
		out.println("{");
		out.println("   delete ("+clazz.getName()+"*) jaco->ClassForHandle(handle);");
		out.println("}");
		out.println("JNIEXPORT void JNICALL Java_"+name+"_releaseNative");
		out.println("   (JNIEnv *env, jobject obj, jint handle)");
		out.println("{");
		out.println("   jaco->FreeHandle(handle,env);");
		out.println("}");
		return false;
    }

}
