/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */
#include "common.h"
#include "BaseWnd.h"

//NOTE: it's not thread-safe
unsigned int BaseWnd::sm_classNameCounter = 0;

static LPCTSTR szBaseWndProp = TEXT("BaseWndProp");

BaseWnd::BaseWnd(HWND ancestor) :
    m_hWnd(NULL),
    m_ancestor(ancestor)
{

}

BaseWnd::~BaseWnd()
{

}

/*static*/
BaseWnd* BaseWnd::FromHandle(HWND hWnd)
{
    return (BaseWnd *)::GetProp(hWnd, szBaseWndProp);
}

HWND BaseWnd::Create(HWND hParent, int x, int y, int width, int height,
        LPCTSTR lpWindowName, DWORD dwExStyle, DWORD dwStyle, HBRUSH hbrBackground)
{
    HINSTANCE hInst = ::GetModuleHandle(NULL);
    TCHAR szClassName[256];

    ::ZeroMemory(szClassName, sizeof(szClassName));
    _stprintf_s(szClassName, sizeof(szClassName)/sizeof(szClassName[0]),
            _T("GlassWndClass-%s-%u"), GetWindowClassNameSuffix(), ++BaseWnd::sm_classNameCounter);

    WNDCLASSEX wndcls;
    wndcls.cbSize           = sizeof(WNDCLASSEX);
    wndcls.style            = CS_HREDRAW | CS_VREDRAW;
    wndcls.lpfnWndProc      = StaticWindowProc;
    wndcls.cbClsExtra       = 0;
    wndcls.cbWndExtra       = 0;
    wndcls.hInstance        = hInst;
    wndcls.hIcon            = NULL;
    wndcls.hCursor          = ::LoadCursor(NULL, IDC_ARROW);
    wndcls.hbrBackground    = hbrBackground;
    wndcls.lpszMenuName     = NULL;
    wndcls.lpszClassName    = szClassName;
    wndcls.hIconSm          = NULL;
    ::RegisterClassEx(&wndcls);

    if (lpWindowName == NULL) {
        lpWindowName = TEXT("");
    }
    ::CreateWindowEx(dwExStyle, szClassName, lpWindowName,
            dwStyle, x, y, width, height, hParent,
            NULL, hInst, (void *)this);

    if (GetHWND() == NULL) {
        _tprintf_s(L"BaseWnd::Create(%s) error: %u\n", szClassName, ::GetLastError());
    }

    return m_hWnd;

}

/*static*/
BOOL BaseWnd::GetDefaultWindowBounds(LPRECT r)
{
    HINSTANCE hInst = ::GetModuleHandle(NULL);
    TCHAR* szClassName = L"GLASSDEFAULTWINDOW";

    WNDCLASS wndcls;
    ::ZeroMemory(&wndcls, sizeof(WNDCLASS));
    wndcls.lpfnWndProc      = StaticWindowProc;
    wndcls.hInstance        = hInst;
    wndcls.lpszClassName    = szClassName;
    ::RegisterClass(&wndcls);

    HWND hwnd = ::CreateWindow(szClassName, L"", WS_OVERLAPPED,
                               CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                               0, 0, 0, 0);
    BOOL res = ::GetWindowRect(hwnd, r);
    ::DestroyWindow(hwnd);
    ::UnregisterClass(szClassName, hInst);

    return res;
}

/*static*/
LRESULT CALLBACK BaseWnd::StaticWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    BaseWnd *pThis = NULL;
    if (msg == WM_CREATE) {
        pThis = (BaseWnd *)((CREATESTRUCT *)lParam)->lpCreateParams;
        ::SetProp(hWnd, szBaseWndProp, (HANDLE)pThis);
        if (pThis != NULL) {
            pThis->m_hWnd = hWnd;
        }
    } else {
        pThis = (BaseWnd *)::GetProp(hWnd, szBaseWndProp);
    }
    if (pThis != NULL) {
        LRESULT result = pThis->WindowProc(msg, wParam, lParam);
        if (msg == WM_NCDESTROY) {
            ::RemoveProp(hWnd, szBaseWndProp);
            delete pThis;
        }
        return result;
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


