/*
 * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2014 Igalia S.L.
 * Copyright (C) 2018 Sony Interactive Entertainment Inc.
 *
 * 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 "PlatformWebView.h"

#include <WebCore/HWndDC.h>
#include <cstdio>
#include <windows.h>
#include <wtf/RunLoop.h>
#include <wtf/win/GDIObject.h>

#if USE(CAIRO)
#include <cairo.h>
#endif

#if USE(SKIA)
IGNORE_CLANG_WARNINGS_BEGIN("cast-align")
#include <skia/core/SkColorSpace.h>
#include <skia/core/SkImage.h>
#include <skia/core/SkPixmap.h>
IGNORE_CLANG_WARNINGS_END
#endif

namespace WTR {

static LPCWSTR hostWindowClassName = L"WTRWebViewHostWindow";
static LPCWSTR testRunnerWindowName = L"WebKitTestRunner";

static void registerWindowClass()
{
    static bool initialized = false;
    if (initialized)
        return;
    initialized = true;

    WNDCLASSEXW wndClass { };
    wndClass.cbSize = sizeof(wndClass);
    wndClass.style = CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = DefWindowProc;
    wndClass.hCursor = LoadCursor(0, IDC_ARROW);
    wndClass.hInstance = GetModuleHandle(0);
    wndClass.lpszClassName = hostWindowClassName;

    ::RegisterClassExW(&wndClass);
}

PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration, const TestOptions& options)
    : m_window(nullptr)
    , m_windowIsKey(true)
    , m_options(options)
{
    registerWindowClass();

    m_window = ::CreateWindowEx(
        WS_EX_TOOLWINDOW,
        hostWindowClassName,
        testRunnerWindowName,
        WS_POPUP,
        CW_USEDEFAULT,
        0,
        0,
        0,
        0,
        0,
        GetModuleHandle(0),
        0);
    RECT viewRect = { };
    m_view = WKViewCreate(viewRect, configuration, m_window);
    WKViewSetIsInWindow(m_view, true);
    WKViewSetUsesOffscreenRendering(m_view, true);

    ShowWindow(m_window, SW_SHOW);
}

PlatformWebView::~PlatformWebView()
{
    if (::IsWindow(m_window))
        ::DestroyWindow(m_window);
    WKRelease(m_view);
}

void PlatformWebView::resizeTo(unsigned width, unsigned height, WebViewSizingMode)
{
    WKRect frame = { };
    frame.size.width = width;
    frame.size.height = height;
    setWindowFrame(frame);
}

WKPageRef PlatformWebView::page()
{
    return WKViewGetPage(m_view);
}

void PlatformWebView::focus()
{
    ::SetFocus(::WKViewGetWindow(m_view));
}

WKRect PlatformWebView::windowFrame()
{
    WKRect wkFrame { };
    RECT r;

    if (::GetWindowRect(m_window, &r)) {
        wkFrame.origin.x = r.left;
        wkFrame.origin.y = r.top;
        wkFrame.size.width = r.right - r.left;
        wkFrame.size.height = r.bottom - r.top;
    }

    return wkFrame;
}

void PlatformWebView::setWindowFrame(WKRect frame, WebViewSizingMode)
{
    ::SetWindowPos(
        WKViewGetWindow(m_view),
        0,
        0,
        0,
        frame.size.width,
        frame.size.height,
        SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);

    UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS;
    if (m_options.shouldShowWindow())
        flags |= SWP_NOMOVE;
    ::SetWindowPos(
        m_window,
        0,
        -frame.size.width,
        -frame.size.height,
        frame.size.width,
        frame.size.height,
        flags);
}

void PlatformWebView::didInitializeClients()
{
}

void PlatformWebView::addChromeInputField()
{
}

void PlatformWebView::removeChromeInputField()
{
}

void PlatformWebView::setTextInChromeInputField(const String&)
{
}

void PlatformWebView::selectChromeInputField()
{
}

String PlatformWebView::getSelectedTextInChromeInputField()
{
    return { };
}

void PlatformWebView::addToWindow()
{
}

void PlatformWebView::removeFromWindow()
{
}

void PlatformWebView::setWindowIsKey(bool windowIsKey)
{
    m_windowIsKey = windowIsKey;
}

void PlatformWebView::makeWebViewFirstResponder()
{
}

#if USE(CAIRO)
static cairo_surface_t* generateCairoSurfaceFromBitmap(BITMAP bitmapTag)
{
    cairo_surface_t* image = cairo_image_surface_create(
        CAIRO_FORMAT_ARGB32,
        bitmapTag.bmWidth,
        bitmapTag.bmHeight);

    unsigned char* src = (unsigned char*)bitmapTag.bmBits;
    int srcPitch = bitmapTag.bmWidthBytes;
    unsigned char* dst = cairo_image_surface_get_data(image);
    int dstPitch = cairo_image_surface_get_stride(image);

    for (int y = 0; y < bitmapTag.bmHeight; y++) {
        memcpy(dst, src, dstPitch);
        src += srcPitch;
        dst += dstPitch;
    }

    return image;
}
#elif USE(SKIA)
static SkImage* generateCairoSurfaceFromBitmap(BITMAP bitmapTag)
{
    auto imageInfo = SkImageInfo::MakeN32Premul(bitmapTag.bmWidth, bitmapTag.bmHeight, SkColorSpace::MakeSRGB());
    SkPixmap pixmap(imageInfo, bitmapTag.bmBits, bitmapTag.bmWidthBytes);
    return SkImages::RasterFromPixmapCopy(pixmap).release();
}
#endif

PlatformImage PlatformWebView::windowSnapshotImage()
{
    RECT windowRect;
    ::GetClientRect(m_window, &windowRect);
    LONG width = windowRect.right - windowRect.left;
    LONG height = windowRect.bottom - windowRect.top;

    WebCore::HWndDC windowDC(m_window);
    auto memoryDC = adoptGDIObject(::CreateCompatibleDC(windowDC));

    BITMAPINFO bitmapInfo { };
    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapInfo.bmiHeader.biWidth = width;
    bitmapInfo.bmiHeader.biHeight = -height;
    bitmapInfo.bmiHeader.biPlanes = 1;
    bitmapInfo.bmiHeader.biBitCount = 32;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
    bitmapInfo.bmiHeader.biSizeImage = width * height * 4;

    void* bitsPointer = 0;
    auto bitmap = adoptGDIObject(::CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, &bitsPointer, 0, 0));
    if (!bitmap)
        return nullptr;

    ::SelectObject(memoryDC.get(), bitmap.get());
    ::SendMessage(m_window, WM_PRINT, reinterpret_cast<WPARAM>(memoryDC.get()), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED);

    BITMAP bitmapTag { };
    GetObject(bitmap.get(), sizeof(bitmapTag), &bitmapTag);
    ASSERT(bitmapTag.bmBitsPixel == 32);

    return generateCairoSurfaceFromBitmap(bitmapTag);
}

void PlatformWebView::changeWindowScaleIfNeeded(float)
{
}

void PlatformWebView::setNavigationGesturesEnabled(bool)
{
}

void PlatformWebView::forceWindowFramesChanged()
{
}

bool PlatformWebView::drawsBackground() const
{
    return false;
}

void PlatformWebView::setDrawsBackground(bool)
{
}

void PlatformWebView::setEditable(bool)
{
}

bool PlatformWebView::isSecureEventInputEnabled() const
{
    return false;
}

} // namespace WTR
