what is this for // MemoryScanner.cpp

#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <string>
#include <unordered_set>
#include <mutex>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <thread>
#include <functional>
#include <chrono>
#include <map>
#include <memory>
#include <atomic>
#include <future>
#include <regex>
#include <tchar.h>
#include <algorithm>
#include <float.h>
#include <lua.hpp>
#include <optional> // Added to fix std::optional errors

// DirectX and ImGui includes
#define IMGUI_ENABLE_DOCKING
#define IMGUI_ENABLE_VIEWPORTS
#include <d3d11.h>
#include <dxgi.h>
#include <wrl/client.h>  // For ComPtr
#include <imgui.h>
#include <imgui_impl_win32.h>
#include <imgui_impl_dx11.h>


// Lua integration
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

// JSON library for structured state persistence
#include <nlohmann/json.hpp>
using json = nlohmann::json;

// Intel XED for disassembly and DbgHelp for symbol management
#include "xed-interface.h"
#include <DbgHelp.h>
#include <wrl.h>
using Microsoft::WRL::ComPtr;

// Link necessary libraries
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "lua.lib")
#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "xed.lib") // Ensure XED library is linked

// Forward declarations for ImGui Win32 handler
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM);

// Forward declaration of WndProc
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Logger with verbosity levels for structured logging
enum LogLevel { LOG_INFO_LEVEL, LOG_WARNING, LOG_ERROR, LOG_DEBUG, LOG_LEVEL_COUNT };

class Logger {
public:
    Logger() {
        logFile.open("MemoryScanner.log", std::ios::out | std::ios::app);
        if (!logFile.is_open()) {
            MessageBoxA(NULL, "Failed to open log file.", "Logger Error", MB_ICONERROR);
        }
    }

    ~Logger() {
        if (logFile.is_open()) logFile.close();
    }

    // Delete copy constructor and assignment operator to prevent copying
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    void Log(LogLevel level, const std::string& message) {
        std::lock_guard<std::mutex> lock(logMutex);
        std::string logMessage = GetTimestamp() + " " + LogLevelToString(level) + " " + message + "\n";
        logBuffer += logMessage;

        if (logFile.is_open()) {
            logFile << logMessage;
            logFile.flush();
        }
    }

    std::string GetLogBuffer() const {
        std::lock_guard<std::mutex> lock(logMutex);
        return logBuffer;
    }

private:
    std::ofstream logFile;
    std::string logBuffer;
    mutable std::mutex logMutex;

    std::string GetTimestamp() const {
        auto now = std::chrono::system_clock::now();
        auto in_time_t = std::chrono::system_clock::to_time_t(now);
        std::tm buf;
        localtime_s(&buf, &in_time_t);
        std::stringstream ss;
        ss << "[" << std::put_time(&buf, "%Y-%m-%d %X") << "]";
        return ss.str();
    }

    std::string LogLevelToString(LogLevel level) const {
        switch (level) {
        case LOG_DEBUG: return "[DEBUG]";
        case LOG_INFO_LEVEL: return "[INFO]";
        case LOG_WARNING: return "[WARNING]";
        case LOG_ERROR: return "[ERROR]";
        default: return "[UNKNOWN]";
        }
    }
};

// RAII Wrapper for HANDLEs
struct HandleDeleter {
    void operator()(HANDLE h) const {
        if (h && h != INVALID_HANDLE_VALUE) {
            CloseHandle(h);
        }
    }
};

using UniqueHandle = std::unique_ptr<std::remove_pointer<HANDLE>::type, HandleDeleter>;

// Watchlist Manager with advanced functionality
class WatchlistManager {
public:
    // Adds a new watch entry with a timestamp
    bool AddWatchEntry(uintptr_t addr, int type, const std::string& value) {
        std::lock_guard<std::mutex> lock(watchMutex);
        // Check for duplicates
        if (FindWatchEntry(addr, type)) {
            logger.Log(LOG_WARNING, "Duplicate watch entry found: Address " + AddressToString(addr));
            return false;
        }
        watchEntries.emplace_back(addr, type, value, GetCurrentTimestamp());
        logger.Log(LOG_INFO_LEVEL, "Added watch entry at address " + AddressToString(addr));
        return true;
    }

    // Removes a watch entry by index and logs action
    bool RemoveWatchEntry(size_t index) {
        std::lock_guard<std::mutex> lock(watchMutex);
        if (index >= watchEntries.size()) {
            logger.Log(LOG_ERROR, "Invalid watch entry index: " + std::to_string(index));
            return false;
        }
        logger.Log(LOG_INFO_LEVEL, "Removed watch entry at index " + std::to_string(index));
        watchEntries.erase(watchEntries.begin() + index);
        return true;
    }

    // Clears all watch entries and logs action
    void ClearWatchlist() {
        std::lock_guard<std::mutex> lock(watchMutex);
        watchEntries.clear();
        logger.Log(LOG_INFO_LEVEL, "Cleared all watchlist entries.");
    }

    // Retrieves all watch entries
    std::vector<std::tuple<uintptr_t, int, std::string, std::string>> GetWatchEntries() const {
        std::lock_guard<std::mutex> lock(watchMutex);
        return watchEntries;
    }

    // Saves the current watchlist to a JSON file with error handling
    bool SaveWatchlist(const std::string& filename) {
        std::lock_guard<std::mutex> lock(watchMutex);
        json j;
        for (const auto& entry : watchEntries) {
            j["watchlist"].push_back({
                {"address", std::get<0>(entry)},
                {"type", std::get<1>(entry)},
                {"value", std::get<2>(entry)},
                {"timestamp", std::get<3>(entry)}
                });
        }
        std::ofstream file(filename);
        if (!file.is_open()) {
            logger.Log(LOG_ERROR, "Failed to open file for saving: " + filename);
            return false;
        }
        file << j.dump(4);
        logger.Log(LOG_INFO_LEVEL, "Saved watchlist to " + filename);
        return true;
    }

    // Loads the watchlist from a JSON file with detailed error handling
    bool LoadWatchlist(const std::string& filename) {
        std::lock_guard<std::mutex> lock(watchMutex);
        std::ifstream file(filename);
        if (!file.is_open()) {
            logger.Log(LOG_ERROR, "Failed to open file for loading: " + filename);
            return false;
        }
        json j;
        try {
            file >> j;
        }
        catch (const std::exception& e) {
            logger.Log(LOG_ERROR, "JSON parsing error in " + filename + ": " + e.what());
            return false;
        }

        watchEntries.clear();
        for (const auto& item : j["watchlist"]) {
            uintptr_t addr = item["address"].get<uintptr_t>();
            int type = item["type"].get<int>();
            std::string value = item["value"].get<std::string>();
            std::string timestamp = item["timestamp"].get<std::string>();
            watchEntries.emplace_back(addr, type, value, timestamp);
        }
        logger.Log(LOG_INFO_LEVEL, "Loaded watchlist from " + filename);
        return true;
    }

    // Finds a watch entry by address and type
    std::optional<std::tuple<uintptr_t, int, std::string, std::string>> FindWatchEntry(uintptr_t addr, int type) const {
        std::lock_guard<std::mutex> lock(watchMutex);
        auto it = std::find_if(watchEntries.begin(), watchEntries.end(), [&](const auto& entry) {
            return std::get<0>(entry) == addr && std::get<1>(entry) == type;
            });
        if (it != watchEntries.end()) return *it;
        return std::nullopt;
    }

    // Filters watch entries by type
    std::vector<std::tuple<uintptr_t, int, std::string, std::string>> FilterWatchEntriesByType(int type) const {
        std::lock_guard<std::mutex> lock(watchMutex);
        std::vector<std::tuple<uintptr_t, int, std::string, std::string>> filteredEntries;
        for (const auto& entry : watchEntries) {
            if (std::get<1>(entry) == type) {
                filteredEntries.push_back(entry);
            }
        }
        return filteredEntries;
    }

private:
    std::vector<std::tuple<uintptr_t, int, std::string, std::string>> watchEntries;
    mutable std::mutex watchMutex;
    mutable Logger logger; // Made mutable to allow logging in const methods

    // Helper to get current timestamp as a string
    std::string GetCurrentTimestamp() const {
        auto now = std::chrono::system_clock::now();
        auto in_time_t = std::chrono::system_clock::to_time_t(now);
        std::tm buf;
        localtime_s(&buf, &in_time_t);
        std::stringstream ss;
        ss << std::put_time(&buf, "%Y-%m-%d %X");
        return ss.str();
    }

    // Helper to convert address to string format
    std::string AddressToString(uintptr_t address) const {
        std::stringstream ss;
        ss << "0x" << std::hex << address;
        return ss.str();
    }
};

// Centralized State Management
struct AppState {
    // Process Information
    std::vector<std::string> processes;
    std::string selectedProcess = "";
    DWORD selectedPID = 0;
    UniqueHandle hProcess = nullptr;

    // Scanning Information
    int scanType = 0; // 0: Integer, 1: Float, 2: String
    char scanValue[256] = "";
    std::vector<std::tuple<uintptr_t, int, std::string, std::string>> watchlistEntries;
    std::vector<uintptr_t> memoryViewAddresses;
    uintptr_t viewAddress = 0x00000000;

    // Asynchronous Scanning
    std::future<std::vector<uintptr_t>> scanFuture;
    std::atomic<bool> cancelScan{ false };
    std::atomic<int> scanProgress{ 0 };

    // Previous Scan Data for Change Highlighting
    std::unordered_set<uintptr_t> previousScanResults;

    // Function Boundaries for Analysis
    uintptr_t functionStart = 0;
    uintptr_t functionEnd = 0;

    // Disassembly Results
    std::vector<std::string> disassemblyResults;

    // Cross-References for Functions and Memory
    std::map<uintptr_t, std::vector<uintptr_t>> crossReferences;

    // Pattern and Mask for Pattern Scanning
    std::vector<BYTE> pattern;
    std::string patternMask;

    // Function Signatures for Matching
    std::map<std::string, std::vector<BYTE>> functionSignatures;

    // Symbols and Hooks for Memory Management
    std::vector<std::pair<uintptr_t, std::string>> symbols;
    std::vector<std::tuple<uintptr_t, uintptr_t, uintptr_t>> hooks; // (target, detour, original)

    // Stack Tracing and Call Stack Information
    std::vector<std::pair<uintptr_t, std::string>> callStack;

    // Visualization Data (Flow Graph and Memory Sections)
    std::vector<std::string> flowGraph;
    std::map<std::string, std::pair<uintptr_t, size_t>> memorySections;

    // State Persistence
    json persistentState;

    // Watchlist Manager
    WatchlistManager watchlistManager;

    // Mutex for thread-safe operations
    mutable std::mutex stateMutex;
};

// MemoryScanner class with scan types and basic Read/Write functionality
class MemoryScanner {
public:
    // Made logger and hProcess public for accessibility
    UniqueHandle hProcess;
    Logger& logger;

    MemoryScanner(UniqueHandle hProcess, Logger& logger)
        : hProcess(std::move(hProcess)), logger(logger) {}

    // Delete copy constructor and assignment operator to prevent copying
    MemoryScanner(const MemoryScanner&) = delete;
    MemoryScanner& operator=(const MemoryScanner&) = delete;

    // Scan for integer values
    virtual std::vector<uintptr_t> ScanForInteger(int value, std::atomic<bool>& cancelFlag, std::atomic<int>& progress) {
        logger.Log(LOG_INFO_LEVEL, "Starting scan for integer value: " + std::to_string(value));
        std::vector<uintptr_t> results;
        MEMORY_BASIC_INFORMATION mbi;
        uintptr_t address = 0;
        SYSTEM_INFO sysInfo;
        GetSystemInfo(&sysInfo);
        uintptr_t maxAddress = (uintptr_t)sysInfo.lpMaximumApplicationAddress;

        while (address < maxAddress) {
            if (cancelFlag.load()) {
                logger.Log(LOG_INFO_LEVEL, "Scan for integer value canceled.");
                break;
            }

            SIZE_T bytes = VirtualQueryEx(hProcess.get(), (LPCVOID)address, &mbi, sizeof(mbi));
            if (bytes == 0) break;

            if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE)) {
                std::vector<int> buffer(mbi.RegionSize / sizeof(int));
                SIZE_T bytesRead;
                if (ReadProcessMemory(hProcess.get(), mbi.BaseAddress, buffer.data(), mbi.RegionSize, &bytesRead)) {
                    for (size_t i = 0; i < bytesRead / sizeof(int); ++i) {
                        if (buffer[i] == value) {
                            results.push_back((uintptr_t)mbi.BaseAddress + i * sizeof(int));
                        }
                    }
                }
            }

            address += mbi.RegionSize;
            progress.store((int)((double)address / maxAddress * 100));
        }

        logger.Log(LOG_INFO_LEVEL, "Completed scan for integer value. Results found: " + std::to_string(results.size()));
        return results;
    }

    // Virtual scan for float values to be overridden in derived class
    virtual std::vector<uintptr_t> ScanForFloat(float value, std::atomic<bool>& cancelFlag, std::atomic<int>& progress) {
        logger.Log(LOG_ERROR, "ScanForFloat not implemented in base MemoryScanner.");
        return {};
    }

    // Virtual method to get process base address to be overridden in derived class
    virtual uintptr_t GetProcessBaseAddress() const {
        logger.Log(LOG_ERROR, "GetProcessBaseAddress not implemented in base MemoryScanner.");
        return 0;
    }

    // Read memory
    bool ReadMemory(uintptr_t address, BYTE* buffer, size_t size) { // Removed const
        SIZE_T bytesRead;
        bool success = ReadProcessMemory(hProcess.get(), (LPCVOID)address, buffer, size, &bytesRead);
        if (!success || bytesRead != size) {
            logger.Log(LOG_ERROR, "Failed to read memory at address: " + AddressToString(address));
            return false;
        }
        return true;
    }

    // Write memory
    bool WriteMemory(uintptr_t address, const void* buffer, size_t size) {
        SIZE_T bytesWritten;
        bool success = WriteProcessMemory(hProcess.get(), (LPVOID)address, buffer, size, &bytesWritten);
        if (!success || bytesWritten != size) {
            logger.Log(LOG_ERROR, "Failed to write memory at address: " + AddressToString(address));
            return false;
        }
        return true;
    }

    // Convert address to string
    std::string AddressToString(uintptr_t address) const {
        std::stringstream ss;
        ss << "0x" << std::hex << address;
        return ss.str();
    }

    // Get handle for disassembler integration
    HANDLE GetProcessHandle() const {
        return hProcess.get();
    }
};

// Forward declaration of AdvancedMemoryScanner
class AdvancedMemoryScanner;

// Lua scripting integration with advanced functionality
class LuaScripting {
public:
    LuaScripting(MemoryScanner* scanner, Logger& logger)
        : scanner(scanner), logger(logger), L(nullptr) {}

    // Prevent copying to maintain single Lua state
    LuaScripting(const LuaScripting&) = delete;
    LuaScripting& operator=(const LuaScripting&) = delete;

    bool Initialize() {
        L = luaL_newstate();
        if (!L) {
            logger.Log(LOG_ERROR, "Failed to create Lua state.");
            return false;
        }
        luaL_openlibs(L);
        RegisterFunctions();
        logger.Log(LOG_INFO_LEVEL, "Lua state initialized and libraries loaded.");
        return true;
    }

    bool ExecuteScript(const std::string& script) {
        std::lock_guard<std::mutex> lock(luaMutex);
        if (L && luaL_dostring(L, script.c_str()) != LUA_OK) {
            const char* error = lua_tostring(L, -1);
            logger.Log(LOG_ERROR, "Lua execution error: " + std::string(error));
            lua_pop(L, 1);
            return false;
        }
        logger.Log(LOG_INFO_LEVEL, "Lua script executed successfully.");
        return true;
    }

    bool ExecuteScriptFromFile(const std::string& filename) {
        std::ifstream file(filename);
        if (!file.is_open()) {
            logger.Log(LOG_ERROR, "Failed to open Lua script file: " + filename);
            return false;
        }

        std::stringstream buffer;
        buffer << file.rdbuf();
        return ExecuteScript(buffer.str());
    }

    void RegisterFunctions() {
        // Register `MemoryScanner` functions and other Lua utilities
        lua_pushlightuserdata(L, scanner);
        lua_setglobal(L, "memory_scanner");

        lua_register(L, "ScanForInteger", Lua_ScanForInteger);
        lua_register(L, "ScanForFloat", Lua_ScanForFloat);
        lua_register(L, "GetProcessBaseAddress", Lua_GetProcessBaseAddress);

        logger.Log(LOG_INFO_LEVEL, "Lua functions registered.");
    }

    void Close() {
        std::lock_guard<std::mutex> lock(luaMutex);
        if (L) {
            lua_close(L);
            L = nullptr;
            logger.Log(LOG_INFO_LEVEL, "Lua state closed.");
        }
    }

private:
    lua_State* L;
    std::mutex luaMutex;
    MemoryScanner* scanner;
    Logger& logger;

    // Retrieve MemoryScanner instance from Lua
    static MemoryScanner* RetrieveScanner(lua_State* L) {
        lua_getglobal(L, "memory_scanner");
        auto scanner = static_cast<MemoryScanner*>(lua_touserdata(L, -1));
        lua_pop(L, 1);
        return scanner;
    }

    // Lua function for scanning integers
    static int Lua_ScanForInteger(lua_State* L) {
        // Get pointer to MemoryScanner from Lua registry
        lua_getglobal(L, "memory_scanner");
        MemoryScanner* scanner = static_cast<MemoryScanner*>(lua_touserdata(L, -1));
        lua_pop(L, 1);

        if (!scanner) {
            return luaL_error(L, "MemoryScanner instance is null.");
        }

        lua_Integer value = luaL_checkinteger(L, 1); // Changed to lua_Integer
        std::atomic<bool> cancelFlag{ false };
        std::atomic<int> progress{ 0 };
        std::future<std::vector<uintptr_t>> future = std::async(std::launch::async, &MemoryScanner::ScanForInteger, scanner, static_cast<int>(value), std::ref(cancelFlag), std::ref(progress));

        std::vector<uintptr_t> results = future.get();

        lua_newtable(L);
        for (size_t i = 0; i < results.size(); ++i) {
            lua_pushinteger(L, results[i]);
            lua_rawseti(L, -2, i + 1);
        }
        return 1;
    }
    // Lua function for scanning floats
    static int Lua_ScanForFloat(lua_State* L) {
        // Retrieve the pointer to MemoryScanner from the Lua registry
        lua_getglobal(L, "memory_scanner");
        MemoryScanner* scanner = static_cast<MemoryScanner*>(lua_touserdata(L, -1));
        lua_pop(L, 1);

        // Ensure the MemoryScanner instance is valid
        if (!scanner) {
            return luaL_error(L, "MemoryScanner instance is null.");
        }

        // Get the float value passed as an argument from Lua
        lua_Number value = luaL_checknumber(L, 1);
        std::atomic<bool> cancelFlag{ false };
        std::atomic<int> progress{ 0 };

        // Cast to AdvancedMemoryScanner to access specialized functions
        auto* advancedScanner = dynamic_cast<AdvancedMemoryScanner*>(scanner);
        if (!advancedScanner) {
            return luaL_error(L, "AdvancedMemoryScanner instance is required for ScanForFloat.");
        }

        try {
            // Run the ScanForFloat function asynchronously
            auto future = std::async(
                std::launch::async, &AdvancedMemoryScanner::ScanForFloat,
                advancedScanner, static_cast<float>(value), std::ref(cancelFlag), std::ref(progress)
            );

            // Retrieve results after completion of asynchronous operation
            std::vector<uintptr_t> results = future.get();

            // Create a new Lua table to store the scan results
            lua_newtable(L);
            for (size_t i = 0; i < results.size(); ++i) {
                lua_pushinteger(L, static_cast<lua_Integer>(results[i]));
                lua_rawseti(L, -2, static_cast<int>(i + 1));
            }
            return 1;

        }
        catch (const std::exception& e) {
            // Catch and report any exceptions from ScanForFloat
            return luaL_error(L, e.what());
        }
    }

    // Lua function to get the base address of the process
    static int Lua_GetProcessBaseAddress(lua_State* L) {
        // Retrieve the pointer to MemoryScanner from the Lua registry
        lua_getglobal(L, "memory_scanner");
        MemoryScanner* scanner = static_cast<MemoryScanner*>(lua_touserdata(L, -1));
        lua_pop(L, 1);

        // Validate the MemoryScanner instance
        if (!scanner) {
            return luaL_error(L, "MemoryScanner instance is null.");
        }

        // Get the base address of the process and push it to the Lua stack
        uintptr_t baseAddress = scanner->GetProcessBaseAddress();
        lua_pushinteger(L, baseAddress);
        return 1;
    }

// StackTracer for analyzing call stack and memory sections
class StackTracer {
public:
    StackTracer(HANDLE hProcess, Logger& logger)
        : hProcess(hProcess), logger(logger) {}

    // Memory sections enumeration
    enum SectionType { TEXT, DATA, RDATA, OTHER };

    // Get memory sections for tracing
    std::map<std::string, std::pair<uintptr_t, size_t>> GetMemorySections() const {
        std::map<std::string, std::pair<uintptr_t, size_t>> sections;
        MEMORY_BASIC_INFORMATION mbi;
        uintptr_t address = 0;
        SYSTEM_INFO sysInfo;
        GetSystemInfo(&sysInfo);
        uintptr_t maxAddress = (uintptr_t)sysInfo.lpMaximumApplicationAddress;

        while (address < maxAddress) {
            SIZE_T bytes = VirtualQueryEx(hProcess, (LPCVOID)address, &mbi, sizeof(mbi));
            if (bytes == 0) break;

            if (mbi.State == MEM_COMMIT) {
                std::string sectionName = "OTHER";
                if (mbi.Type == MEM_IMAGE) {
                    HMODULE hModule;
                    if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                        reinterpret_cast<LPCSTR>(mbi.BaseAddress), &hModule)) {
                        IMAGE_DOS_HEADER dosHeader;
                        ReadProcessMemory(hProcess, mbi.BaseAddress, &dosHeader, sizeof(dosHeader), NULL);
                        if (dosHeader.e_magic == IMAGE_DOS_SIGNATURE) {
                            IMAGE_NT_HEADERS64 ntHeaders;
                            ReadProcessMemory(hProcess, (LPVOID)((uintptr_t)mbi.BaseAddress + dosHeader.e_lfanew), &ntHeaders, sizeof(ntHeaders), NULL);
                            if (ntHeaders.Signature == IMAGE_NT_SIGNATURE) {
                                // Accessing SectionHeaders correctly
                                IMAGE_SECTION_HEADER section;
                                // The first section header is immediately after the IMAGE_NT_HEADERS64
                                ReadProcessMemory(hProcess, (LPVOID)((uintptr_t)mbi.BaseAddress + dosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS64)), &section, sizeof(section), NULL);
                                sectionName = std::string(reinterpret_cast<char*>(section.Name));
                            }
                        }
                    }
                }

                sections[sectionName] = { (uintptr_t)mbi.BaseAddress, mbi.RegionSize };
            }

            address += mbi.RegionSize;
        }

        return sections;
    }

private:
    HANDLE hProcess;
    Logger& logger;
};

// Advanced Memory Scanner with disassembly and pattern scanning
class AdvancedMemoryScanner : public MemoryScanner {
public:
    AdvancedMemoryScanner(UniqueHandle hProcess, Logger& logger)
        : MemoryScanner(std::move(hProcess), logger) {
        InitializeDisassembler();
    }

    ~AdvancedMemoryScanner() {
        // Removed xed_tables_shutdown(); as it's not part of Intel XED
    }

    // Override ScanForFloat
    virtual std::vector<uintptr_t> ScanForFloat(float value, std::atomic<bool>& cancelFlag, std::atomic<int>& progress) override {
        logger.Log(LOG_INFO_LEVEL, "Starting scan for float value: " + std::to_string(value));
        std::vector<uintptr_t> results;
        MEMORY_BASIC_INFORMATION mbi;
        uintptr_t address = 0;
        SYSTEM_INFO sysInfo;
        GetSystemInfo(&sysInfo);
        uintptr_t maxAddress = (uintptr_t)sysInfo.lpMaximumApplicationAddress;

        while (address < maxAddress) {
            if (cancelFlag.load()) {
                logger.Log(LOG_INFO_LEVEL, "Scan for float value canceled.");
                break;
            }

            SIZE_T bytes = VirtualQueryEx(hProcess.get(), (LPCVOID)address, &mbi, sizeof(mbi));
            if (bytes == 0) break;

            if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE)) {
                std::vector<float> buffer(mbi.RegionSize / sizeof(float));
                SIZE_T bytesRead;
                if (ReadProcessMemory(hProcess.get(), mbi.BaseAddress, buffer.data(), mbi.RegionSize, &bytesRead)) {
                    for (size_t i = 0; i < bytesRead / sizeof(float); ++i) {
                        if (buffer[i] == value) {
                            results.push_back((uintptr_t)mbi.BaseAddress + i * sizeof(float));
                        }
                    }
                }
            }

            address += mbi.RegionSize;
            progress.store((int)((double)address / maxAddress * 100));
        }

        logger.Log(LOG_INFO_LEVEL, "Completed scan for float value. Results found: " + std::to_string(results.size()));
        return results;
    }

    // Override GetProcessBaseAddress
    virtual uintptr_t GetProcessBaseAddress() const override {
        // Implement logic to retrieve process base address
        // Placeholder implementation
        MODULEENTRY32 me32;
        me32.dwSize = sizeof(MODULEENTRY32);
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
        if (hSnapshot == INVALID_HANDLE_VALUE) {
            logger.Log(LOG_ERROR, "Failed to create snapshot for GetProcessBaseAddress.");
            return 0;
        }

        if (Module32First(hSnapshot, &me32)) {
            CloseHandle(hSnapshot);
            return reinterpret_cast<uintptr_t>(me32.modBaseAddr);
        }
        else {
            logger.Log(LOG_ERROR, "Failed to get first module for GetProcessBaseAddress.");
            CloseHandle(hSnapshot);
            return 0;
        }
    }
    // Initialize XED disassembler
    void InitializeDisassembler() {
        xed_state_t state;
        xed_state_zero(&state);
        state.mmode = XED_MACHINE_MODE_LONG_64;
        state.stack_addr_width = XED_ADDRESS_WIDTH_64b;
        xed_tables_init();
        disas_state = state;
    }

    // Disassemble code at specific address
    std::string Disassemble(uintptr_t address) {
        BYTE buffer[16];
        if (!ReadMemory(address, buffer, sizeof(buffer))) {
            return "Failed to read memory.";
        }


        xed_decoded_inst_t xedd;
        xed_decoded_inst_zero_set_mode(&xedd, &disas_state);
        xed_error_enum_t xed_error = xed_decode(&xedd, buffer, sizeof(buffer));
        if (xed_error != XED_ERROR_NONE) {
            return "Disassembly error.";
        }

        char disasm_buf[256];
        xed_format_context(XED_SYNTAX_INTEL, &xedd, disasm_buf, sizeof(disasm_buf), (uint64_t)address, 0, 0);
        return std::string(disasm_buf);
    }

    // DisassembleAtAddress as per user request
    std::vector<std::string> DisassembleAtAddress(uintptr_t address, size_t length)  {
        std::vector<std::string> instructions;
        for (size_t offset = 0; offset < length; ) {
            BYTE buffer[16];
            // Remove the misplaced "const;" and fix syntax
            if (!ReadMemory(address + offset, buffer, sizeof(buffer))) {
                instructions.emplace_back("Failed to read memory at address: " + AddressToString(address + offset));
                break;
            }

            xed_decoded_inst_t xedd;
            xed_decoded_inst_zero_set_mode(&xedd, &disas_state);
            xed_error_enum_t xed_error = xed_decode(&xedd, buffer, sizeof(buffer));
            if (xed_error != XED_ERROR_NONE) {
                instructions.emplace_back("Disassembly error at address: " + AddressToString(address + offset));
                break;
            }

            char disasm_buf[256];
            xed_format_context(XED_SYNTAX_INTEL, &xedd, disasm_buf, sizeof(disasm_buf), (uint64_t)(address + offset), 0, 0);
            instructions.emplace_back(std::string(disasm_buf));

            offset += xed_decoded_inst_get_length(&xedd);
        }
        return instructions;
    }



    // Pattern scan using wildcards
    std::vector<uintptr_t> PatternScan(const std::vector<BYTE>& pattern, const std::string& mask, std::atomic<bool>& cancelFlag, std::atomic<int>& progress) const {
        logger.Log(LOG_INFO_LEVEL, "Starting pattern scan.");
        std::vector<uintptr_t> results;
        MEMORY_BASIC_INFORMATION mbi;
        uintptr_t address = 0;
        SYSTEM_INFO sysInfo;
        GetSystemInfo(&sysInfo);
        uintptr_t maxAddress = (uintptr_t)sysInfo.lpMaximumApplicationAddress;

        size_t patternLength = pattern.size();
        for (; address < maxAddress; ) {
            if (cancelFlag.load()) {
                logger.Log(LOG_INFO_LEVEL, "Pattern scan canceled.");
                break;
            }

            SIZE_T bytes = VirtualQueryEx(hProcess.get(), (LPCVOID)address, &mbi, sizeof(mbi));
            if (bytes == 0) break;

            if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_EXECUTE_READWRITE)) {
                std::vector<BYTE> buffer(mbi.RegionSize);
                SIZE_T bytesRead;
                if (ReadProcessMemory(hProcess.get(), mbi.BaseAddress, buffer.data(), mbi.RegionSize, &bytesRead)) {
                    for (size_t i = 0; i < bytesRead - patternLength; ++i) {
                        bool found = true;
                        for (size_t j = 0; j < patternLength; ++j) {
                            if (mask[j] == 'x' && buffer[i + j] != pattern[j]) {
                                found = false;
                                break;
                            }
                        }
                        if (found) {
                            results.push_back((uintptr_t)mbi.BaseAddress + i);
                        }
                    }
                }
            }

            address += mbi.RegionSize;
            progress.store((int)((double)address / maxAddress * 100));
        }

        logger.Log(LOG_INFO_LEVEL, "Completed pattern scan. Results found: " + std::to_string(results.size()));
        return results;
    }

    bool CreateHook(uintptr_t targetFunction, uintptr_t detourFunction, uintptr_t& originalFunction) {
        // Step 1: Calculate bytes needed to overwrite (at least 14 for x64 jump)
        const size_t hookSize = 14; // Using a 14-byte jump instruction for x64
        std::vector<BYTE> originalBytes(hookSize);

        // Backup original bytes from targetFunction
        if (!ReadProcessMemory(GetCurrentProcess(), (LPCVOID)targetFunction, originalBytes.data(), hookSize, NULL)) {
            logger.Log(LOG_ERROR, "Failed to read original bytes from target function.");
            return false;
        }

        // Step 2: Allocate executable memory for the shadow function (cloned original + jump back)
        originalFunction = (uintptr_t)VirtualAlloc(NULL, hookSize + 14, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!originalFunction) {
            logger.Log(LOG_ERROR, "Failed to allocate memory for shadow function.");
            return false;
        }

        // Step 3: Copy original bytes to the shadow function and add a jump back to the target
        memcpy((void*)originalFunction, originalBytes.data(), hookSize);
        uintptr_t returnAddress = targetFunction + hookSize;
        BYTE jmpBack[14] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // FF 25 is JMP [rip + disp32] on x64
        *reinterpret_cast<uintptr_t*>(jmpBack + 6) = returnAddress; // Set return address in jump

        memcpy((void*)(originalFunction + hookSize), jmpBack, 14);

        // Step 4: Write the hook to targetFunction with absolute JMP to detourFunction
        DWORD oldProtect;
        VirtualProtect((LPVOID)targetFunction, hookSize, PAGE_EXECUTE_READWRITE, &oldProtect);

        // Write the trampoline to detour function
        BYTE jmpDetour[14] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // JMP to detourFunction
        *reinterpret_cast<uintptr_t*>(jmpDetour + 6) = detourFunction; // Absolute address for x64

        memcpy((void*)targetFunction, jmpDetour, 14);
        VirtualProtect((LPVOID)targetFunction, hookSize, oldProtect, &oldProtect);

        // Flush CPU instruction cache to ensure the processor sees new instructions
        FlushInstructionCache(GetCurrentProcess(), (LPCVOID)targetFunction, hookSize);

        logger.Log(LOG_INFO_LEVEL, "Hook successfully created at address: " + AddressToString(targetFunction));
        return true;
    }

private:
    xed_state_t disas_state;
};

// Hook Manager for creating and removing hooks
class HookManager {
public:
    HookManager(Logger& logger) : logger(logger) {}

    bool CreateHook(uintptr_t targetFunction, uintptr_t detourFunction, uintptr_t& originalFunction) {
        // Placeholder: Implement hooking logic here
        logger.Log(LOG_INFO_LEVEL, "Creating hook at address: " + std::to_string(targetFunction));
        originalFunction = targetFunction; // Placeholder
        return true;
    }

    bool RemoveHook(uintptr_t targetFunction) {
        // Placeholder: Implement unhooking logic here
        logger.Log(LOG_INFO_LEVEL, "Removing hook at address: " + std::to_string(targetFunction));
        return true;
    }

private:
    Logger& logger;
};

// SymbolManager for resolving symbols
class SymbolManager {
public:
    SymbolManager(HANDLE hProcess, Logger& logger)
        : hProcess(hProcess), logger(logger) {
        SymInitialize(hProcess, NULL, TRUE);
    }

    ~SymbolManager() {
        SymCleanup(hProcess);
    }

    std::string ResolveSymbol(uintptr_t address) const {
        char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        pSymbol->MaxNameLen = MAX_SYM_NAME;

        DWORD64 displacement = 0;
        if (SymFromAddr(hProcess, (DWORD64)address, &displacement, pSymbol)) {
            return std::string(pSymbol->Name);
        }
        else {
            return "Unknown";
        }
    }

private:
    HANDLE hProcess;
    Logger& logger;
};

// LabelManager for managing labels and comments on specific addresses
struct LabelEntry {
    uintptr_t address;
    std::string label;
    std::string comment;
};

class LabelManager {
public:
    void AddLabel(uintptr_t addr, const std::string& label, const std::string& comment) {
        std::lock_guard<std::mutex> lock(labelMutex);
        labels.emplace_back(LabelEntry{ addr, label, comment });
    }

    void RemoveLabel(size_t index) {
        std::lock_guard<std::mutex> lock(labelMutex);
        if (index < labels.size()) {
            labels.erase(labels.begin() + index);
        }
    }

    void ClearLabels() {
        std::lock_guard<std::mutex> lock(labelMutex);
        labels.clear();
    }

    std::vector<LabelEntry> GetLabels() const {
        std::lock_guard<std::mutex> lock(labelMutex);
        return labels;
    }

    bool SaveLabels(const std::string& filename) const {
        std::lock_guard<std::mutex> lock(labelMutex);
        json j;
        for (const auto& label : labels) {
            j["labels"].push_back({
                {"address", label.address},
                {"label", label.label},
                {"comment", label.comment}
                });
        }
        std::ofstream file(filename);
        if (!file.is_open()) return false;
        file << j.dump(4);
        file.close();
        return true;
    }

    bool LoadLabels(const std::string& filename) {
        std::lock_guard<std::mutex> lock(labelMutex);
        std::ifstream file(filename);
        if (!file.is_open()) return false;
        json j;
        file >> j;
        file.close();

        labels.clear();
        for (const auto& item : j["labels"]) {
            uintptr_t addr = item["address"].get<uintptr_t>();
            std::string label = item["label"].get<std::string>();
            std::string comment = item["comment"].get<std::string>();
            labels.emplace_back(LabelEntry{ addr, label, comment });
        }
        return true;
    }

private:
    std::vector<LabelEntry> labels;
    mutable std::mutex labelMutex;
};

// Data Structure Analyzer for analyzing and recognizing data structures
class DataStructureAnalyzer {
public:
    DataStructureAnalyzer(Logger& logger)
        : logger(logger) {}

    // RTTI Parsing to identify data structures
    void ParseRTTI(uintptr_t address) {
        // Placeholder: Implement RTTI parsing logic here
        logger.Log(LOG_INFO_LEVEL, "Parsing RTTI at address: " + std::to_string(address));
    }

    // Recognize data structure by name at a specific address
    void RecognizeStructure(uintptr_t address, const std::string& structName) {
        // Placeholder: Recognize and validate structures in memory
        logger.Log(LOG_INFO_LEVEL, "Recognizing structure '" + structName + "' at address: " + std::to_string(address));
    }

private:
    Logger& logger;
};

// Visualization Tools for Flow Graph and Memory Map display
class VisualizationTools {
public:
    VisualizationTools(Logger& logger)
        : logger(logger) {}

    // Display a Flow Graph based on provided data
    void DisplayFlowGraph(const std::vector<std::string>& flowData) const {
        ImGui::Begin("Flow Graph");
        for (const auto& node : flowData) {
            ImGui::Text("%s", node.c_str());
        }
        ImGui::End();
    }

    // Display a Memory Map with section details
    void DisplayMemoryMap(const std::map<std::string, std::pair<uintptr_t, size_t>>& sections) const {
        ImGui::Begin("Memory Map Viewer");
        for (const auto& [name, info] : sections) {
            ImGui::Text("Section: %s | Base: 0x%016llX | Size: %zu bytes", name.c_str(), info.first, info.second);
        }
        ImGui::End();
    }

private:
    Logger& logger;
};

// ExportImportManager for session state handling
class ExportImportManager {
public:
    ExportImportManager(Logger& logger) : logger(logger) {}

    bool ExportSession(const std::string& filename, const AppState& state) const {
        json j;
        j["selectedProcess"] = state.selectedProcess;
        j["viewAddress"] = state.viewAddress;
        j["watchlist"] = state.watchlistManager.GetWatchEntries();

        std::ofstream file(filename);
        if (!file.is_open()) return false;
        file << j.dump(4);
        file.close();
        logger.Log(LOG_INFO_LEVEL, "Exported session to " + filename);
        return true;
    }

    bool ImportSession(const std::string& filename, AppState& state) const {
        std::lock_guard<std::mutex> lock(state.stateMutex);
        std::ifstream file(filename);
        if (!file.is_open()) return false;
        json j;
        file >> j;
        file.close();

        state.selectedProcess = j["selectedProcess"].get<std::string>();
        state.viewAddress = j["viewAddress"].get<uintptr_t>();
        state.watchlistManager.ClearWatchlist();
        for (const auto& entry : j["watchlist"]) {
            uintptr_t addr = entry["address"].get<uintptr_t>();
            int type = entry["type"].get<int>();
            std::string value = entry["value"].get<std::string>();
            state.watchlistManager.AddWatchEntry(addr, type, value);
        }

        logger.Log(LOG_INFO_LEVEL, "Imported session from " + filename);
        return true;
    }

private:
    Logger& logger;
};

// LuaPluginManager for handling Lua plugins
class LuaPluginManager {
public:
    LuaPluginManager(Logger& logger) : logger(logger) {}

    bool LoadPlugin(const std::string& scriptPath, LuaScripting& luaScripting) {
        std::ifstream scriptFile(scriptPath);
        if (!scriptFile.is_open()) {
            logger.Log(LOG_ERROR, "Failed to open Lua script: " + scriptPath);
            return false;
        }
        std::stringstream buffer;
        buffer << scriptFile.rdbuf();
        std::string script = buffer.str();
        luaScripting.ExecuteScript(script);
        logger.Log(LOG_INFO_LEVEL, "Loaded Lua plugin: " + scriptPath);
        return true;
    }

private:
    Logger& logger;
};

// Memory Viewer for displaying memory data and highlighting changes
class MemoryViewer {
public:
    MemoryViewer(MemoryScanner* scanner, WatchlistManager* watchlistManager, Logger& logger)
        : scanner(scanner), watchlistManager(watchlistManager), logger(logger) {}

    void DisplayMemoryView(uintptr_t address, const std::unordered_set<uintptr_t>& previousResults) const {
        BYTE buffer[256];
        bool readSuccess = scanner->ReadMemory(address, buffer, sizeof(buffer));
        if (readSuccess) {
            ImGui::BeginChild("MemoryContent", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
            for (int i = 0; i < 16; ++i) {
                uintptr_t addr = address + i * 16;
                ImGui::Text("0x%016llX: ", addr);
                ImGui::SameLine();
                for (int j = 0; j < 16; ++j) {
                    BYTE byte = buffer[i * 16 + j];
                    bool changed = previousResults.find(addr + j) != previousResults.end();

                    if (changed) {
                        ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
                    }
                    else {
                        ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 255));
                    }

                    ImGui::Text("%02X ", byte);
                    ImGui::PopStyleColor();
                }

                ImGui::SameLine(500);
                for (int j = 0; j < 16; ++j) {
                    BYTE byte = buffer[i * 16 + j];
                    if (byte >= 32 && byte <= 126) {
                        char c = static_cast<char>(byte);
                        ImGui::TextUnformatted(&c, &c + 1);
                    }
                    else {
                        ImGui::Text(".");
                    }
                }

                ImGui::NewLine();
            }
            ImGui::EndChild();
        }
        else {
            ImGui::TextColored(ImVec4(1, 0, 0, 1), "Failed to read memory at address: 0x%016llX", address);
        }
    }

private:
    MemoryScanner* scanner;
    WatchlistManager* watchlistManager;
    Logger& logger;
};

// Main Application Class
```cpp
class Application {
public:
    class AppRunner {
    public:
        bool Initialize() {
            logger.Log(LOG_INFO_LEVEL, "Initializing Application.");

            // Check for administrator privileges
            bool isAdmin = IsRunningAsAdministrator(logger);
            if (!isAdmin) {
                MessageBoxA(NULL, "This application requires administrator privileges to function correctly.", "Insufficient Privileges", MB_ICONWARNING | MB_OK);
            }

            // Initialize COM
            if (FAILED(CoInitialize(NULL))) {
                logger.Log(LOG_ERROR, "Failed to initialize COM.");
                return false;
            }

            // Initialize Lua Scripting
            luaScripting = std::make_unique<LuaScripting>(nullptr, logger); // Will assign scanner later
            if (!luaScripting->Initialize()) {
                logger.Log(LOG_ERROR, "Failed to initialize Lua scripting.");
                return false;
            }

            // Initialize StackTracer with a dummy handle for now
            // Later, this should be properly initialized after selecting a process
            stackTracer = std::make_unique<StackTracer>(nullptr, logger);

            return true;
        }

        void Run() {
            // Register and create the main application window
            WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
                              GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                              _T("MemoryScannerWindow"), NULL };
            RegisterClassEx(&wc);
            HWND hwnd = CreateWindow(wc.lpszClassName, _T("Memory Scanner"), WS_OVERLAPPEDWINDOW,
                100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);

            // Initialize Direct3D
            ComPtr<ID3D11Device> g_pd3dDevice;
            ComPtr<ID3D11DeviceContext> g_pd3dDeviceContext;
            ComPtr<IDXGISwapChain> g_pSwapChain;

            DXGI_SWAP_CHAIN_DESC sd = {};
            sd.BufferCount = 2;
            sd.BufferDesc.Width = 1280;
            sd.BufferDesc.Height = 800;
            sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            sd.BufferDesc.RefreshRate.Numerator = 60;
            sd.BufferDesc.RefreshRate.Denominator = 1;
            sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            sd.OutputWindow = hwnd;
            sd.SampleDesc.Count = 1;
            sd.Windowed = TRUE;

            HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE,
                NULL, 0, NULL, 0, D3D11_SDK_VERSION, &sd,
                &g_pSwapChain, &g_pd3dDevice, NULL, &g_pd3dDeviceContext);
            if (FAILED(hr)) {
                logger.Log(LOG_ERROR, "Failed to create D3D11 device and swap chain.");
                return;
            }

            // Create render target
            ComPtr<ID3D11Texture2D> pBackBuffer;
            g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
            ComPtr<ID3D11RenderTargetView> g_mainRenderTargetView;
            g_pd3dDevice->CreateRenderTargetView(pBackBuffer.Get(), NULL, &g_mainRenderTargetView);

            // Show the window
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            // Ensure ImGui version is correct
            IMGUI_CHECKVERSION();

            // Create ImGui context
            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO(); (void)io;

            // Enable keyboard navigation, docking, and viewports
            io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
            io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
            io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

            // Set custom black-red theme
            SetCustomTheme();

            // Initialize platform and renderer backends
            ImGui_ImplWin32_Init(hwnd);
            ImGui_ImplDX11_Init(g_pd3dDevice.Get(), g_pd3dDeviceContext.Get());

            // Load persistent state
            LoadPersistentState();

            // Initialize SymbolManager if process is selected
            if (state.hProcess) {
                symbolManager = std::make_unique<SymbolManager>(state.hProcess.get(), logger);
            }

            // Initialize MemoryScanner
            if (state.hProcess) {
                memoryScanner = std::make_unique<AdvancedMemoryScanner>(std::move(state.hProcess), logger);
                // Initialize LuaScripting with the scanner
                luaScripting->Close(); // Close previous state
                luaScripting = std::make_unique<LuaScripting>(memoryScanner.get(), logger);
                luaScripting->Initialize();
            }

            // Initialize StackTracer with the process handle
            if (memoryScanner && memoryScanner->GetProcessHandle()) {
                stackTracer = std::make_unique<StackTracer>(memoryScanner->GetProcessHandle(), logger);
            }

            // Main application loop
            bool done = false;
            while (!done) {
                MSG msg;
                while (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                    if (msg.message == WM_QUIT) done = true;
                }
                if (done) break;

                // Start the Dear ImGui frame
                ImGui_ImplDX11_NewFrame();
                ImGui_ImplWin32_NewFrame();
                ImGui::NewFrame();

                // Render Program Name with Shadow
                RenderProgramName();

                // Begin the main window
                ImGui::Begin("Memory Scanner Application");

                // Example UI elements with black-red theme
                if (ImGui::Button("Scan for Integer")) {
                    // Trigger scan
                    int value = 1234; // Example value
                    state.scanFuture = std::async(std::launch::async, &MemoryScanner::ScanForInteger, memoryScanner.get(), value, std::ref(state.cancelScan), std::ref(state.scanProgress));
                }

                ImGui::ProgressBar(state.scanProgress / 100.0f, ImVec2(0.0f, 0.0f), "Scanning...");

                // Display glitched terminal-style output
                DisplayGlitchedTerminal();

                // Example Watchlist Display
                DisplayWatchlist();

                ImGui::End();

                // Render additional windows with toggles
                RenderFunctionToggles();

                // Render Memory Viewer
                if (ImGui::Begin("Memory Viewer")) {
                    static uintptr_t memAddress = 0x00000000;
                    ImGui::InputScalar("Address", ImGuiDataType_U64, &memAddress, NULL, NULL, "%016llX");
                    if (ImGui::Button("View Memory")) {
                        state.viewAddress = memAddress;
                    }
                    memoryViewer.DisplayMemoryView(state.viewAddress, state.previousScanResults);
                    ImGui::End();
                }

                // Render Disassembly Window
                if (ImGui::Begin("Disassembly")) {
                    static uintptr_t disasmAddress = 0x00000000;
                    static size_t disasmLength = 64;
                    ImGui::InputScalar("Address", ImGuiDataType_U64, &disasmAddress, NULL, NULL, "%016llX");
                    ImGui::InputScalar("Length", ImGuiDataType_U64, &disasmLength, NULL, NULL, "%llu");
                    if (ImGui::Button("Disassemble")) {
                        if (memoryScanner) {
                            state.disassemblyResults = memoryScanner->DisassembleAtAddress(disasmAddress, disasmLength);
                        }
                    }

                    ImGui::BeginChild("DisassemblyContent", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
                    for (const auto& instr : state.disassemblyResults) {
                        ImGui::Text("%s", instr.c_str());
                    }
                    ImGui::EndChild();
                    ImGui::End();
                }

                // Render Program Logs Window
                if (ImGui::Begin("Program Logs")) {
                    std::string logs = logger.GetLogBuffer();
                    // Allocate a mutable buffer for ImGui
                    static char mutableLogs[65536] = ""; // Large enough buffer
                    strncpy_s(mutableLogs, logs.c_str(), sizeof(mutableLogs) - 1);
                    ImGui::InputTextMultiline("##logs", mutableLogs, sizeof(mutableLogs), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_ReadOnly);
                    ImGui::End();
                }

                // Render All Additional Windows Based on Toggles
                RenderAllAdditionalWindows();

                // Render Settings Window for Color Customization
                RenderSettingsWindow();

                // Render ImGui frame
                ImGui::Render();
                g_pd3dDeviceContext->OMSetRenderTargets(1, g_mainRenderTargetView.GetAddressOf(), NULL);
                const float clear_color_with_alpha[4] = { 0.1f, 0.0f, 0.0f, 1.0f }; // Dark red background
                g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView.Get(),

        bool Initialize() {
            logger.Log(LOG_INFO_LEVEL, "Initializing Application.");

            // Check for administrator privileges
            bool isAdmin = IsRunningAsAdministrator(logger);
            if (!isAdmin) {
                MessageBoxA(NULL, "This application requires administrator privileges to function correctly.", "Insufficient Privileges", MB_ICONWARNING | MB_OK);
            }

            // Initialize COM
            if (FAILED(CoInitialize(NULL))) {
                logger.Log(LOG_ERROR, "Failed to initialize COM.");
                return false;
            }

            // Initialize Lua Scripting
            luaScripting = std::make_unique<LuaScripting>(nullptr, logger); // Will assign scanner later
            if (!luaScripting->Initialize()) {
                logger.Log(LOG_ERROR, "Failed to initialize Lua scripting.");
                return false;
            }

            // Initialize StackTracer with a dummy handle for now
            // Later, this should be properly initialized after selecting a process
            stackTracer = std::make_unique<StackTracer>(nullptr, logger);

            return true;
        }

        void Run() {
            // Register and create the main application window
            WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
                              GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                              _T("MemoryScannerWindow"), NULL };
            RegisterClassEx(&wc);
            HWND hwnd = CreateWindow(wc.lpszClassName, _T("Memory Scanner"), WS_OVERLAPPEDWINDOW,
                100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);

            // Initialize Direct3D
            ComPtr<ID3D11Device> g_pd3dDevice;
            ComPtr<ID3D11DeviceContext> g_pd3dDeviceContext;
            ComPtr<IDXGISwapChain> g_pSwapChain;

            DXGI_SWAP_CHAIN_DESC sd = {};
            sd.BufferCount = 2;
            sd.BufferDesc.Width = 1280;
            sd.BufferDesc.Height = 800;
            sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            sd.BufferDesc.RefreshRate.Numerator = 60;
            sd.BufferDesc.RefreshRate.Denominator = 1;
            sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            sd.OutputWindow = hwnd;
            sd.SampleDesc.Count = 1;
            sd.Windowed = TRUE;

            HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE,
                NULL, 0, NULL, 0, D3D11_SDK_VERSION, &sd,
                &g_pSwapChain, &g_pd3dDevice, NULL, &g_pd3dDeviceContext);
            if (FAILED(hr)) {
                logger.Log(LOG_ERROR, "Failed to create D3D11 device and swap chain.");
                return;
            }

            // Create render target
            ComPtr<ID3D11Texture2D> pBackBuffer;
            g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
            ComPtr<ID3D11RenderTargetView> g_mainRenderTargetView;
            g_pd3dDevice->CreateRenderTargetView(pBackBuffer.Get(), NULL, &g_mainRenderTargetView);

            // Show the window
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            // Ensure ImGui version is correct
            IMGUI_CHECKVERSION();

            // Create ImGui context
            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO(); (void)io;

            // Enable keyboard navigation, docking, and viewports
            io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
            io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
            io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

            // Set custom black-red theme
            SetCustomTheme();

            // Initialize platform and renderer backends
            ImGui_ImplWin32_Init(hwnd);
            ImGui_ImplDX11_Init(g_pd3dDevice.Get(), g_pd3dDeviceContext.Get());

            // Load persistent state
            LoadPersistentState();

            // Initialize SymbolManager if process is selected
            if (state.hProcess) {
                symbolManager = std::make_unique<SymbolManager>(state.hProcess.get(), logger);
            }

            // Initialize MemoryScanner
            if (state.hProcess) {
                memoryScanner = std::make_unique<AdvancedMemoryScanner>(std::move(state.hProcess), logger);
                // Initialize LuaScripting with the scanner
                luaScripting->Close(); // Close previous state
                luaScripting = std::make_unique<LuaScripting>(memoryScanner.get(), logger);
                luaScripting->Initialize();
            }

            // Initialize StackTracer with the process handle
            if (memoryScanner && memoryScanner->GetProcessHandle()) {
                stackTracer = std::make_unique<StackTracer>(memoryScanner->GetProcessHandle(), logger);
            }

            class MemoryViewer {
            public:
                MemoryViewer(const MemoryViewer&) = delete;
                MemoryViewer& operator=(const MemoryViewer&) = delete;
                // Class content...
            };

            // Main application loop
            bool done = false;
            while (!done) {
                MSG msg;
                while (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                    if (msg.message == WM_QUIT) done = true;
                }
                if (done) break;

                // Start the Dear ImGui frame
                ImGui_ImplDX11_NewFrame();
                ImGui_ImplWin32_NewFrame();
                ImGui::NewFrame();

                // Render Program Name with Shadow
                RenderProgramName();

                // Begin the main window
                ImGui::Begin("Memory Scanner Application");

                // Example UI elements with black-red theme
                if (ImGui::Button("Scan for Integer")) {
                    // Trigger scan
                    int value = 1234; // Example value
                    state.scanFuture = std::async(std::launch::async, &MemoryScanner::ScanForInteger, memoryScanner.get(), value, std::ref(state.cancelScan), std::ref(state.scanProgress));
                }

                ImGui::ProgressBar(state.scanProgress / 100.0f, ImVec2(0.0f, 0.0f), "Scanning...");

                // Display glitched terminal-style output
                DisplayGlitchedTerminal();

                // Example Watchlist Display
                DisplayWatchlist();

                ImGui::End();

                // Render additional windows with toggles
                RenderFunctionToggles();

                // Render Memory Viewer
                if (ImGui::Begin("Memory Viewer")) {
                    static uintptr_t memAddress = 0x00000000;
                    ImGui::InputScalar("Address", ImGuiDataType_U64, &memAddress, NULL, NULL, "%016llX");
                    if (ImGui::Button("View Memory")) {
                        state.viewAddress = memAddress;
                    }
                    memoryViewer.DisplayMemoryView(state.viewAddress, state.previousScanResults);
                    ImGui::End();
                }

                // Render Disassembly Window
                if (ImGui::Begin("Disassembly")) {
                    static uintptr_t disasmAddress = 0x00000000;
                    static size_t disasmLength = 64;
                    ImGui::InputScalar("Address", ImGuiDataType_U64, &disasmAddress, NULL, NULL, "%016llX");
                    ImGui::InputScalar("Length", ImGuiDataType_U64, &disasmLength, NULL, NULL, "%llu");
                    if (ImGui::Button("Disassemble")) {
                        if (memoryScanner) {
                            state.disassemblyResults = memoryScanner->DisassembleAtAddress(disasmAddress, disasmLength);
                        }
                    }

                    ImGui::BeginChild("DisassemblyContent", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
                    for (const auto& instr : state.disassemblyResults) {
                        ImGui::Text("%s", instr.c_str());
                    }
                    ImGui::EndChild();
                    ImGui::End();
                }

                // Render Program Logs Window
                if (ImGui::Begin("Program Logs")) {
                    std::string logs = logger.GetLogBuffer();
                    // Allocate a mutable buffer for ImGui
                    static char mutableLogs[65536] = ""; // Large enough buffer
                    strncpy_s(mutableLogs, logs.c_str(), sizeof(mutableLogs) - 1);
                    ImGui::InputTextMultiline("##logs", mutableLogs, sizeof(mutableLogs), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_ReadOnly);
                    ImGui::End();
                }

                // Render All Additional Windows Based on Toggles
                RenderAllAdditionalWindows();

                // Render Settings Window for Color Customization
                RenderSettingsWindow();

                // Render ImGui frame
                ImGui::Render();
                g_pd3dDeviceContext->OMSetRenderTargets(1, g_mainRenderTargetView.GetAddressOf(), NULL);
                const float clear_color_with_alpha[4] = { 0.1f, 0.0f, 0.0f, 1.0f }; // Dark red background
                g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView.Get(), clear_color_with_alpha);
                ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

                if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
                    ImGui::UpdatePlatformWindows();
                    ImGui::RenderPlatformWindowsDefault();
                }

                g_pSwapChain->Present(1, 0); // Vsync enabled
            }

            // Save persistent state before exiting
            SavePersistentState();

            // Cleanup
            luaScripting->Close();
            ImGui_ImplDX11_Shutdown();
            ImGui_ImplWin32_Shutdown();
            ImGui::DestroyContext();

            g_pSwapChain.Reset();
            g_mainRenderTargetView.Reset();
            g_pd3dDeviceContext.Reset();
            g_pd3dDevice.Reset();

            DestroyWindow(hwnd);
            UnregisterClass(wc.lpszClassName, wc.hInstance);
            CoUninitialize();

            logger.Log(LOG_INFO_LEVEL, "Exiting MemoryScanner Application.");
        }

    private:
        Logger logger;
        AppState state;
        std::unique_ptr<LuaScripting> luaScripting;
        HookManager hookManager;
        std::unique_ptr<StackTracer> stackTracer;
        std::unique_ptr<SymbolManager> symbolManager;
        LabelManager labelManager;
        DataStructureAnalyzer dataStructureAnalyzer;
        VisualizationTools visualizationTools;
        ExportImportManager exportImportManager;
        LuaPluginManager luaPluginManager;
        std::unique_ptr<AdvancedMemoryScanner> memoryScanner;
        MemoryViewer memoryViewer;

        // Toggle flags for functions
        bool toggleDisassembleAtAddress = false;
        bool toggleFindFunctionBoundaries = false;
        bool toggleEnumerateCrossReferences = false;
        bool togglePatternScan = false;
        bool toggleCreateFunctionGraph = false;
        bool toggleTraceExecutionFlow = false;
        bool toggleGenerateStringTable = false;
        bool toggleMapMemorySections = false;
        bool toggleSymbolResolution = false;
        bool toggleCommentAddress = false;
        bool toggleStackFrameAnalysis = false;
        bool toggleShowTypeInfo = false;
        bool toggleHexViewWindow = false;

        // Set a custom black-red theme
        void SetCustomTheme() {
            ImGui::StyleColorsDark();
            ImGuiStyle& style = ImGui::GetStyle();
            ImVec4* colors = style.Colors;

            // Customize colors
            colors[ImGuiCol_WindowBg] = ImVec4(0.1f, 0.0f, 0.0f, 1.0f); // Dark red
            colors[ImGuiCol_TitleBg] = ImVec4(0.2f, 0.0f, 0.0f, 1.0f);
            colors[ImGuiCol_TitleBgActive] = ImVec4(0.3f, 0.0f, 0.0f, 1.0f);
            colors[ImGuiCol_Button] = ImVec4(0.8f, 0.1f, 0.1f, 1.0f);
            colors[ImGuiCol_ButtonHovered] = ImVec4(0.9f, 0.2f, 0.2f, 1.0f);
            colors[ImGuiCol_ButtonActive] = ImVec4(0.7f, 0.0f, 0.0f, 1.0f);
            colors[ImGuiCol_Text] = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Red text

            // Additional customization for glitched text can be implemented using shaders or special rendering techniques.
        }

        // Render Program Name with Shadow
        void RenderProgramName() const {
            ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiCond_Always);
            ImGui::SetNextWindowBgAlpha(0.0f); // Transparent background
            ImGui::Begin("ProgramName", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
                ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs);

            // Shadow
            ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 0.5f));
            ImGui::SetCursorPos(ImVec2(102, 102));
            ImGui::Text("Memory Scanner");
            ImGui::PopStyleColor();

            // Main text
            ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); // Red color
            ImGui::SetCursorPos(ImVec2(100, 100));
            ImGui::Text("Memory Scanner");
            ImGui::PopStyleColor();

            ImGui::End();
        }

        // Display glitched terminal-style output
        void DisplayGlitchedTerminal() const {
            static std::string terminalText = "Initializing...\n";
            static std::chrono::steady_clock::time_point lastUpdate = std::chrono::steady_clock::now();

            // Update terminal text periodically
            auto now = std::chrono::steady_clock::now();
            if (now - lastUpdate > std::chrono::milliseconds(500)) {
                terminalText += ">> ";
                terminalText += GenerateGlitchText("Welcome to Memory Scanner!\n");
                lastUpdate = now;
            }

            ImGui::BeginChild("Terminal", ImVec2(0, 200), true, ImGuiWindowFlags_HorizontalScrollbar);
            ImGui::TextWrapped("%s", terminalText.c_str());
            ImGui::EndChild();
        }

        // Function to generate glitched text
        std::string GenerateGlitchText(const std::string& text) const {
            std::string glitched = "";
            for (char c : text) {
                if (rand() % 5 == 0) { // 20% chance to glitch
                    glitched += static_cast<char>(c + (rand() % 3 - 1)); // Slight random shift
                }
                else {
                    glitched += c;
                }
            }
            return glitched;
        }

        // Display Watchlist
        void DisplayWatchlist() const {
            if (ImGui::BeginTabBar("WatchlistTabs")) {
                // Display existing watch entries
                if (ImGui::BeginTabItem("Watch Entries")) {
                    auto entries = state.watchlistManager.GetWatchEntries();
                    for (size_t i = 0; i < entries.size(); ++i) {
                        ImGui::Text("Address: 0x%016llX | Type: %d | Value: %s",
                            static_cast<unsigned long long>(std::get<0>(entries[i])),  // Cast for uintptr_t
                            std::get<1>(entries[i]),
                            std::get<2>(entries[i]).c_str());
                    }
                    ImGui::EndTabItem();
                }

                // Tab for adding new entries to the watchlist
                if (ImGui::BeginTabItem("Add Entry")) {
                    static uintptr_t addr = 0;
                    static int type = 0;
                    static char value[256] = "";

                    ImGui::InputScalar("Address", ImGuiDataType_U64, &addr, NULL, NULL, "%016llX");
                    ImGui::InputInt("Type", &type);
                    ImGui::InputText("Value", value, IM_ARRAYSIZE(value));

                    // Add the watch entry when button is clicked
                    if (ImGui::Button("Add Watch Entry")) {
                        state.watchlistManager.AddWatchEntry(addr, type, std::string(value));
                    }
                    ImGui::EndTabItem();
                }
                ImGui::EndTabBar();
            }
        }


        // Render toggles for various functions
        void RenderFunctionToggles() {
            if (ImGui::Begin("Function Toggles")) {
                // Toggle for DisassembleAtAddress
                ImGui::Checkbox("Enable DisassembleAtAddress", &toggleDisassembleAtAddress);
                if (toggleDisassembleAtAddress) {
                    // Enable related functionalities
                }

                // Toggle for FindFunctionBoundaries
                ImGui::Checkbox("Enable FindFunctionBoundaries", &toggleFindFunctionBoundaries);
                if (toggleFindFunctionBoundaries) {
                    // Enable related functionalities
                }

                // Toggle for EnumerateCrossReferences
                ImGui::Checkbox("Enable EnumerateCrossReferences", &toggleEnumerateCrossReferences);
                if (toggleEnumerateCrossReferences) {
                    // Enable related functionalities
                }

                // Toggle for PatternScan
                ImGui::Checkbox("Enable PatternScan", &togglePatternScan);
                if (togglePatternScan) {
                    // Enable related functionalities
                }

                // Toggle for CreateFunctionGraph
                ImGui::Checkbox("Enable CreateFunctionGraph", &toggleCreateFunctionGraph);
                if (toggleCreateFunctionGraph) {
                    // Enable related functionalities
                }

                // Toggle for TraceExecutionFlow
                ImGui::Checkbox("Enable TraceExecutionFlow", &toggleTraceExecutionFlow);
                if (toggleTraceExecutionFlow) {
                    // Enable related functionalities
                }

                // Toggle for GenerateStringTable
                ImGui::Checkbox("Enable GenerateStringTable", &toggleGenerateStringTable);
                if (toggleGenerateStringTable) {
                    // Enable related functionalities
                }

                // Toggle for MapMemorySections
                ImGui::Checkbox("Enable MapMemorySections", &toggleMapMemorySections);
                if (toggleMapMemorySections) {
                    // Enable related functionalities
                }

                // Toggle for SymbolResolution
                ImGui::Checkbox("Enable SymbolResolution", &toggleSymbolResolution);
                if (toggleSymbolResolution) {
                    // Enable related functionalities
                }

                // Toggle for CommentAddress
                ImGui::Checkbox("Enable CommentAddress", &toggleCommentAddress);
                if (toggleCommentAddress) {
                    // Enable related functionalities
                }

                // Toggle for StackFrameAnalysis
                ImGui::Checkbox("Enable StackFrameAnalysis", &toggleStackFrameAnalysis);
                if (toggleStackFrameAnalysis) {
                    // Enable related functionalities
                }

                // Toggle for ShowTypeInfo
                ImGui::Checkbox("Enable ShowTypeInfo", &toggleShowTypeInfo);
                if (toggleShowTypeInfo) {
                    // Enable related functionalities
                }

                // Toggle for HexViewWindow
                ImGui::Checkbox("Enable HexViewWindow", &toggleHexViewWindow);
                if (toggleHexViewWindow) {
                    // Enable related functionalities
                }

                ImGui::End();
            }
        }

        // Render additional windows based on toggles
        void RenderAdditionalWindows() {
            // Example: DisassembleAtAddress window
            if (toggleDisassembleAtAddress && ImGui::Begin("DisassembleAtAddress")) {
                static uintptr_t address = 0x00000000;
                static size_t length = 64;
                ImGui::InputScalar("Address", ImGuiDataType_U64, &address, NULL, NULL, "%016llX");
                ImGui::InputScalar("Length", ImGuiDataType_U64, &length, NULL, NULL, "%llu");
                if (ImGui::Button("Disassemble")) {
                    if (memoryScanner) {
                        state.disassemblyResults = memoryScanner->DisassembleAtAddress(address, length);
                    }
                }

                ImGui::BeginChild("DisassembleResults", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
                for (const auto& instr : state.disassemblyResults) {
                    ImGui::Text("%s", instr.c_str());
                }
                ImGui::EndChild();
                ImGui::End();
            }

            // Similarly, implement other windows based on toggles
            // FindFunctionBoundaries, EnumerateCrossReferences, etc.
        }

        // Render All Additional Windows
        void RenderAllAdditionalWindows() {
            RenderAdditionalWindows();
            // Implement rendering for other toggles similarly
        }

        // Render Settings Window for Color Customization
        void RenderSettingsWindow() {
            if (ImGui::Begin("Settings")) {
                static ImVec4 windowBg = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
                static ImVec4 textColor = ImGui::GetStyle().Colors[ImGuiCol_Text];
                static ImVec4 buttonColor = ImGui::GetStyle().Colors[ImGuiCol_Button];
                static ImVec4 buttonHoveredColor = ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered];
                static ImVec4 buttonActiveColor = ImGui::GetStyle().Colors[ImGuiCol_ButtonActive];

                if (ImGui::ColorEdit3("Window Background", (float*)&windowBg)) {
                    ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = windowBg;
                }

                if (ImGui::ColorEdit3("Text Color", (float*)&textColor)) {
                    ImGui::GetStyle().Colors[ImGuiCol_Text] = textColor;
                }

                if (ImGui::ColorEdit3("Button Color", (float*)&buttonColor)) {
                    ImGui::GetStyle().Colors[ImGuiCol_Button] = buttonColor;
                }

                if (ImGui::ColorEdit3("Button Hovered Color", (float*)&buttonHoveredColor)) {
                    ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered] = buttonHoveredColor;
                }

                if (ImGui::ColorEdit3("Button Active Color", (float*)&buttonActiveColor)) {
                    ImGui::GetStyle().Colors[ImGuiCol_ButtonActive] = buttonActiveColor;
                }

                ImGui::End();
            }
        }

        // Load persistent state from config.json
        void LoadPersistentState() {
            std::ifstream configFile("config.json");
            if (configFile.is_open()) {
                try {
                    configFile >> state.persistentState;
                    state.selectedProcess = state.persistentState["selectedProcess"].get<std::string>();
                    state.viewAddress = state.persistentState["viewAddress"].get<uintptr_t>();
                    logger.Log(LOG_INFO_LEVEL, "Loaded persistent state from config.json.");
                }
                catch (const std::exception& e) {
                    logger.Log(LOG_ERROR, "Failed to parse config.json: " + std::string(e.what()));
                }
            }
        }

        // Save persistent state to config.json
        void SavePersistentState() const {
            json saveState;
            saveState["selectedProcess"] = state.selectedProcess;
            saveState["viewAddress"] = state.viewAddress;

            std::ofstream outConfig("config.json");
            if (outConfig.is_open()) {
                outConfig << saveState.dump(4);
                outConfig.close();
                void Log(LogLevel level, const std::string & message);

            }
            else {
                void Log(LogLevel level, const std::string & message);

            }
        }

        // Function to check if the application is running as administrator
        bool IsRunningAsAdministrator(Logger& logger) {
            BOOL fIsRunAsAdmin = FALSE;
            PSID pAdministratorsGroup = NULL;

            // Allocate and initialize a SID of the administrators group.
            SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
            if (!AllocateAndInitializeSid(
                &NtAuthority,
                2,
                SECURITY_BUILTIN_DOMAIN_RID,
                DOMAIN_ALIAS_RID_ADMINS,
                0, 0, 0, 0, 0, 0,
                &pAdministratorsGroup)) {
                logger.Log(LOG_ERROR, "AllocateAndInitializeSid Error");
                return false;
            }

            // Determine whether the SID of administrators group is enabled in the primary access token of the process.
            if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) {
                logger.Log(LOG_ERROR, "CheckTokenMembership Error");
                fIsRunAsAdmin = FALSE;
            }

            // Free the SID.
            FreeSid(pAdministratorsGroup);

            return fIsRunAsAdmin == TRUE;
        }
    };

    // Win32 message handler
    LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
            return true;

        switch (msg) {
        case WM_SIZE:
            // Handle window resizing if necessary
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    // Main application initialization
    int main() {
        // Instantiate the Application class
        Application app;

        // Move semantics demonstration (optional):
        // Application movedApp(std::move(app)); // Only if you need to test move semantics

        // Initialize ImGui context and configure docking and viewport settings
        ImGui::CreateContext();
        ImGuiIO& io = ImGui::GetIO();
        io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;

        // Configure viewport settings
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
            ImGui::UpdatePlatformWindows();        // Update platform windows first
            ImGui::RenderPlatformWindowsDefault(); // Render the platform windows after updating
        }

        return 0;
    }

}