/*
 * 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 "JSBasics.h"
#include "UIScriptController.h"
#include <WebCore/FloatRect.h>

using namespace WTR;

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

UIScriptContext::UIScriptContext(UIScriptContextDelegate& delegate, UIScriptControllerFactory factory)
    : m_context(adopt(JSGlobalContextCreate(nullptr)))
    , m_delegate(delegate)
{
    m_controller = factory(*this);
    m_controller->makeWindowObject(m_context.get());
}

UIScriptContext::~UIScriptContext()
{
    m_controller->waitForOutstandingCallbacks();
}

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()) {
        requestUIScriptCompletion(createJSString(m_context.get(), result).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, std::initializer_list<JSValueRef> arguments)
{
    if (!decltype(m_callbacks)::isValidKey(callbackID))
        return;
    Task task = m_callbacks.take(callbackID);
    if (!task.callback)
        return;

    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()), arguments.size(), arguments.size() ? arguments.begin() : 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);

    auto currentScriptCallbackID = task.parentScriptCallbackID;
    m_currentScriptCallbackID = currentScriptCallbackID;

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

    m_currentScriptCallbackID = currentScriptCallbackID;

    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 char16_t*>(JSStringGetCharactersPtr(result)), JSStringGetLength(result) });
    if (result)
        JSStringRelease(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;
}

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

    setProperty(m_context.get(), object, "left", rect.x());
    setProperty(m_context.get(), object, "top", rect.y());
    setProperty(m_context.get(), object, "width", rect.width());
    setProperty(m_context.get(), object, "height", rect.height());
    
    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;
}

