#include "antithread.h"
#include "../kill_process.h"
#include <windows.h>
#include <TlHelp32.h>
#include <thread>
#include <chrono>
#include <vector>
#include <atomic>

int antisuspendthread() {
    struct ThreadInfo {
        DWORD threadId;
        DWORD lastSuspendCount;
    };

    std::vector<ThreadInfo> threadStates;
    DWORD currentProcessId = GetCurrentProcessId();
    DWORD protectorThreadId = GetCurrentThreadId();

    while (true) {
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
        if (hSnapshot == INVALID_HANDLE_VALUE) {
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
            continue;
        }

        THREADENTRY32 te = { sizeof(te) };
        std::vector<DWORD> currentThreadIds;

        if (Thread32First(hSnapshot, &te)) {
            do {
                if (te.th32OwnerProcessID == currentProcessId &&
                    te.th32ThreadID != protectorThreadId) {

                    currentThreadIds.push_back(te.th32ThreadID);

                    HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
                        FALSE, te.th32ThreadID);
                    if (hThread) {
                        DWORD suspendCount = SuspendThread(hThread);
                        if (suspendCount != (DWORD)-1) {
                            ResumeThread(hThread);

                            bool found = false;
                            for (auto& threadInfo : threadStates) {
                                if (threadInfo.threadId == te.th32ThreadID) {
                                    found = true;

                                    if (suspendCount > 0) {
                                        blue_screen();
                                        exit(0);
                                    }

                                    threadInfo.lastSuspendCount = 0;
                                    break;
                                }
                            }

                            if (!found) {
                                threadStates.push_back({ te.th32ThreadID, 0 });
                            }
                        }

                        CloseHandle(hThread);
                    }
                }
            } while (Thread32Next(hSnapshot, &te));
        }

        CloseHandle(hSnapshot);

        threadStates.erase(
            std::remove_if(threadStates.begin(), threadStates.end(),
                [&currentThreadIds](const ThreadInfo& info) {
                    return std::find(currentThreadIds.begin(), currentThreadIds.end(),
                        info.threadId) == currentThreadIds.end();
                }),
            threadStates.end()
        );

        if (IsDebuggerPresent()) {
            blue_screen();
            exit(0);
        }

        BOOL debuggerPresent = FALSE;
        CheckRemoteDebuggerPresent(GetCurrentProcess(), &debuggerPresent);
        if (debuggerPresent) {
            blue_screen();
            exit(0);
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
}