/*
 * Copyright 2016 The Fuchsia Authors. 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 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 HOLDERS 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 "WebView.h"

#include <WebCore/BackForwardController.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/FocusController.h>
#include <WebCore/FrameLoadRequest.h>
#include <WebCore/GraphicsContext.h>
#include <WebCore/IntSize.h>
#include <WebCore/LogInitialization.h>
#include <WebCore/MainFrame.h>
#include <WebCore/NetworkStorageSession.h>
#include <WebCore/Page.h>
#include <WebCore/PageConfiguration.h>
#include <WebCore/PlatformCookieJar.h>
#include <WebCore/PlatformKeyboardEvent.h>
#include <WebCore/ResourceRequest.h>
#include <WebCore/Settings.h>
#include <WebCore/URLParser.h>

#include <WebKit/fuchsia/WebCoreSupport/WebChromeClient.h>
#include <WebKit/fuchsia/WebCoreSupport/WebEditorClient.h>
#include <WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.h>
#include <WebKit/fuchsia/WebCoreSupport/WebPlatformStrategies.h>

#include <WebStorageNamespaceProvider.h>

#include <iomanip>
#include <iostream>
#include <sstream>

#include <hid/hid.h>
#include <hid/usages.h>
#include <magenta/pixelformat.h>

using namespace std;
using namespace WebCore;

WebView::~WebView()
{
    if (m_cairoSurface) {
        cairo_surface_destroy(m_cairoSurface);
    }
    if (m_cairoContext) {
        cairo_destroy(m_cairoContext);
    }
    delete m_frameLoaderClient;
    delete m_chromeClient;
    delete m_page;
}

bool WebView::setup(unsigned char* pixelBuffer, int pixelFormat, size_t targetWidth, size_t targetHeight, size_t rowbytes)
{
    cairo_format_t format = CAIRO_FORMAT_INVALID;
    switch (pixelFormat) {
    case MX_PIXEL_FORMAT_RGB_565:
        format = CAIRO_FORMAT_RGB16_565;
        break;
    case MX_PIXEL_FORMAT_RGB_x888:
        format = CAIRO_FORMAT_RGB24;
        break;
    case MX_PIXEL_FORMAT_ARGB_8888:
        format = CAIRO_FORMAT_ARGB32;
        break;
    case MX_PIXEL_FORMAT_MONO_1:
        format = CAIRO_FORMAT_A1;
        break;
    case MX_PIXEL_FORMAT_MONO_8:
        format = CAIRO_FORMAT_A8;
        break;
    default:
        cout << "Unsupported pixel format " << pixelFormat << endl;
        return false;
    }

    m_cairoSurface = cairo_image_surface_create_for_data(pixelBuffer,
        format,
        targetWidth,
        targetHeight,
        rowbytes);
    cairo_status_t cairoStatus = cairo_surface_status(m_cairoSurface);
    if (cairoStatus != CAIRO_STATUS_SUCCESS) {
        cout << "cairo_image_surface_create_for_data failed: " << cairo_status_to_string(cairoStatus) << endl;
        return false;
    }

    m_cairoContext = cairo_create(m_cairoSurface);

    static std::once_flag initializeOnceFlag;
    std::call_once(initializeOnceFlag, [] {
        setenv("WEBKIT_DEBUG", "", 1);
        setenv("CURL_COOKIE_JAR_PATH", "/data/web_view/cookies.dat", 1);
#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
        WebCore::initializeLogChannelsIfNecessary();
#endif
        WTF::initializeThreading();
        WTF::initializeMainThread();
        WTF::RunLoop::initializeMainRunLoop();
        WebPlatformStrategies::initializeIfNecessary();
    });

    m_pageWidth = targetWidth;
    m_pageHeight = targetHeight;

    if (m_page == nullptr) {
        IntSize targetSize(targetWidth, targetHeight);
        PageConfiguration pageConfiguration(makeUniqueRef<WebKit::WebEditorClient>(), SocketProvider::create());
        fillWithEmptyClients(pageConfiguration);
        m_frameLoaderClient = new WebFrameLoaderClient(targetSize, this);
        pageConfiguration.loaderClientForMainFrame = m_frameLoaderClient;
        pageConfiguration.storageNamespaceProvider = WebStorageNamespaceProvider::create("/data/web_view");
        m_chromeClient = new WebChromeClient(targetSize);
        pageConfiguration.chromeClient = m_chromeClient;

        m_page = new Page(WTFMove(pageConfiguration));
        Settings& settings = m_page->settings();
        settings.setScriptEnabled(true);
        settings.setLoadsImagesAutomatically(true);
        settings.setLocalStorageEnabled(true);

        m_page->setIsInWindow(true);
        m_page->setGroupName("fuchsia_group");
        auto& mainFrame = m_page->mainFrame();
        m_frameLoaderClient->setFrame(&mainFrame);

        mainFrame.tree().setName("fuchsia_group");
        mainFrame.init();
    } else {
        Frame* frame = m_frameLoaderClient->frame();
        FrameView* view = frame->view();
        IntRect newRect(0, 0, m_pageWidth, m_pageHeight);
        view->setFrameRect(newRect);
    }

    return true;
}

void WebView::setFileURL(const std::string& urlString)
{
    URL fileURL(URL::fileURLWithFileSystemPath(urlString.c_str()));
    setURLInternal(fileURL);
}

void WebView::setURL(const std::string& urlString)
{
    URLParser parser(urlString.c_str());
    URL url(parser.result());
    setURLInternal(url);
}

void WebView::setURLInternal(const WebCore::URL& url)
{
    ResourceRequest resourceRequest(url);

    auto& mainFrame = m_page->mainFrame();
    auto& loader = mainFrame.loader();
    FrameLoadRequest loadRequest(&mainFrame, resourceRequest, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
    m_frameLoaderClient->clearMainDocumentError();
    loader.load(loadRequest);
}

void WebView::reload()
{
    if (m_page) {
        m_page->mainFrame().loader().reload();
    }
}

void WebView::goBack()
{
    if (m_page) {
        m_page->backForward().goBack();
    }
}

void WebView::goForward()
{
    if (m_page) {
        m_page->backForward().goForward();
    }
}

void WebView::scrollDownOneLine()
{
    scrollInternal(ScrollDirection::ScrollDown, ScrollGranularity::ScrollByLine);
}

void WebView::scrollUpOneLine()
{
    scrollInternal(ScrollDirection::ScrollUp, ScrollGranularity::ScrollByLine);
}

void WebView::scrollLeftOneLine()
{
    scrollInternal(ScrollDirection::ScrollLeft, ScrollGranularity::ScrollByLine);
}

void WebView::scrollRightOneLine()
{
    scrollInternal(ScrollDirection::ScrollRight, ScrollGranularity::ScrollByLine);
}

void WebView::scrollPixels(int deltaX, int deltaY)
{
    Frame* frame = m_frameLoaderClient->frame();
    if (frame) {
        FrameView* view = frame->view();
        view->scrollBy(IntSize(deltaX, deltaY));
    }
}

void WebView::scrollInternal(uint8_t direction, uint8_t granularity)
{
    if (m_page) {
        Frame* frame = m_frameLoaderClient->frame();
        if (frame) {
            FrameView* view = frame->view();
            view->scroll((ScrollDirection)direction, (ScrollGranularity)granularity);
        }
    }
}

void WebView::layoutAndPaint()
{
    Frame* frame = m_frameLoaderClient->frame();
    if (frame) {
        GraphicsContext gc(m_cairoContext);
        FrameView* view = frame->view();
        view->updateLayoutAndStyleIfNeededRecursive();
        if (view->frame().contentRenderer()) {
            IntRect fullRect(0, 0, m_pageWidth, m_pageHeight);
            view->paint(gc, fullRect);
        }
        cairo_surface_flush(m_cairoSurface);
    }
}

void WebView::setFocused(bool focused)
{
    auto& mainFrame = m_page->mainFrame();
    m_page->focusController().setFocusedFrame(&mainFrame);
    m_page->focusController().setActive(focused);
    m_page->focusController().setFocused(focused);
}

void WebView::setVisible(bool visible)
{
    m_page->setIsVisible(visible);
}

void WebView::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
{
    auto& mainFrame = m_page->mainFrame();
    mainFrame.setPageAndTextZoomFactors(pageZoomFactor, textZoomFactor);
}

void WebView::handleMouseEvent(int x, int y, MouseEventKind eventType)
{
    auto& mainFrame = m_page->mainFrame();
    IntPoint mousePosition(x, y);
    auto now = std::chrono::steady_clock::now().time_since_epoch();
    auto timeSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
    if (eventType == kMouseDown) {
        WebCore::PlatformMouseEvent mouseEvent(mousePosition, mousePosition,
            WebCore::MouseButton::LeftButton, PlatformEvent::MousePressed,
            1, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().handleMousePressEvent(mouseEvent);
    } else if (eventType == kMouseUp) {
        WebCore::PlatformMouseEvent mouseEvent(mousePosition, mousePosition,
            WebCore::MouseButton::LeftButton, PlatformEvent::MouseReleased,
            1, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().handleMouseReleaseEvent(mouseEvent);
    } else {
        WebCore::PlatformMouseEvent mouseEvent(mousePosition, mousePosition,
            WebCore::MouseButton::NoButton, PlatformEvent::MouseMoved,
            0, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().mouseMoved(mouseEvent);
    }
}

bool WebView::handleKeyEvent(uint8_t keycode, uint8_t charValue, bool pressed, bool repeat)
{
    string identifier;

    if (keycode == HID_USAGE_KEY_LEFT_SHIFT || keycode == HID_USAGE_KEY_RIGHT_SHIFT) {
        fShift = pressed;
    } else if (keycode == HID_USAGE_KEY_LEFT_CTRL || keycode == HID_USAGE_KEY_RIGHT_CTRL) {
        fControl = pressed;
    }

    int rawModifiers = 0;
    if (fControl) {
        rawModifiers |= PlatformEvent::Modifiers::CtrlKey;
    }

    if (fShift) {
        rawModifiers |= PlatformEvent::Modifiers::ShiftKey;
    }

    if (charValue != 0) {
        ostringstream oss;
        oss << "U+" << hex << setw(4) << setfill('0') << (int)charValue;
        identifier = oss.str();
    } else if (keycode == HID_USAGE_KEY_BACKSPACE) {
        identifier = "U+0008";
        charValue = 9;
    } else if (keycode == HID_USAGE_KEY_TAB) {
        identifier = "U+0009";
        charValue = 8;
    }

    char charStr[2] = { static_cast<char>(charValue), 0 };

    auto now = std::chrono::steady_clock::now().time_since_epoch();
    auto timeSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
    WebCore::PlatformKeyboardEvent keyboardEvent(pressed ? WebCore::PlatformEvent::KeyDown : WebCore::PlatformEvent::KeyUp, charStr, charStr, identifier.c_str(),
        0, keycode, 0, repeat, false, false, (PlatformEvent::Modifiers)rawModifiers, timeSinceEpoch);
    auto& mainFrame = m_page->mainFrame();
    return mainFrame.eventHandler().keyEvent(keyboardEvent);
}


void WebView::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
  if (m_webRequestDelegate) {
    std::string url = request.url().string().utf8().data();
    std::string new_url = m_webRequestDelegate(url);

    if (url != new_url) {
      URLParser parser(new_url.c_str());
      URL url(parser.result());
      request.setURL(url);
    }
  }
}

void WebView::setWebRequestDelegate(WebRequestDelegate delegate) {
  m_webRequestDelegate = delegate;
}

void WebView::iterateEventLoop()
{
    RunLoop::iterate();
}

std::string WebView::getTitle()
{
    return m_frameLoaderClient->getTitle();
}

bool WebView::isMainFrameLoaded()
{
    auto& mainFrame = m_page->mainFrame();
    return !mainFrame.loader().isLoading();
}

std::string WebView::getMainDocumentError() const
{
    return m_frameLoaderClient->getMainDocumentError();
}

void WebView::deleteAllCookies()
{
  WebCore::deleteAllCookies(NetworkStorageSession::defaultStorageSession());
}
