#include <QDebug.h>
#include <QString>
#include <windows.h>

#include "winSpy.h"

// 全局变量，保存钩子句柄
static HWINEVENTHOOK hook = NULL;

// 获取窗口标题的辅助函数
QString GetWindowTitle(HWND hwnd) {
    char title[256];
    if (GetWindowTextA(hwnd, title, sizeof(title))) {
        return QString(title);
    }
    return "Untitled";
}

// 获取窗口所属进程名的辅助函数
QString GetWindowProcessName(HWND hwnd) {
    DWORD processId;
    GetWindowThreadProcessId(hwnd, &processId);
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (hProcess) {
        char  processName[MAX_PATH];
        DWORD size = sizeof(processName);
        if (QueryFullProcessImageNameA(hProcess, 0, processName, &size)) {
            CloseHandle(hProcess);
            QString fullPath(processName);
            // 只返回可执行文件名称
            qsizetype lastSlash = fullPath.lastIndexOf("\\");
            if (lastSlash != -1) {
                return fullPath.mid(lastSlash + 1);
            }
            return fullPath;
        }
        CloseHandle(hProcess);
    }
    return "Unknown";
}

// 事件回调函数
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
                           DWORD dwmsEventTime) {

    // 确保事件对象是窗口且事件是前台窗口改变
    if (idObject != OBJID_WINDOW || idChild != CHILDID_SELF) {
        return;
    }

    if (event == EVENT_SYSTEM_FOREGROUND) {
        HWND foregroundWindow = GetForegroundWindow(); // 获取当前前景窗口
        if (foregroundWindow) {
            QString title       = GetWindowTitle(foregroundWindow);
            QString processName = GetWindowProcessName(foregroundWindow);
            // 记录信息，这里示例为输出到控制台
            qDebug() << "Foreground Window Changed:";
            qDebug() << "  Handle: " << foregroundWindow;
            qDebug() << "  Title: " << title;
            qDebug() << "  Process: " << processName;
            qDebug() << "----------------------------------------";
            // TODO: 处理窗口数据保存
        }
    }
}

void WinSpy::setHook() {
    if (hook) {
        qDebug() << "Already monitoring.";
        return;
    }
    // 设置事件钩子，监听前台窗口变化事件
    hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,                        // 最小事件值
                           EVENT_SYSTEM_FOREGROUND,                        // 最大事件值
                           NULL,                                           // 钩子函数所在的DLL句柄（NULL表示当前进程）
                           WinEventProc,                                   // 事件回调函数指针
                           0,                                              // 感兴趣的进程ID（0表示所有进程）
                           0,                                              // 感兴趣的线程ID（0表示所有线程）
                           WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS // 标志：上下文外，跳过自身进程事件
    );

    if (!hook) {
        qWarning() << "Failed to set win event hook!";
        return;
    }
    qDebug() << "Start monitoring foreground window changes";
    // // 消息循环是必须的，否则回调函数不会被调用
    // MSG msg;
    // while (GetMessage(&msg, NULL, 0, 0)) {
    //     TranslateMessage(&msg);
    //     DispatchMessage(&msg);
    // }
}

void WinSpy::freeHook() {
    // 程序退出前卸载钩子
    if (hook) {
        UnhookWinEvent(hook);
    }
}

WinSpy::WinSpy() { setHook(); }
WinSpy::~WinSpy() { freeHook(); }
