/*
 * 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->waitForOutstandingCallbacks();
    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;
}

