#include <iostream>
#include <fstream>
#include <string>
#include <curl/curl.h>
#include <thread>
#include <chrono>
#include <windows.h>
#include "nlohmann/json.hpp"  // Make sure this points to the correct location of json.hpp from nlohmann/json

// Using namespace from nlohmann to simplify json usage
using json = nlohmann::json;

// Curl write callback function
std::size_t writeCallback(void* contents, std::size_t size, std::size_t nmemb, std::string* s) {
    size_t newLength = size * nmemb;
    try {
        s->append((char*)contents, newLength);
    }
    catch (std::bad_alloc& e) {
        // Handle memory allocation errors
        return 0;
    }
    return newLength;
}

// Perform HTTP GET request
bool performRequest(const std::string& url, const std::string& savePath) {
    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cerr << "Curl initialization failed!" << std::endl;
        return false;
    }

    std::string response_string;
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_string);

    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        curl_easy_cleanup(curl);
        return false;
    }

    std::ofstream outFile(savePath);
    if (!outFile.is_open()) {
        std::cerr << "Failed to open " << savePath << std::endl;
        curl_easy_cleanup(curl);
        return false;
    }

    outFile << response_string;
    outFile.close();

    curl_easy_cleanup(curl);
    return true;
}

// Load JSON configuration from file
json loadConfig(const std::string& configPath) {
    std::ifstream configFile(configPath);
    json configJson;
    if (configFile.is_open()) {
        configFile >> configJson;
    }
    else {
        std::cerr << "Unable to open config file" << std::endl;
        std::exit(EXIT_FAILURE);
    }
    return configJson;
}

// Launch an external process and wait for it
void launchAndWait(const std::string& executablePath) {
    STARTUPINFOA si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;

    if (!CreateProcessA(NULL, const_cast<char*>(executablePath.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        std::cerr << "Failed to start process. Error: " << GetLastError() << std::endl;
        std::exit(EXIT_FAILURE);
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

int main() {
    // Specific config file path (hard-coded)
    std::string configFilePath = "config.json";
    auto config = loadConfig(configFilePath);
    std::string url = config["url"];
    std::string jsonPath = config["jsonPath"];
    int interval = config["interval"];
    std::string launchPath = config["launchPath"];

    std::thread otherApp(launchAndWait, launchPath);

    while (otherApp.joinable()) {
        if (!performRequest(url, jsonPath)) {
            std::cerr << "Error performing HTTP request." << std::endl;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(interval));
    }

    otherApp.join();
    return 0;
}

The executable should run in the background, and add a trigger when closing a particular exe + its name in the config is used. The main application should be closed after another application is closed by a trigger