/* Copyright Krzysztof Kowalczyk 2006-2007
   License: GPLv2 */

/* This is a preview support for perf-test for Windows */

#include <windows.h>
#include <cassert>

#include "SplashBitmap.h"

#define WIN_CLASS_NAME "PDFTEST_PDF_WIN"
#define COL_WINDOW_BG RGB(0xff, 0xff, 0xff)

static HWND gHwndSplash;
static HBRUSH gBrushBg;

static SplashBitmap *gBmpSplash;

int rect_dx(RECT *r)
{
    int dx = r->right - r->left;
    assert(dx >= 0);
    return dx;
}

int rect_dy(RECT *r)
{
    int dy = r->bottom - r->top;
    assert(dy >= 0);
    return dy;
}

static HBITMAP createDIBitmapCommon(SplashBitmap *bmp, HDC hdc)
{
    int bmpDx = bmp->getWidth();
    int bmpDy = bmp->getHeight();
    int bmpRowSize = bmp->getRowSize();

    BITMAPINFOHEADER bmih;
    bmih.biSize = sizeof(bmih);
    bmih.biHeight = -bmpDy;
    bmih.biWidth = bmpDx;
    bmih.biPlanes = 1;
    bmih.biBitCount = 24;
    bmih.biCompression = BI_RGB;
    bmih.biSizeImage = bmpDy * bmpRowSize;
    ;
    bmih.biXPelsPerMeter = bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = bmih.biClrImportant = 0;

    unsigned char *bmpData = bmp->getDataPtr();
    HBITMAP hbmp = ::CreateDIBitmap(hdc, &bmih, CBM_INIT, bmpData, (BITMAPINFO *)&bmih, DIB_RGB_COLORS);
    return hbmp;
}

static void stretchDIBitsCommon(SplashBitmap *bmp, HDC hdc, int leftMargin, int topMargin, int pageDx, int pageDy)
{
    int bmpDx = bmp->getWidth();
    int bmpDy = bmp->getHeight();
    int bmpRowSize = bmp->getRowSize();

    BITMAPINFOHEADER bmih;
    bmih.biSize = sizeof(bmih);
    bmih.biHeight = -bmpDy;
    bmih.biWidth = bmpDx;
    bmih.biPlanes = 1;
    // we could create this dibsection in monochrome
    // if the printer is monochrome, to reduce memory consumption
    // but splash is currently setup to return a full colour bitmap
    bmih.biBitCount = 24;
    bmih.biCompression = BI_RGB;
    bmih.biSizeImage = bmpDy * bmpRowSize;
    ;
    bmih.biXPelsPerMeter = bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = bmih.biClrImportant = 0;
    SplashColorPtr bmpData = bmp->getDataPtr();

    ::StretchDIBits(hdc,
                    // destination rectangle
                    -leftMargin, -topMargin, pageDx, pageDy,
                    // source rectangle
                    0, 0, bmpDx, bmpDy, bmpData, (BITMAPINFO *)&bmih, DIB_RGB_COLORS, SRCCOPY);
}

/* Set the client area size of the window 'hwnd' to 'dx'/'dy'. */
static void resizeClientArea(HWND hwnd, int x, int dx, int dy, int *dx_out)
{
    RECT rc;
    GetClientRect(hwnd, &rc);
    if ((rect_dx(&rc) == dx) && (rect_dy(&rc) == dy))
        return;

    RECT rw;
    GetWindowRect(hwnd, &rw);
    int win_dx = rect_dx(&rw) + (dx - rect_dx(&rc));
    int win_dy = rect_dy(&rw) + (dy - rect_dy(&rc));
    SetWindowPos(hwnd, NULL, x, 0, win_dx, win_dy, SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOZORDER);
    if (dx_out)
        *dx_out = win_dx;
}

static void resizeClientAreaToRenderedBitmap(HWND hwnd, SplashBitmap *bmp, int x, int *dxOut)
{
    int dx = bmp->getWidth();
    int dy = bmp->getHeight();
    resizeClientArea(hwnd, x, dx, dy, dxOut);
}

static void drawBitmap(HWND hwnd, SplashBitmap *bmp)
{
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hwnd, &ps);
    SetBkMode(hdc, TRANSPARENT);
    FillRect(hdc, &ps.rcPaint, gBrushBg);

    HBITMAP hbmp = createDIBitmapCommon(bmp, hdc);
    if (hbmp) {
        HDC bmpDC = CreateCompatibleDC(hdc);
        if (bmpDC) {
            SelectObject(bmpDC, hbmp);
            int xSrc = 0, ySrc = 0;
            int xDest = 0, yDest = 0;
            int bmpDx = bmp->getWidth();
            int bmpDy = bmp->getHeight();
            BitBlt(hdc, xDest, yDest, bmpDx, bmpDy, bmpDC, xSrc, ySrc, SRCCOPY);
            DeleteDC(bmpDC);
            bmpDC = NULL;
        }
        DeleteObject(hbmp);
        hbmp = NULL;
    }
    EndPaint(hwnd, &ps);
}

static void onPaint(HWND hwnd)
{
    if (hwnd == gHwndSplash) {
        if (gBmpSplash) {
            drawBitmap(hwnd, gBmpSplash);
        }
    }
}

static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    case WM_CREATE:
        // do nothing
        break;

    case WM_ERASEBKGND:
        return TRUE;

    case WM_PAINT:
        /* it might happen that we get WM_PAINT after destroying a window */
        onPaint(hwnd);
        break;

    case WM_DESTROY:
        /* WM_DESTROY might be sent as a result of File\Close, in which case CloseWindow() has already been called */
        break;

    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

static BOOL registerWinClass(void)
{
    WNDCLASSEX wcex;
    ATOM atom;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = NULL;
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = WIN_CLASS_NAME;
    wcex.hIconSm = NULL;

    atom = RegisterClassEx(&wcex);
    if (atom)
        return TRUE;
    return FALSE;
}

static bool initWinIfNecessary(void)
{
    if (gHwndSplash)
        return true;

    if (!registerWinClass())
        return false;

    gBrushBg = CreateSolidBrush(COL_WINDOW_BG);

    gHwndSplash = CreateWindow(WIN_CLASS_NAME, "Splash", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL);

    if (!gHwndSplash)
        return false;

    ShowWindow(gHwndSplash, SW_HIDE);
    return true;
}

static void pumpMessages(void)
{
    BOOL isMessage;
    MSG msg;

    for (;;) {
        isMessage = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        if (!isMessage)
            return;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

void PreviewBitmapInit(void)
{
    /* no need to do anything */
}

void PreviewBitmapDestroy(void)
{
    PostQuitMessage(0);
    pumpMessages();
    DeleteObject(gBrushBg);
}

static void UpdateWindows(void)
{
    if (gBmpSplash) {
        resizeClientAreaToRenderedBitmap(gHwndSplash, gBmpSplash, 0, NULL);
        ShowWindow(gHwndSplash, SW_SHOW);
        InvalidateRect(gHwndSplash, NULL, FALSE);
        UpdateWindow(gHwndSplash);
    } else {
        ShowWindow(gHwndSplash, SW_HIDE);
    }

    pumpMessages();
}

void PreviewBitmapSplash(SplashBitmap *bmpSplash)
{
    if (!initWinIfNecessary())
        return;

    gBmpSplash = bmpSplash;
    UpdateWindows();
}
