/** Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*     * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*     * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "NPApi.h"

#include <webkit/glue/plugins/plugin_host.h>
#include <third_party/WebKit/WebKit/chromium/public/WebBindings.h>

#include <base/thread.h>
#include <base/waitable_event.h>

#include "API/WebView.h"
#include "WebView/WebViewProxy.h"

using namespace Awesomium;

namespace Awesomium {

bool WebBindings::construct(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant* result)
{
  return WebKit::WebBindings::construct(npp, npobj, args, argCount, result);
}

NPObject* WebBindings::createObject(NPP npp, NPClass* npClass)
{
  return WebKit::WebBindings::createObject(npp, npClass);
}

bool WebBindings::enumerate(NPP id, NPObject* obj, NPIdentifier** identifier, uint32_t* val)
{
  return WebKit::WebBindings::enumerate(id, obj, identifier, val);
}

bool WebBindings::evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result)
{
  return WebKit::WebBindings::evaluate(npp, npObject, npScript, result);
}

bool WebBindings::evaluateHelper(NPP npp, bool popups_allowed, NPObject* npobj, NPString* npscript, NPVariant* result)
{
  return WebKit::WebBindings::evaluateHelper(npp, popups_allowed, npobj, npscript, result);
}

NPIdentifier WebBindings::getIntIdentifier(int32_t number)
{
  return WebKit::WebBindings::getIntIdentifier(number);
}

bool WebBindings::getProperty(WebView* view, NPObject* obj, NPIdentifier propertyName, NPVariant *result)
{
  if (view == NULL)
    return false;

  base::WaitableEvent event_(true, false);    // manual reset to prevent potential deadlocks
	view->coreThread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(view->viewProxy, &WebViewProxy::getNPObjectProperty, obj, propertyName, result, &event_));
  event_.Wait();
  return true;
}

NPIdentifier WebBindings::getStringIdentifier(const NPUTF8* string)
{
  return WebKit::WebBindings::getStringIdentifier(string);
}

void WebBindings::getStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
{
  return WebKit::WebBindings::getStringIdentifiers(names, nameCount, identifiers);
}

bool WebBindings::hasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
{
  return WebKit::WebBindings::hasMethod(npp, npObject, methodName);
}

bool WebBindings::hasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
{
  return WebKit::WebBindings::hasProperty(npp, npObject, propertyName);
}

bool WebBindings::identifierIsString(NPIdentifier identifier)
{
  return WebKit::WebBindings::identifierIsString(identifier);
}

int32_t WebBindings::intFromIdentifier(NPIdentifier identifier)
{
  return WebKit::WebBindings::intFromIdentifier(identifier);
}

void WebBindings::initializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
{
  WebKit::WebBindings::initializeVariantWithStringCopy(variant, value);
}

bool WebBindings::invoke(WebView* view, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
  if (view == NULL)
    return false;

  base::WaitableEvent event_(true, false);    // manual reset to prevent potential deadlocks
	view->coreThread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(view->viewProxy, &WebViewProxy::invokeNPObject, npObject, methodName, arguments, argumentCount, result, &event_));
  event_.Wait();
  return true;
}

bool WebBindings::invokeDefault(WebView* view, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
  if (view == NULL)
    return false;

  base::WaitableEvent event_(true, false);    // manual reset to prevent potential deadlocks
	view->coreThread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(view->viewProxy, &WebViewProxy::invokeNPObjectDefault, npObject, arguments, argumentCount, result, &event_));
  event_.Wait();
  return true;
}

void WebBindings::releaseObject(NPObject* npObject)
{
  return WebKit::WebBindings::releaseObject(npObject);
}

void WebBindings::releaseVariantValue(NPVariant* variant)
{
  WebKit::WebBindings::releaseVariantValue(variant);
}

bool WebBindings::removeProperty(NPP id, NPObject* object, NPIdentifier identifier)
{
  return  WebKit::WebBindings::removeProperty(id, object, identifier);
}

NPObject* WebBindings::retainObject(NPObject* npObject)
{
  return WebKit::WebBindings::retainObject(npObject);
}

void WebBindings::setException(NPObject* obj, const NPUTF8* message)
{
  WebKit::WebBindings::setException(obj, message);
}

bool WebBindings::setProperty(NPP id, NPObject* obj, NPIdentifier identifier, const NPVariant* variant)
{
  return WebKit::WebBindings::setProperty(id, obj, identifier, variant);
}

void WebBindings::unregisterObject(NPObject* npObject)
{
  WebKit::WebBindings::unregisterObject(npObject);
}

NPUTF8* WebBindings::utf8FromIdentifier(NPIdentifier identifier)
{
  return WebKit::WebBindings::utf8FromIdentifier(identifier);
}

void* WebBindings::memAlloc(uint32 size)
{
  return NPAPI::PluginHost::Singleton()->host_functions()->memalloc(size);
}
  
void WebBindings::memFree(void* data)
{
  return NPAPI::PluginHost::Singleton()->host_functions()->memfree(data);
}
  
} // namespace Awesomium
