/*
 * 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/CustomEvent.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/FocusController.h>
#include <WebCore/FrameLoadRequest.h>
#include <WebCore/ScriptController.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 <runtime/JSCJSValue.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 <zircon/pixelformat.h>

using namespace std;
using namespace WebCore;

namespace {

class CustomEventListener : public WebCore::EventListener {
 public:
  CustomEventListener(CustomEventHandler handler, WebView *webView)
      : EventListener(CPPEventListenerType), handler_(handler), webView_(webView) {
  }
  ~CustomEventListener() { }
  virtual bool operator==(const EventListener& that) const {
    return (void*)this == (void*)&that;
  }
  virtual void handleEvent(WebCore::ScriptExecutionContext* s,
                           WebCore::Event* e) {
    if (e->eventInterface() == WebCore::CustomEventInterfaceType) {
        handler_();
    }
  }
  static Ref<CustomEventListener> create(CustomEventHandler handler, WebView *webView) {
    return adoptRef(*new CustomEventListener(handler, webView));
  }

 private:
  CustomEventHandler handler_;
  WebView* webView_;
};

}  // namespace

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

void WebView::setup_once() {
    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();
    });
}

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 ZX_PIXEL_FORMAT_RGB_565:
        format = CAIRO_FORMAT_RGB16_565;
        break;
    case ZX_PIXEL_FORMAT_RGB_x888:
        format = CAIRO_FORMAT_RGB24;
        break;
    case ZX_PIXEL_FORMAT_ARGB_8888:
        format = CAIRO_FORMAT_ARGB32;
        break;
    case ZX_PIXEL_FORMAT_MONO_8:
        format = CAIRO_FORMAT_A8;
        break;
    default:
        cout << "Unsupported pixel format " << pixelFormat << endl;
        return false;
    }

    if (m_cairoSurface) {
        cairo_surface_destroy(m_cairoSurface);
        m_cairoSurface = nullptr;
    }

    if (m_cairoContext) {
        cairo_destroy(m_cairoContext);
        m_cairoContext = nullptr;
    }

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

    m_pageWidth = targetWidth;
    m_pageHeight = targetHeight;

    if (m_page == nullptr) {
        IntSize targetSize(targetWidth, targetHeight);
        std::function<void(bool)> delegate = [=](bool focused) {
            this->dispatchInputFocusChange(focused);
        };

        PageConfiguration pageConfiguration(makeUniqueRef<WebKit::WebEditorClient>(delegate), 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::dispatchInputFocusChange(bool focused) {
  if (m_inputFocusDelegate) {
    m_inputFocusDelegate(focused);
  }
}

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

void WebView::setInputFocusDelegate(InputFocusDelegate delegate) {
  m_inputFocusDelegate = delegate;
}

void WebView::setDidFinishLoadDelegate(DidFinishLoadDelegate delegate) {
  m_didFinishLoadDelegate = delegate;
}

void WebView::dispatchDidFinishLoad() {
  if (m_didFinishLoadDelegate) {
    m_didFinishLoadDelegate();
  }
}

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

std::string WebView::getAllCookies(const std::string& urlString)
{
  URLParser parser(urlString.c_str());
  URL url(parser.result());

  WTF::String cookies = WebCore::cookieRequestHeaderFieldValue(
      NetworkStorageSession::defaultStorageSession(), URL(), url);

  return std::string(cookies.utf8().data());
}

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

std::string WebView::stringByEvaluatingJavaScriptFromString(
    const std::string& script) {
  auto& mainFrame = m_page->mainFrame();
  WTF::String scriptString(script.data(), script.size());
  JSC::JSValue result = mainFrame.script().executeScript(scriptString, true);

  if (!result) {
    return "";
  }

  JSC::ExecState* exec =
      mainFrame.script().globalObject(mainThreadNormalWorld())->globalExec();
  JSC::JSLockHolder lock(exec);
  WTF::String resultString = result.getString(exec);
  WTF::CString resultCString =
      resultString.utf8(WTF::ConversionMode::LenientConversion);
  return std::string(resultCString.data(), resultCString.length());
}

void WebView::addCustomEventHandler(const std::string& type,
                                    CustomEventHandler handler) {
  Document* document = m_page->mainFrame().document();
  if (document) {
    Ref<CustomEventListener> listener = CustomEventListener::create(handler, this);
    // The document takes ownership of the event listener.
    document->addEventListener( type.c_str(), WTFMove(listener), false);
  }
}
