jobjectArray JsArgToArrayConverter::ToJavaArray()
{
	if ((m_arr == nullptr) && (m_argsLen > 0))
	{
		m_arr = JavaObjectArrayCache::GetJavaObjectArray(m_argsLen);
	}

	if (m_argsLen > 0)
	{
		JEnv env;

		for (int i = 0; i < m_argsLen; i++)
		{
			env.SetObjectArrayElement(m_arr, i, m_argsAsObject[i]);
		}
	}

	return m_arr;
}
//delete the returned local reference after use
jobjectArray NativeScriptRuntime::GetMethodOverrides(JEnv& env, const Local<Object>& implementationObject)
{
	if (implementationObject.IsEmpty())
	{
		return JavaObjectArrayCache::GetJavaStringArray(0);
	}

	vector<jstring> methodNames;
	auto propNames = implementationObject->GetOwnPropertyNames();
	for (int i = 0; i < propNames->Length(); i++)
	{
		auto name = propNames->Get(i).As<String>();
		auto method = implementationObject->Get(name);

		bool methodFound = !method.IsEmpty() && method->IsFunction();

		if (methodFound)
		{
			String::Utf8Value stringValue(name);
			jstring value = env.NewStringUTF(*stringValue);
			methodNames.push_back(value);
		}
	}

	int methodCount = methodNames.size();

	jobjectArray methodOverrides = JavaObjectArrayCache::GetJavaStringArray(methodCount);
	for (int i = 0; i < methodCount; i++)
	{
		env.SetObjectArrayElement(methodOverrides, i, methodNames[i]);
	}

	for (int i = 0; i < methodCount; i++)
	{
		env.DeleteLocalRef(methodNames[i]);
	}

	return methodOverrides;
}
void ArrayElementAccessor::SetArrayElement(const Local<Object>& array, uint32_t index, const string& arraySignature, Local<Value>& value)
{
	JEnv env;

	Isolate* isolate = Isolate::GetCurrent();
	HandleScope handleScope(isolate);

	jweak arr = objectManager->GetJavaObjectByJsObject(array);

	const string elementSignature = arraySignature.substr(1);
	jboolean isCopy = false;

	if (elementSignature == "Z") //bool
	{
		jboolean boolElementValue = (jboolean) value->BooleanValue();
		jbooleanArray boolArr = reinterpret_cast<jbooleanArray>(arr);
		env.SetBooleanArrayRegion(boolArr, index, 1, &boolElementValue);
	}
	else if (elementSignature == "B") //byte
	{
		jbyte byteElementValue = (jbyte) value->Int32Value();
		jbyteArray byteArr = reinterpret_cast<jbyteArray>(arr);
		env.SetByteArrayRegion(byteArr, index, 1, &byteElementValue);
	}
	else if (elementSignature == "C") //char
	{
		String::Utf8Value utf8(value->ToString());
		JniLocalRef s(env.NewString((jchar*) *utf8, 1));
		const char* singleChar = env.GetStringUTFChars(s, &isCopy);
		jchar charElementValue = *singleChar;
		env.ReleaseStringUTFChars(s, singleChar);
		jcharArray charArr = reinterpret_cast<jcharArray>(arr);
		env.SetCharArrayRegion(charArr, index, 1, &charElementValue);
	}
	else if (elementSignature == "S") //short
	{
		jshort shortElementValue = (jshort) value->Int32Value();
		jshortArray shortArr = reinterpret_cast<jshortArray>(arr);
		env.SetShortArrayRegion(shortArr, index, 1, &shortElementValue);
	}
	else if (elementSignature == "I") //int
	{
		jint intElementValue = value->Int32Value();
		jintArray intArr = reinterpret_cast<jintArray>(arr);
		env.SetIntArrayRegion(intArr, index, 1, &intElementValue);
	}
	else if (elementSignature == "J") //long
	{
		jlong longElementValue;
		if (value->IsObject())
		{
			longElementValue = (jlong) ArgConverter::ConvertToJavaLong(value);
		}
		else
		{
			longElementValue = (jlong) value->IntegerValue();
		}
		jlongArray longArr = reinterpret_cast<jlongArray>(arr);
		env.SetLongArrayRegion(longArr, index, 1, &longElementValue);
	}
	else if (elementSignature == "F") //float
	{
		jfloat floatElementValue = (jfloat) value->NumberValue();
		jfloatArray floatArr = reinterpret_cast<jfloatArray>(arr);
		env.SetFloatArrayRegion(floatArr, index, 1, &floatElementValue);
	}
	else if (elementSignature == "D") //double
	{
		jdouble doubleElementValue = (jdouble) value->NumberValue();
		jdoubleArray doubleArr = reinterpret_cast<jdoubleArray>(arr);
		env.SetDoubleArrayRegion(doubleArr, index, 1, &doubleElementValue);
	}
	else //string or object
	{
		bool isReferenceType = value->IsObject() || value->IsString();
		if (isReferenceType)
		{
			auto object = value.As<Object>();

			JsArgToArrayConverter argConverter(value, false, (int)Type::Null);
			if (argConverter.IsValid())
			{
				jobjectArray objArr = reinterpret_cast<jobjectArray>(arr);
				jobject objectElementValue = argConverter.GetConvertedArg();
				env.SetObjectArrayElement(objArr, index, objectElementValue);
			}
			else
			{
				JsArgToArrayConverter::Error err = argConverter.GetError();
				throw NativeScriptException(string(err.msg));
			}
		}
		else
		{
			throw NativeScriptException(string("Cannot assign primitive value to array of objects."));
		}
	}
}