void CSFunctionWriter::WriteNativeFunction(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();
    String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();

    String returnType;
    String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);

    String line;

    line = ToString("ATOMIC_EXPORT_API %s %s\n",
                    returnType.CString(), functionSig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();


    source += "\n";

    bool returnValue = false;
    bool sharedPtrReturn = false;

    String returnStatement;

    if (returnType == "const char*")
    {
        returnValue = true;
        source += IndentLine("static String returnValue;\n");
        returnStatement = "returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
    {
        returnStatement = "*returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
    {
        returnStatement = ToString("SharedPtr<%s> returnValue = ", function_->GetReturnClass()->GetNativeName().CString());
        sharedPtrReturn = true;
    }
    else
    {
        if (returnType != "void")
        {
            returnStatement = "return ";
        }
    }

    String callSig;
    GenNativeCallParameters(callSig);
    if (!function_->isConstructor_)
    {
        if (function_->IsStatic())
        {
            line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
        }
        else
        {
            line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
        }

    }
    else
    {
        if (klass->IsAbstract())
        {
            line = "return 0; // Abstract Class\n";
        }
        else if (klass->IsObject())
        {
            if (callSig.Length())
                line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
            else
                line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
        }
        else
        {
            line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
        }
    }

    source += IndentLine(line);

    if (sharedPtrReturn)
    {
        source += IndentLine("returnValue->AddRef();\n");
        source += IndentLine("return returnValue;\n");
    }
    else if (returnType == "const char*")
    {
        source += IndentLine("return returnValue.CString();\n");
    }

    Dedent();

    source += IndentLine("}\n");

    source += "\n";

}
void CSFunctionWriter::WriteNativeFunction(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();
    String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();

    String returnType;
    String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);

    String line;

    line = ToString("ATOMIC_EXPORT_API %s %s\n",
                    returnType.CString(), functionSig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    source += "\n";

    // vector marshal

    bool hasVectorMarshal = false;
    const Vector<JSBFunctionType*>& fparams = function_->GetParameters();

    for (unsigned i = 0; i < fparams.Size(); i++)
    {
        JSBFunctionType* ftype = fparams[i];

        // Interface        
        JSBClass* interface = 0;
        if (ftype->type_->asClassType() && ftype->type_->asClassType()->class_->IsInterface())
        {
            // We need to downcast to the interface 
            // TODO: this assumes Object* is in hierarchy, how do we validate this?
            interface = ftype->type_->asClassType()->class_;
            line = ToString("%s = dynamic_cast<%s*>((Object*)%s);\n", ftype->name_.CString(), interface->GetNativeName().CString(), ftype->name_.CString());
            source += IndentLine(line);
        }

        // Vector
        JSBVectorType* vtype = ftype->type_->asVectorType();

        if (!vtype)
            continue;

        JSBClassType* classType = vtype->vectorType_->asClassType();

        if (!classType)
            continue;

        String className = classType->class_->GetName();

        String vectorMarshal;

        hasVectorMarshal = true;

        if (vtype->isPODVector_)
        {
            const String& pname = ftype->name_;
            source += IndentLine(ToString("PODVector<%s*> %s__vector;\n", className.CString(), pname.CString()));
            source += IndentLine(ToString("if (%s) %s->AdaptToVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
        }
        else
        {
            // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
        }

        if (vectorMarshal.Length())
        {
            source += IndentLine(vectorMarshal);
            vectorMarshal = String::EMPTY;
        }
    }


    bool returnValue = false;
    bool sharedPtrReturn = false;

    String returnStatement;

    if (returnType == "const char*")
    {
        returnValue = true;
        source += IndentLine("static String returnValue;\n");
        returnStatement = "returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
    {
        returnStatement = "*returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
    {
        returnStatement = ToString("SharedPtr<%s> returnValue = ", function_->GetReturnClass()->GetNativeName().CString());
        sharedPtrReturn = true;
    }
    else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
    {
        // we have an out parameter
        JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();

        if (!vtype->vectorTypeIsSharedPtr_ && !vtype->vectorTypeIsWeakPtr_)
        {
            returnStatement = ToString("%sVector<%s*> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorType_->asClassType()->class_->GetName().CString());
        }
        else
        {
            returnStatement = ToString("%sVector<%s<%s>> returnValue__vector = ",  vtype->isPODVector_ ? "POD" : "", vtype->vectorTypeIsSharedPtr_ ? "SharedPtr" : "WeakPtr", vtype->vectorType_->asClassType()->class_->GetName().CString());
        }
    }
    else
    {
        if (returnType != "void" && !hasVectorMarshal)
        {
            returnStatement = "return ";
        }
        else if (returnType != "void")
        {
            returnStatement = ToString("%s returnValue = ", returnType.CString());
        }
    }

    String callSig;
    GenNativeCallParameters(callSig);
    if (!function_->isConstructor_)
    {
        if (function_->IsStatic())
        {
            line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
        }
        else
        {
            line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
        }

    }
    else
    {
        if (klass->IsAbstract())
        {
            line = "return 0; // Abstract Class\n";
        }
        else if (klass->IsObject())
        {
            if (callSig.Length())
                line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
            else
                line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
        }
        else
        {
            line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
        }
    }

    source += IndentLine(line);

    // Vector marshaling

    for (unsigned i = 0; i < fparams.Size(); i++)
    {
        JSBFunctionType* ftype = fparams[i];

        JSBVectorType* vtype = ftype->type_->asVectorType();

        if (!vtype)
            continue;

        JSBClassType* classType = vtype->vectorType_->asClassType();

        if (!classType)
            continue;

        String className = classType->class_->GetName();

        String vectorMarshal;

        if (vtype->isPODVector_)
        {
            const String& pname = ftype->name_;
            source += IndentLine(ToString("if (%s) %s->AdaptFromVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
        }
        else
        {
            // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
        }

        if (vectorMarshal.Length())
        {
            source += IndentLine(vectorMarshal);
            vectorMarshal = String::EMPTY;
        }
    }


    if (sharedPtrReturn)
    {
        source += IndentLine("if (returnValue.NotNull()) returnValue->AddRef();\n");
        source += IndentLine("return returnValue;\n");
    }
    else if (returnType == "const char*")
    {
        source += IndentLine("return returnValue.CString();\n");
    }
    else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
    {
        // we have an out parameter
        JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
        source += IndentLine("if (returnValue) returnValue->AdaptFromVector(returnValue__vector);\n");

    }
    else if (returnType != "void" && hasVectorMarshal)
    {
        source += IndentLine("return returnValue;\n");
    }

    Dedent();

    source += IndentLine("}\n");

    source += "\n";

}