//+--------------------------------------------------------------------------+
//|                                                                          |
//|                                 MINI                                     |
//|                                                                          |
//|               Example to create very small binary window                 |
//|                    using only the core SDK flat API                      |
//|             and the Tiny C Runtime library from Matt Pietrek.            |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                            www.objreader.com                             |
//|                           objreader@gmail.com                            |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 01-04-2001 (MM-DD-YYYY)            |
//|                        Last revised : 07-04-2024 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

#include <windows.h>

constexpr auto CLIENT_WIDTH   = 640;
constexpr auto CLIENT_HEIGHT  = 480;

struct PROP {
    HWND        hMain;
    long        minTrackSizeW;
    long        minTrackSizeH;
};

static PROP gP;

static long rWidth(IN RECT &r) {
    return r.right - r.left;
}

static long rHeight(IN RECT &r) {
    return r.bottom - r.top;
}

static LRESULT CALLBACK WndProc(IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) {
    LRESULT nRet = -1;
    MINMAXINFO* pMM;
    switch (uMsg) {
    case WM_CREATE:
        break;

    case WM_GETMINMAXINFO:
        pMM = (MINMAXINFO*)lParam;
        pMM->ptMinTrackSize.x = gP.minTrackSizeW;
        pMM->ptMinTrackSize.y = gP.minTrackSizeH;
        break;

    case WM_SIZE:
        InvalidateRect(hWnd, NULL, TRUE);
        nRet = 0;
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint(hWnd, &ps);
            // Paint the window content here
            EndPaint(hWnd, &ps);
            nRet = 0;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        nRet = 0;
        break;
    }

    if (nRet == -1) nRet = DefWindowProc(hWnd, uMsg, wParam, lParam);
    return nRet;
}

int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    int nRet = 0;
    WCHAR szClass[] = L"MINI";

    // Detect process without using a Mutex
    HWND hFound = FindWindow(szClass, NULL);
    if (hFound) {
        if (IsIconic(hFound)) { ShowWindow(hFound, SW_RESTORE); }
        SetForegroundWindow(hFound);
        return nRet;
    }

    WNDCLASSEX wcx = { 0 };
    wcx.cbSize = sizeof(wcx);
    long IsInitialized = GetClassInfoEx(hInstance, szClass, &wcx);
    if (!IsInitialized) {
        wcx.style         = CS_HREDRAW | CS_VREDRAW;
        wcx.lpfnWndProc   = WndProc;
        wcx.cbClsExtra    = 0;
        wcx.cbWndExtra    = 0;
        wcx.hInstance     = hInstance;
        wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcx.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
        wcx.lpszMenuName  = 0;
        wcx.lpszClassName = szClass;
        wcx.hIconSm       = wcx.hIcon;
        if (RegisterClassEx(&wcx)) { IsInitialized = -1; }
    }

    if (IsInitialized) {
        DWORD dwExStyle = 0;
        DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        RECT lpr = { 0 }; SetRect(&lpr, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT);
        AdjustWindowRectEx(&lpr, dwStyle, FALSE, dwExStyle);
        gP.minTrackSizeW = rWidth(lpr);
        gP.minTrackSizeH = rHeight(lpr);
        long x = max((GetSystemMetrics(SM_CXSCREEN) - gP.minTrackSizeW) / 2, 0);
        long y = max((GetSystemMetrics(SM_CYSCREEN) - gP.minTrackSizeH) / 2, 0);

        gP.hMain = CreateWindowEx(dwExStyle, szClass, szClass, dwStyle, x, y, gP.minTrackSizeW, gP.minTrackSizeH, 0, 0, hInstance, NULL);
        if (gP.hMain) {

            ShowWindow(gP.hMain, nCmdShow);
            SetForegroundWindow(gP.hMain); // Slightly Higher Priority

            MSG msg = { 0 };
            while (GetMessage(&msg, NULL, 0, 0)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            nRet = (int) msg.wParam;
        }
        UnregisterClass(wcx.lpszClassName, hInstance);
    }
    return nRet;
}