#ifndef ZCPPWIN_WNDBASE_HPP
#define ZCPPWIN_WNDBASE_HPP
#include <Windows.h>


template<typename T>
class Wndbase {
public:
    Wndbase() = default;
    virtual ~Wndbase() = default;
    bool Init(HINSTANCE hinstance,
              PCWSTR titleName,
              int width = 1280,
              int height = 720,
              HWND parent = nullptr,
              DWORD dwStyle = WS_OVERLAPPEDWINDOW) {
        WNDCLASSEXW wc{};
        wc.lpszClassName = T::CLASSNAME();
        wc.hCursor = LoadCursor(nullptr,IDC_ARROW);
        wc.lpfnWndProc = StaticWndProc;
        wc.hInstance = hinstance;
        wc.cbSize = sizeof(WNDCLASSEXW);
        wc.style = 0;

        RECT rect{0, 0, width, height};
        AdjustWindowRect(&rect, dwStyle, false);

        RegisterClassExW(&wc);
        HWND hwnd = CreateWindowExW(0, T::CLASSNAME(), titleName, dwStyle,
                                    // CW_USEDEFAULT,CW_USEDEFAULT,
                                    0,0,
                                    rect.right, rect.bottom,
                                    parent, nullptr, hinstance,
                                    reinterpret_cast<LPVOID>(this));
        if (hwnd == nullptr) {
            MessageBoxW(nullptr, L"创建窗口失败", L"WndBase.cpp", 0);
            return false;
        }
        return true;
    }
    WPARAM Exec(int nCmdShow) {
        ShowWindow(m_hwnd, nCmdShow);
        if (EDGEMODE()) {
            return RunEdge();
        } else {
            return Run();
        }
    }
    static LRESULT WINAPI StaticWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
        T *p;
        if (msg == WM_NCCREATE) {
            auto *cp = reinterpret_cast<CREATESTRUCT *>(lparam);
            p = static_cast<T *>(cp->lpCreateParams);
            SetWindowLongPtr(hwnd,GWLP_USERDATA, reinterpret_cast<LONG_PTR>(p));
            p->m_hwnd = hwnd;
        } else {
            p = reinterpret_cast<T *>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
        }
        if (p) return p->WndProc(msg, wparam, lparam);
        return DefWindowProc(hwnd, msg, wparam, lparam);
    }
    virtual LRESULT WndProc(UINT msg, WPARAM wparam, LPARAM lparam) = 0;
public:
    HWND m_hwnd{};

protected:
    virtual bool EDGEMODE() =0;
    // virtual void UpdateWnd() {};

private:
    WPARAM RunEdge() {
        MSG msg{};
        for (;;) {
            while (PeekMessage(&msg, nullptr, 0, 0,PM_REMOVE)) {
                if (msg.message == WM_QUIT) {
                    return msg.wParam;
                }
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            static_cast<T *>(this)->UpdateWnd();
        }

    }

    static WPARAM Run() {
        MSG msg{};
        while (GetMessage(&msg, nullptr, 0, 0) > 0) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
};




















#endif
