/* Call back for V8 named properties.  This is the entry point for accessing
 * properties from js.  We handle the properties we know and let V8 handle
 * all other properties.
 */
Handle<Value> TiObject::_propGetter(Local<String> prop, const AccessorInfo& info)
{
    HandleScope handleScope;
    Handle<Object> result;
    TiObject* obj = getTiObjectFromJsObject(info.Holder());
    if (obj == NULL)
    {
        // Returns "empty". This will cause V8 to go back to default lookup.
        return result;
    }
    Handle<ObjectTemplate> global = getObjectTemplateFromJsObject(info.Holder());
    String::Utf8Value propName(prop);
    const char* propString = (const char*)(*propName);
    TiObject* propObject = obj->onLookupMember(propString);
    if (propObject == NULL)
    {
        // TODO: Fix the following block of commented out code. Currently it breaks
        // Titanium runtime.
        /*
        if(obj->canAddMembers())
        {
            // If we're allowed to add members, return an "empty" result
            // so V8 will handle it. V8 will set the value internally so
            // we can ignore non-Titanium objects.
            return result;
        }
        */
        return Handle<Value>();
    }
    Handle<Value> ret = propObject->getValue();
    if (!ret.IsEmpty())
    {
        return handleScope.Close(ret);
    }
    if ((propObject->hasMembers()) || (propObject->isFunction()))
    {
        result = global->NewInstance();
        propObject->setValue(result);
        setTiObjectToJsObject(result, propObject);
    }
    else
    {
        propObject->release();
        return handleScope.Close(propObject->getValue());
    }
    propObject->release();
    return handleScope.Close(result);
}
Handle<Value> TiTitaniumObject::_createBuffer(void* userContext, TiObject*, const Arguments& args)
{
    HandleScope handleScope;
    TiTitaniumObject* obj = (TiTitaniumObject*) userContext;
    Handle<ObjectTemplate> global = getObjectTemplateFromJsObject(args.Holder());
    Handle<Object> result = global->NewInstance();
    TiBufferObject* newBuffer = TiBufferObject::createBuffer(obj->objectFactory_);
    newBuffer->setValue(result);
    if ((args.Length() > 0) && (args[0]->IsObject()))
    {
        Local<Object> settingsObj = Local<Object>::Cast(args[0]);
        newBuffer->setParametersFromObject(newBuffer, settingsObj);
    }
    setTiObjectToJsObject(result, newBuffer);
    return handleScope.Close(result);
}
Handle<Value> TiNetwork::_createHTTPClient(void* userContext, TiObject* /*caller*/, const Arguments& args)
{
    HandleScope handleScope;
    TiNetwork* obj = (TiNetwork*) userContext;
    Handle<ObjectTemplate> global = getObjectTemplateFromJsObject(args.Holder());
    Handle<Object> result = global->NewInstance();
    TiHTTPClientObject* newHTTP = TiHTTPClientObject::createHTTPClient(obj->objectFactory_);
    newHTTP->setValue(result);
    if ((args.Length() > 0) && (args[0]->IsObject()))
    {
        Local<Object> settingsObj = Local<Object>::Cast(args[0]);
        newHTTP->setParametersFromObject(newHTTP, settingsObj);
    }
    setTiObjectToJsObject(result, newHTTP);
    return handleScope.Close(result);
}
Handle<Value> TiProxy::createProxy(TiProxy *proxy, void* userContext, const Arguments& args)
{
    
    TiProxy *module = static_cast<TiProxy*>(userContext);
    HandleScope handleScope;
    Handle<ObjectTemplate> global = getObjectTemplateFromJsObject(args.Holder());
    Handle<Object> result = global->NewInstance();

    proxy->setNativeObjectFactory(module->getNativeObjectFactory());
    proxy->initializeTiObject(NULL);
    proxy->setValue(result);
    proxy->setAttachedObject(module);
    if ((args.Length() > 0) && (args[0]->IsObject()))
    {
        Local<Object> settingsObj = Local<Object>::Cast(args[0]);
        proxy->setParametersFromObject(proxy, settingsObj);
    }
    setTiObjectToJsObject(result, proxy);
    return handleScope.Close(result);
}