/*
 * Copyright (C) 2012 Intel Corporation. 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 "WorkQueueManager.h"

#include "PlatformWebView.h"
#include "StringFunctions.h"
#include "TestController.h"
#include "TestInvocation.h"
#include <WebKit/WKPage.h>
#include <WebKit/WKPagePrivate.h>
#include <WebKit/WKRetainPtr.h>
#include <stdio.h>
#include <wtf/text/CString.h>

namespace WTR {

static inline WKPageRef mainPage()
{
    return TestController::singleton().mainWebView()->page();
}

static inline bool goToItemAtIndex(int index)
{
    WKBackForwardListRef backForwardList = WKPageGetBackForwardList(mainPage());
    ASSERT(backForwardList);

    WKBackForwardListItemRef listItem = WKBackForwardListGetItemAtIndex(backForwardList, index);
    if (!listItem)
        return false;

    WKPageGoToBackForwardListItem(mainPage(), listItem);

    return true;
}

class WorkQueueItem {
public:
    enum Type {
        Loading,
        NonLoading
    };

    virtual ~WorkQueueItem() { }
    virtual Type invoke() const = 0;
};

template <WorkQueueItem::Type type>
class ScriptItem : public WorkQueueItem {
public:
    explicit ScriptItem(const String& script)
        : m_script(toWK(script))
    {
    }

    WorkQueueItem::Type invoke() const
    {
        WKPageEvaluateJavaScriptInMainFrame(mainPage(), m_script.get(), nullptr, nullptr);
        return type;
    }

    WKRetainPtr<WKStringRef> m_script;
};

class NavigationItem : public WorkQueueItem {
public:
    explicit NavigationItem(int index) : m_index(index) { }

    WorkQueueItem::Type invoke() const
    {
        return goToItemAtIndex(m_index) ? WorkQueueItem::Loading : WorkQueueItem::NonLoading;
    }

    unsigned m_index;
};

WorkQueueManager::WorkQueueManager()
    : m_processing(false)
{
}

WorkQueueManager::~WorkQueueManager()
{
}

void WorkQueueManager::clearWorkQueue()
{
    m_processing = false;
    m_workQueue.clear();
}

bool WorkQueueManager::processWorkQueue()
{
    m_processing = false;
    while (!m_processing && !m_workQueue.isEmpty()) {
        std::unique_ptr<WorkQueueItem> item(m_workQueue.takeFirst());
        m_processing = (item->invoke() == WorkQueueItem::Loading);
    }

    return !m_processing;
}

void WorkQueueManager::queueLoad(const String& relativeURL, const String& target, bool shouldOpenExternalURLs)
{
    class LoadItem : public WorkQueueItem {
    public:
        LoadItem(WKRetainPtr<WKURLRef>&& url, const String& target, bool shouldOpenExternalURLs)
            : m_url(WTFMove(url))
            , m_target(target)
            , m_shouldOpenExternalURLs(shouldOpenExternalURLs)
        {
        }

        WorkQueueItem::Type invoke() const
        {
            if (!m_target.isEmpty()) {
                // FIXME: Use target. Some layout tests cannot pass as they rely on this functionality.
                fprintf(stderr, "queueLoad for a specific target is not implemented.\n");
                return WorkQueueItem::NonLoading;
            }
            WKPageLoadURLWithShouldOpenExternalURLsPolicy(mainPage(), m_url.get(), m_shouldOpenExternalURLs);
            return WorkQueueItem::Loading;
        }

        WKRetainPtr<WKURLRef> m_url;
        String m_target;
        bool m_shouldOpenExternalURLs;
    };

    auto baseURL = adoptWK(WKFrameCopyURL(WKPageGetMainFrame(mainPage())));
    auto url = adoptWK(WKURLCreateWithBaseURL(baseURL.get(), relativeURL.utf8().data()));
    enqueue(new LoadItem(WTFMove(url), target, shouldOpenExternalURLs));
}

void WorkQueueManager::queueLoadHTMLString(const String& content, const String& baseURL, const String& unreachableURL)
{
    class LoadHTMLStringItem : public WorkQueueItem {
    public:
        LoadHTMLStringItem(const String& content, const String& baseURL, const String& unreachableURL)
            : m_content(toWK(content))
            , m_baseURL(adoptWK(WKURLCreateWithUTF8CString(baseURL.utf8().data())))
            , m_unreachableURL(adoptWK(WKURLCreateWithUTF8CString(unreachableURL.utf8().data())))
        {
        }

        WorkQueueItem::Type invoke() const
        {
            WKPageLoadAlternateHTMLString(mainPage(), m_content.get(), m_baseURL.get(), m_unreachableURL.get());
            return WorkQueueItem::Loading;
        }

        WKRetainPtr<WKStringRef> m_content;
        WKRetainPtr<WKURLRef> m_baseURL;
        WKRetainPtr<WKURLRef> m_unreachableURL;
    };

    enqueue(new LoadHTMLStringItem(content, baseURL, unreachableURL));
}

void WorkQueueManager::queueBackNavigation(unsigned howFarBackward)
{
    enqueue(new NavigationItem(-howFarBackward));
}

void WorkQueueManager::queueForwardNavigation(unsigned howFarForward)
{
    enqueue(new NavigationItem(howFarForward));
}

void WorkQueueManager::queueReload()
{
    class ReloadItem : public WorkQueueItem {
    public:
        WorkQueueItem::Type invoke() const
        {
            if (auto* currentInvocation = TestController::singleton().currentInvocation(); currentInvocation && currentInvocation->options().runInCrossOriginFrame())
                currentInvocation->loadTestInCrossOriginIframe();
            else
                WKPageReload(mainPage());
            return WorkQueueItem::Loading;
        }
    };

    enqueue(new ReloadItem());
}

void WorkQueueManager::queueLoadingScript(const String& script)
{
    enqueue(new ScriptItem<WorkQueueItem::Loading>(script));
}

void WorkQueueManager::queueNonLoadingScript(const String& script)
{
    enqueue(new ScriptItem<WorkQueueItem::NonLoading>(script));
}

void WorkQueueManager::enqueue(WorkQueueItem* item)
{
    ASSERT(item);
    if (m_processing) {
        fprintf(stderr, "Attempt to enqueue a work item while queue is being processed.\n");
        delete item;
        return;
    }

    m_workQueue.append(std::unique_ptr<WorkQueueItem>(item));
}

} // namespace WTR
