/*
 * 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_1:
        format = CAIRO_FORMAT_A1;
        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);
        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::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);
  }
}
