/*
 * Copyright (C) 2015 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "config.h"
#include "UIScriptContext.h"

#include "UIScriptController.h"
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSValueRef.h>
#include <WebCore/FloatRect.h>

using namespace WTR;

static inline bool isPersistentCallbackID(unsigned callbackID)
{
    return callbackID < firstNonPersistentCallbackID;
}

UIScriptContext::UIScriptContext(UIScriptContextDelegate& delegate)
    : m_context(adopt(JSGlobalContextCreate(nullptr)))
    , m_delegate(delegate)
{
    m_controller = UIScriptController::create(*this);

    JSObjectRef globalObject = JSContextGetGlobalObject(m_context.get());

    JSValueRef exception = nullptr;
    m_controller->makeWindowObject(m_context.get(), globalObject, &exception);
}

UIScriptContext::~UIScriptContext()
{
    m_controller->checkForOutstandingCallbacks();
    m_controller->contextDestroyed();
}

void UIScriptContext::runUIScript(const String& script, unsigned scriptCallbackID)
{
    m_currentScriptCallbackID = scriptCallbackID;

    auto stringRef = adopt(JSStringCreateWithUTF8CString(script.utf8().data()));

    JSValueRef exception = nullptr;
    JSValueRef result = JSEvaluateScript(m_context.get(), stringRef.get(), 0, 0, 1, &exception);
    
    if (!hasOutstandingAsyncTasks()) {
        JSValueRef stringifyException = nullptr;
        auto stringified = adopt(JSValueToStringCopy(m_context.get(), result, &stringifyException));
        requestUIScriptCompletion(stringified.get());
        tryToCompleteUIScriptForCurrentParentCallback();
    }
}

unsigned UIScriptContext::nextTaskCallbackID(CallbackType type)
{
    if (type == CallbackTypeNonPersistent)
        return ++m_nextTaskCallbackID + firstNonPersistentCallbackID;

    return type;
}

unsigned UIScriptContext::prepareForAsyncTask(JSValueRef callback, CallbackType type)
{
    unsigned callbackID = nextTaskCallbackID(type);
    
    JSValueProtect(m_context.get(), callback);
    Task task;
    task.parentScriptCallbackID = m_currentScriptCallbackID;
    task.callback = callback;

    ASSERT(!m_callbacks.contains(callbackID));
    m_callbacks.add(callbackID, task);
    
    return callbackID;
}

void UIScriptContext::asyncTaskComplete(unsigned callbackID)
{
    Task task = m_callbacks.take(callbackID);
    ASSERT(task.callback);

    JSValueRef exception = nullptr;
    JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception);

    m_currentScriptCallbackID = task.parentScriptCallbackID;

    exception = nullptr;
    JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception);
    JSValueUnprotect(m_context.get(), task.callback);
    
    tryToCompleteUIScriptForCurrentParentCallback();
    m_currentScriptCallbackID = 0;
}

unsigned UIScriptContext::registerCallback(JSValueRef taskCallback, CallbackType type)
{
    if (m_callbacks.contains(type))
        unregisterCallback(type);

    if (JSValueIsUndefined(m_context.get(), taskCallback))
        return 0;

    return prepareForAsyncTask(taskCallback, type);
}

void UIScriptContext::unregisterCallback(unsigned callbackID)
{
    Task task = m_callbacks.take(callbackID);
    ASSERT(task.callback);
    JSValueUnprotect(m_context.get(), task.callback);
}

JSValueRef UIScriptContext::callbackWithID(unsigned callbackID)
{
    Task task = m_callbacks.get(callbackID);
    return task.callback;
}

void UIScriptContext::fireCallback(unsigned callbackID)
{
    Task task = m_callbacks.get(callbackID);
    ASSERT(task.callback);

    JSValueRef exception = nullptr;
    JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception);

    m_currentScriptCallbackID = task.parentScriptCallbackID;

    exception = nullptr;
    JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception);
    
    tryToCompleteUIScriptForCurrentParentCallback();
    m_currentScriptCallbackID = 0;
}

void UIScriptContext::requestUIScriptCompletion(JSStringRef result)
{
    ASSERT(m_currentScriptCallbackID);
    if (currentParentCallbackIsPendingCompletion())
        return;

    // This request for the UI script to complete is not fulfilled until the last non-persistent task for the parent callback is finished.
    m_uiScriptResultsPendingCompletion.add(m_currentScriptCallbackID, result ? JSStringRetain(result) : nullptr);
}

void UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback()
{
    if (!currentParentCallbackIsPendingCompletion() || currentParentCallbackHasOutstandingAsyncTasks())
        return;

    JSStringRef result = m_uiScriptResultsPendingCompletion.take(m_currentScriptCallbackID);
    String scriptResult(reinterpret_cast<const UChar*>(JSStringGetCharactersPtr(result)), JSStringGetLength(result));

    m_delegate.uiScriptDidComplete(scriptResult, m_currentScriptCallbackID);
    
    // Unregister tasks associated with this callback
    m_callbacks.removeIf([&](auto& keyAndValue) {
        return keyAndValue.value.parentScriptCallbackID == m_currentScriptCallbackID;
    });
    
    m_currentScriptCallbackID = 0;
    if (result)
        JSStringRelease(result);
}

JSObjectRef UIScriptContext::objectFromRect(const WebCore::FloatRect& rect) const
{
    JSObjectRef object = JSObjectMake(m_context.get(), nullptr, nullptr);

    JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("left")).get(), JSValueMakeNumber(m_context.get(), rect.x()), kJSPropertyAttributeNone, nullptr);
    JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("top")).get(), JSValueMakeNumber(m_context.get(), rect.y()), kJSPropertyAttributeNone, nullptr);
    JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("width")).get(), JSValueMakeNumber(m_context.get(), rect.width()), kJSPropertyAttributeNone, nullptr);
    JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("height")).get(), JSValueMakeNumber(m_context.get(), rect.height()), kJSPropertyAttributeNone, nullptr);
    
    return object;
}

bool UIScriptContext::currentParentCallbackHasOutstandingAsyncTasks() const
{
    for (auto entry : m_callbacks) {
        unsigned callbackID = entry.key;
        Task task = entry.value;
        if (task.parentScriptCallbackID == m_currentScriptCallbackID && !isPersistentCallbackID(callbackID))
            return true;
    }

    return false;
}

