/*
 * 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/PlatformTouchEvent.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::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);
    }
}

void WebView::handleTouchEvent(uint32_t touchId, int x, int y, TouchEventKind eventType)
{
#if ENABLE(TOUCH_EVENTS)
    auto& mainFrame = m_page->mainFrame();
    IntPoint touchPosition(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 == kTouchDown) {
        WebCore::PlatformTouchEvent mouseEvent(touchPosition, touchPosition,
            WebCore::MouseButton::LeftButton, PlatformEvent::MousePressed,
            1, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().handleMousePressEvent(mouseEvent);
    } else if (eventType == kTouchUp) {
        WebCore::PlatformTouchEvent mouseEvent(touchPosition, touchPosition,
            WebCore::MouseButton::LeftButton, PlatformEvent::MouseReleased,
            1, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().handleMouseReleaseEvent(mouseEvent);
    } else {
        WebCore::PlatformTouchEvent mouseEvent(touchPosition, touchPosition,
            WebCore::MouseButton::NoButton, PlatformEvent::MouseMoved,
            0, false, false, false, false, timeSinceEpoch, 0, SyntheticClickType::NoTap);
        mainFrame.eventHandler().mouseMoved(mouseEvent);
    }
#endif
}

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