#include <iostream>
#include "iobox_api.h"
#include <thread>
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
#pragma comment(lib, "winmm.lib")

#include <thread>
#include <vector>
#include <chrono>
#include <iostream>
#include <mutex>
#include <atomic>

// Mutex for thread-safe console output
std::mutex consoleMutex;

// Thread-safe console output function
void SafePrint(const std::string& message) {
    std::lock_guard<std::mutex> lock(consoleMutex);
    std::cout << message << std::endl;
}

// Test scenario 1: Reset timeout behavior
void TestResetTimeout(ANSCENTER::iobox_api* handle, const std::string& ip, int threadId) {
    std::string message = "Thread " + std::to_string(threadId) + ": Starting DO1 toggle for 8 seconds";
    SafePrint(message);

    auto start = std::chrono::steady_clock::now();

    int result = ToggleIoboxHandle(&handle, ip.c_str(), "DO1", 8000, 0, 1); // resetFlag = true

    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

    message = "Thread " + std::to_string(threadId) + ": DO1 toggle completed. Result: " +
        std::to_string(result) + ", Duration: " + std::to_string(duration) + "ms";
    SafePrint(message);
}

void TestResetTimeoutInterrupt(ANSCENTER::iobox_api* handle, const std::string& ip, int threadId) {
    // Wait 3 seconds then try to reset the timeout
    std::this_thread::sleep_for(std::chrono::milliseconds(3000));

    std::string message = "Thread " + std::to_string(threadId) + ": Attempting to reset DO0 timeout";
    SafePrint(message);

    int result = ToggleIoboxHandle(&handle, ip.c_str(), "DO1", 8000, 0, 1); // resetFlag = true

    message = "Thread " + std::to_string(threadId) + ": DO1 reset result: " + std::to_string(result);
    SafePrint(message);
}

// Test scenario 2: Reject behavior
void TestRejectBehavior(ANSCENTER::iobox_api* handle, const std::string& ip, int threadId) {
    std::string message = "Thread " + std::to_string(threadId) + ": Starting DO2 toggle for 5 seconds";
    SafePrint(message);

    int result = ToggleIoboxHandle(&handle, ip.c_str(), "DO2", 5000, 0, 0); // resetFlag = false

    message = "Thread " + std::to_string(threadId) + ": DO2 toggle completed. Result: " + std::to_string(result);
    SafePrint(message);
}

void TestRejectAttempt(ANSCENTER::iobox_api* handle, const std::string& ip, int threadId) {
    // Wait 2 seconds then try to toggle same channel (should be rejected)
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    std::string message = "Thread " + std::to_string(threadId) + ": Attempting to toggle DO2 (should be rejected)";
    SafePrint(message);

    int result = ToggleIoboxHandle(&handle, ip.c_str(), "DO2", 3000, 0, 0); // resetFlag = false

    message = "Thread " + std::to_string(threadId) + ": DO2 rejection test result: " + std::to_string(result);
    if (result == 0) {
        message += " (CORRECTLY REJECTED)";
    }
    else {
        message += " (UNEXPECTED - SHOULD HAVE BEEN REJECTED)";
    }
    SafePrint(message);
}

// Test scenario 3: Independent channels
void TestIndependentChannels(ANSCENTER::iobox_api* handle, const std::string& ip, const std::string& channel, int threadId) {
    std::string message = "Thread " + std::to_string(threadId) + ": Starting " + channel + " toggle for 4 seconds";
    SafePrint(message);

    auto start = std::chrono::steady_clock::now();

    int result = ToggleIoboxHandle(&handle, ip.c_str(), channel.c_str(), 4000, 0, 1);

    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

    message = "Thread " + std::to_string(threadId) + ": " + channel + " toggle completed. Result: " +
        std::to_string(result) + ", Duration: " + std::to_string(duration) + "ms";
    SafePrint(message);
}

// Test scenario 4: Revert flag behavior
void TestRevertFlag(ANSCENTER::iobox_api* handle, const std::string& ip, int threadId, bool revertFlag) {
    std::string mode = revertFlag ? "REVERT" : "NORMAL";
    std::string message = "Thread " + std::to_string(threadId) + ": Testing DO3 with " + mode + " mode for 3 seconds";
    SafePrint(message);

    int result = ToggleIoboxHandle(&handle, ip.c_str(), "DO3", 3000, revertFlag ? 1 : 0, 1);

    message = "Thread " + std::to_string(threadId) + ": DO3 " + mode + " mode completed. Result: " + std::to_string(result);
    SafePrint(message);
}

int ToggleTest() {
    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "=== MULTITHREAD TOGGLE TEST START ===\n\n";

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
        return -1;
    }

    std::string ioBoxIP = "192.168.1.34"; // Set your actual IP
    std::string username = "admin";
    std::string password = "1234";

    std::cout << "\n2. Connect to " << ioBoxIP << "\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    std::string deviceInfo;
    int connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }
    std::cout << "\n3. Testing toggle scenarios for multiple channels\n\n";

    // Test Scenario 1: Reset timeout behavior
    std::cout << "=== TEST 1: Reset Timeout Behavior ===\n";
    std::cout << "Expected: DO1 will be ON for ~11 seconds (8s + 3s reset)\n";
    std::vector<std::thread> threads1;

    threads1.emplace_back(TestResetTimeout, infHandle, ioBoxIP, 1);
    threads1.emplace_back(TestResetTimeoutInterrupt, infHandle, ioBoxIP, 2);

    for (auto& t : threads1) {
        t.join();
    }

    std::cout << "\n=== TEST 1 COMPLETED ===\n\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // Wait between tests

    // Test Scenario 2: Reject behavior
    std::cout << "=== TEST 2: Reject Behavior ===\n";
    std::cout << "Expected: DO2 will be ON for exactly 5 seconds, second call rejected\n";
    std::vector<std::thread> threads2;

    threads2.emplace_back(TestRejectBehavior, infHandle, ioBoxIP, 3);
    threads2.emplace_back(TestRejectAttempt, infHandle, ioBoxIP, 4);

    for (auto& t : threads2) {
        t.join();
    }

    std::cout << "\n=== TEST 2 COMPLETED ===\n\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // Wait between tests

    // Test Scenario 3: Independent channels
    std::cout << "=== TEST 3: Independent Channels ===\n";
    std::cout << "Expected: DO3, DO4 all toggle independently for 4 seconds\n";
    std::vector<std::thread> threads3;

    threads3.emplace_back(TestIndependentChannels, infHandle, ioBoxIP, "DO3", 5);
    threads3.emplace_back(TestIndependentChannels, infHandle, ioBoxIP, "DO4", 6);

    for (auto& t : threads3) {
        t.join();
    }

    std::cout << "\n=== TEST 3 COMPLETED ===\n\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // Wait between tests

    // Test Scenario 4: Revert flag behavior
    std::cout << "=== TEST 4: Revert Flag Behavior ===\n";
    std::cout << "Expected: First call turns OFF then ON, second call turns ON then OFF\n";
    std::vector<std::thread> threads4;

    threads4.emplace_back(TestRevertFlag, infHandle, ioBoxIP, 8, true);  // revert = true
    std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Small delay
    threads4.emplace_back(TestRevertFlag, infHandle, ioBoxIP, 9, false); // revert = false

    for (auto& t : threads4) {
        t.join();
    }

    std::cout << "\n=== TEST 4 COMPLETED ===\n\n";

    // Test Scenario 5: Stress test with multiple resets
    std::cout << "=== TEST 5: Stress Test - Multiple Resets ===\n";
    std::cout << "Expected: DO6 will have extended ON time due to multiple resets\n";

    auto stressTest = [&](int threadId) {
        std::string message = "Thread " + std::to_string(threadId) + ": Starting DO1 stress test";
        SafePrint(message);

        int result = ToggleIoboxHandle(&infHandle, ioBoxIP.c_str(), "DO1", 10000, 0, 1);

        message = "Thread " + std::to_string(threadId) + ": DO1 stress test completed. Result: " + std::to_string(result);
        SafePrint(message);
        };

    auto resetTest = [&](int threadId, int delay) {
        std::this_thread::sleep_for(std::chrono::milliseconds(delay));
        std::string message = "Thread " + std::to_string(threadId) + ": Resetting DO1 timeout";
        SafePrint(message);

        int result = ToggleIoboxHandle(&infHandle, ioBoxIP.c_str(), "DO1", 5000, 0, 1);

        message = "Thread " + std::to_string(threadId) + ": DO1 reset result: " + std::to_string(result);
        SafePrint(message);
        };

    std::vector<std::thread> threads5;
    threads5.emplace_back(stressTest, 10);
    threads5.emplace_back(resetTest, 11, 2000);  // Reset after 2s
    threads5.emplace_back(resetTest, 12, 6000);  // Reset after 6s
    threads5.emplace_back(resetTest, 13, 10000); // Reset after 10s

    for (auto& t : threads5) {
        t.join();
    }

    std::cout << "\n=== TEST 5 COMPLETED ===\n\n";

    std::cout << "\n4. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }

    std::cout << "\n=== MULTITHREAD TOGGLE TEST COMPLETED ===\n";
    return 0;
}


//void ListWaveOutDevicesSimple() {
//    UINT numDevices = waveOutGetNumDevs();
//    std::cout << "Available Audio Output Devices:\n";
//
//    for (UINT i = 0; i < numDevices; i++) {
//        WAVEOUTCAPS caps;
//        if (waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
//            std::wcout << i << ": " << caps.szPname << std::endl;
//        }
//    }
//}


/*
* 
using ANSCENTER::iobox_api;
iobox_api ioBoxApp((char*)"239.255.255.250", 12345);
void userInputThread(iobox_api* api) {
    std::string current_ip;

    while (true) {
        std::string input;
        std::cout << std::endl;
        std::cout << "Enter command followed by Enter: exit, scan, setup, connect, channels, disconnect, show, get, set, restart, setauthen, resetauthen" << std::endl;
        // std::cin >> input;       // This will only get the first word
        std::getline(std::cin, input);
        if (input == "exit") {
            break;
        }
        else if(input == "scan") {
            std::vector<std::string> devices = api->scanNetworkDevicesMulticast(5);
            std::cout << "Found devices: " << devices.size() << std::endl;
            for (const std::string& device : devices) {
                std::cout << device << std::endl;
            }
            continue;
        }
        else if(input == "setup") {
            std::cout << "Enter IP: ";
            std::getline(std::cin, current_ip);
            continue;
        }
        else if(input == "connect") {
            if(current_ip == "") {
                std::cout << "Please setip address first" << std::endl;
                continue;
            }
            std::string username, password;
            std::cout << "Enter username: ";
            std::cin >> username;
            std::cout << "Enter password: ";
            std::cin >> password;
            bool connect = api->connectToIobox(current_ip, DEVICE_TCP_PORT, username, password);
            std::cout << "Connection to " << current_ip << (connect ? " succeeded." : " failed.") << std::endl;
            continue;
        }
        else if(input == "disconnect") {
            bool disconnect = api->disconnectToIobox(current_ip);
            std::cout << "Disconnect to " << current_ip << (disconnect ? " succeeded." : " failed.") << std::endl;
            // current_ip = "";
            continue;
        }
        else if(input == "show") {
            api->show_profile_ioboxs();
            continue;
        }
        else if(input == "get") {
            std::string channel;
            std::cout << "Enter channel: ";
            std::cin >> channel;
            std::string value = api->getValueDataStringIoboxFromChannelName(current_ip, channel);
            std::cout << "Value of " << channel << ": " << value << std::endl;
            continue;
        }
        else if(input == "set") {
            std::string  value;
            std::string channel;
            std::cout << "Enter channel: ";
            std::cin >> channel;
            std::cout << "Enter value: ";
            std::cin >> value;
            bool set = api->setValueDataStringIoboxFromChannelName(current_ip, channel, value);
            std::cout << "Set value to " << current_ip << (set ? " succeeded." : " failed.") << std::endl;
        }
        else if(input == "restart") {
            std::string token = api->generateToken(current_ip);
            bool reset = api->resetIobox(current_ip, token);
            std::cout << "Restart " << current_ip << (reset ? " succeeded." : " failed.") << std::endl;
        }
        else if(input == "setauthen") {
            std::string username, password;
            std::cout << "Enter username: ";
            std::cin >> username;
            std::cout << "Enter password: ";
            std::cin >> password;
            bool set = api->setAuthenticationIobox(current_ip, username, password);
            std::cout << "Set authentication to " << current_ip << (set ? " succeeded." : " failed.") << std::endl;
        }
        else if(input == "resetauthen") {
            std::string token = api->generateToken(current_ip);
            bool reset = api->resetAuthenticationIobox(current_ip, token);
            std::cout << "Reset authentication to " << current_ip << (reset ? " succeeded." : " failed.") << std::endl;
        }
        else if(input == "channels") {
            std::vector<std::string> channels = api->getDeviceChannelNames(current_ip);
            std::cout << "Channels of " << current_ip << std::endl;
            for(const std::string& channel : channels) {
                std::cout << channel << std::endl;
            }
        }
        else {
            // std::cout << "Invalid command" << std::endl;
        }
    }
}
int main()
{
    std::thread userThread(userInputThread, &ioBoxApp);
    userThread.join();

    std::cout << "Main thread is done" << std::endl;
    return 0;
}

*/

int FullTest() {

    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token;

    std::cout << "\n2. Get Device Channels\n";
    GetChannelNamesANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 5, ChannelNames);
    std::cout << "Channel Names: " << ChannelNames << std::endl;

    std::cout << "\n3. Generate token information\n";
    GenerateANSIOTokenHandle_CPP(&infHandle, ioBoxIP.c_str(), token);
    std::cout << "Token: " << token << std::endl;

    std::cout << "\n4. Reset box authentication information\n";
    int resetAuthenStatus = ResetAuthenticationANSIOHandle(&infHandle, ioBoxIP.c_str(), token.c_str());
    if (resetAuthenStatus == 1) {
        std::cout << "Reset authentication information successfully" << std::endl;
    }
    else {
        std::cout << "Reset authentication information failed" << std::endl;
    }

    std::cout << "\n5. Connect to " << ioBoxIP<<std::endl;
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    int connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }
    std::cout << "\n6.1. Scan ANSDAQ devices from LAN\n";
    std::string deviceAddresses;
    ScanANSIOHandle_CPP(&infHandle, 5, deviceAddresses);
    std::cout << "Found devices: " << deviceAddresses << std::endl;

    std::cout << "\n6.2. Scan ANSDAQ devices from LAN (Unicast)\n";
    std::string unicastDeviceAddresses;
    ScanANSIOUnicastHandle_CPP(&infHandle, 5, unicastDeviceAddresses);
    std::cout << "Found devices: " << unicastDeviceAddresses << std::endl;

    std::cout << "\n7. Connect to " << ioBoxIP << std::endl;;

    std::cout << "Username:" << username << " Password:" << password << std::endl;
    connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }

    std::cout << "\n8. Change username and password\n";
    std::string newUsername = "admin";
    std::string newPassword = "1234";
    std::cout << "New Username:" << newUsername << " New Password:" << newPassword << std::endl;
    int changeAuthenticationStatus = SetAuthenticationANSIOHandle(&infHandle, ioBoxIP.c_str(), newUsername.c_str(), newPassword.c_str());
    if (changeAuthenticationStatus == 1) {
        std::cout << "Changed authentication information successfully" << std::endl;
    }
    else {
        std::cout << "Changed authentication information failed" << std::endl;
    }
    std::cout << "\n9. Disconnect the IOBOX and reconnect with it via new authentication\n";
    int disconnectStatus1 = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
    if (disconnectStatus1 == 1) {
        std::cout << "Disconnected from IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Disconnection from IOBox failed" << std::endl;
    }
    int connectStatus1 = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, newUsername.c_str(), newPassword.c_str(), deviceInfo);
    if (connectStatus1 == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }
    std::cout << "\n10. Get Device Channels\n";
    GetChannelNamesANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 5, ChannelNames);
    std::cout << "Channel Names: " << ChannelNames << std::endl;

    std::cout << "\n11. Set Value 1 to Channel D01\n";

    int setValueStatus = SetValueANSIOHandle(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value.c_str());
    if (setValueStatus == 1) {
        std::cout << "Value set successfully" << std::endl;
    }
    else {
        std::cout << "Value set failed" << std::endl;
    }
    value = "";
    std::cout << "\n12. Get Value from Channel D01\n";

    GetValueANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value);
    std::cout << "Value of " << channelName << ": " << value << std::endl;

    std::cout << "\n13. Disconnect from device:" << ioBoxIP<<std::endl;

    int disconnectStatus = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
    if (disconnectStatus == 1) {
        std::cout << "Disconnected from IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Disconnection from IOBox failed" << std::endl;
    }
    std::cout << "\n14. Reset OI BOX "<< ioBoxIP << std::endl;

    int resetStatus = ResetANSIOHandle(&infHandle, ioBoxIP.c_str(), token.c_str());
    if (resetStatus == 1) {
        std::cout << "Reset IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Reset IOBox failed" << std::endl;
    }

    std::cout << "\n15. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}


int GenTokenTest() {

    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token = "IIO001234ANS IOBOX";

    std::cout << "\n2. Get Device Channels\n";
    GetChannelNamesANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 5, ChannelNames);
    std::cout << "Channel Names: " << ChannelNames << std::endl;

    //std::cout << "\n3. Generate token information\n";
    //GenerateANSIOTokenHandle_CPP(&infHandle, ioBoxIP.c_str(), token);
    //std::cout << "Token: " << token << std::endl;

    std::cout << "\n4. Reset box authentication information\n";
    int resetAuthenStatus = ResetAuthenticationANSIOHandle(&infHandle, ioBoxIP.c_str(), token.c_str());
    if (resetAuthenStatus == 1) {
        std::cout << "Reset authentication information successfully" << std::endl;
    }
    else {
        std::cout << "Reset authentication information failed" << std::endl;
    }
    std::cout << "\n5. Reset  ANSDAQ object\n";

    int resetStatus = ResetANSIOHandle(&infHandle, ioBoxIP.c_str(), token.c_str());
    if (resetStatus == 1) {
        std::cout << "Reset IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Reset IOBox failed" << std::endl;
    }

    std::cout << "\n5. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}
int testTimeStamp() {
    for (size_t i = 0; i < 1000; i++)
    {
        long m_pts = std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now().time_since_epoch()
        ).count();
        std::cout << "Time Stamp: " << m_pts << std::endl;
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    return 0;


}

// Structure to store device ID and device name
struct DeviceInfo {
    UINT deviceID;
    std::wstring deviceName;
};

// Function to list available audio output devices and store them with their IDs
void ListWaveOutDevices(std::vector<DeviceInfo>& deviceList) {
    UINT numDevices = waveOutGetNumDevs();
    std::cout << "Available Audio Output Devices:\n";

    for (UINT i = 0; i < numDevices; i++) {
        WAVEOUTCAPS caps;
        if (waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) {
            std::wcout << i << ": " << caps.szPname << std::endl;
            deviceList.push_back({ i, caps.szPname });  // Store device ID and name
        }
    }
}

// Function to find device ID by device name
UINT GetDeviceIDByName(const std::vector<DeviceInfo>& deviceList, const std::wstring& deviceName) {
    for (const auto& device : deviceList) {
        if (device.deviceName == deviceName) {
            return device.deviceID;
        }
    }
    return UINT(-1);  // Return invalid ID if not found
}

// Function to play a WAV file on a selected device by name
bool PlayWavOnDevice(const std::string& filename, const std::wstring& deviceName) {
    // Initialize device list and find device ID by name
    std::vector<DeviceInfo> deviceList;
    ListWaveOutDevices(deviceList);
    UINT deviceID = GetDeviceIDByName(deviceList, deviceName);

    if (deviceID == UINT(-1)) {
        //std::cerr << "Device with name " << deviceName << " not found.\n";
        return false;
    }

    HWAVEOUT hWaveOut;
    WAVEFORMATEX wfx = { 0 };
    MMCKINFO chunk, formatChunk;
    HMMIO hMmio;
    MMIOINFO mmioInfo = { 0 };

    // Open WAV file
    hMmio = mmioOpenA((LPSTR)filename.c_str(), &mmioInfo, MMIO_READ);
    if (!hMmio) {
        std::cerr << "Failed to open WAV file: " << filename << std::endl;
        return false;
    }

    // Locate the RIFF chunk
    chunk.fccType = mmioFOURCC('W', 'A', 'V', 'E');
    if (mmioDescend(hMmio, &chunk, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR) {
        std::cerr << "Invalid WAV file.\n";
        mmioClose(hMmio, 0);
        return false;
    }

    // Locate the 'fmt ' chunk
    formatChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
    if (mmioDescend(hMmio, &formatChunk, &chunk, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) {
        std::cerr << "Failed to locate format chunk.\n";
        mmioClose(hMmio, 0);
        return false;
    }

    // Read WAV format
    mmioRead(hMmio, (HPSTR)&wfx, sizeof(WAVEFORMATEX));
    mmioAscend(hMmio, &formatChunk, 0);

    // Open audio output device
    if (waveOutOpen(&hWaveOut, deviceID, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
        std::cerr << "Failed to open audio device ID: " << deviceID << std::endl;
        mmioClose(hMmio, 0);
        return false;
    }

    // Locate the 'data' chunk
    MMCKINFO dataChunk;
    dataChunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
    if (mmioDescend(hMmio, &dataChunk, &chunk, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) {
        std::cerr << "Failed to locate data chunk.\n";
        waveOutClose(hWaveOut);
        mmioClose(hMmio, 0);
        return false;
    }

    // Read and play the audio data
    std::vector<BYTE> audioData(dataChunk.cksize);
    mmioRead(hMmio, (HPSTR)audioData.data(), dataChunk.cksize);

    WAVEHDR waveHdr = { 0 };
    waveHdr.lpData = (LPSTR)audioData.data();
    waveHdr.dwBufferLength = dataChunk.cksize;
    waveHdr.dwFlags = 0;

    waveOutPrepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &waveHdr, sizeof(WAVEHDR));

    // Wait for playback to finish
    while (!(waveHdr.dwFlags & WHDR_DONE)) {
        Sleep(100);
    }

    // Clean up
    waveOutUnprepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR));
    waveOutClose(hWaveOut);
    mmioClose(hMmio, 0);

    std::cout << "Playback finished.\n";
    return true;
}

int UpdateFirmwareTest() {

    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token;
    int connectStatus;
    std::cout << "\n2. Get Device Channels\n";
    GetChannelNamesANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 5, ChannelNames);
    std::cout << "Channel Names: " << ChannelNames << std::endl;

    std::cout << "\n3. Generate token information\n";
    GenerateANSIOTokenHandle_CPP(&infHandle, ioBoxIP.c_str(), token);
    std::cout << "Token: " << token << std::endl;

    std::cout << "\n4. Reset box authentication information\n";
    int resetAuthenStatus = ResetAuthenticationANSIOHandle(&infHandle, ioBoxIP.c_str(), token.c_str());
    if (resetAuthenStatus == 1) {
        std::cout << "Reset authentication information successfully" << std::endl;
    }
    else {
        std::cout << "Reset authentication information failed" << std::endl;
    }

    std::cout << "\n5. Connect to 192.168.1.32\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }

    std::cout << "\n6.1. Scan ANSDAQ devices from LAN\n";
    std::string deviceAddresses;
    ScanANSIOHandle_CPP(&infHandle, 5, deviceAddresses);
    std::cout << "Found devices: " << deviceAddresses << std::endl;


    //std::cout << "\n6.2. Scan ANSDAQ devices from LAN (Unicast)\n";
    //std::string unicastDeviceAddresses;
    //ScanANSIOUnicastHandle_CPP(&infHandle, 5, unicastDeviceAddresses);
    //std::cout << "Found devices: " << unicastDeviceAddresses << std::endl;

    std::cout << "\n7. Connect to 192.168.1.32\n";

    std::cout << "Username:" << username << " Password:" << password << std::endl;
    connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }

   
   /* std::cout << "\n8. Update 192.168.1.32 firmware\n";

	std::string firmwarePath = "C:\\Projects\\ANSVIS\\Documentation\\IOBOX\\esp_iobox_device_fw15.bin";
    int firmwareUpdateStatus = OTAANSIOFirmwareDevice(& infHandle, ioBoxIP.c_str(), firmwarePath.c_str(), "esp");
	if (firmwareUpdateStatus == 1) {
		std::cout << "Firmware update successfully" << std::endl;
	}
	else {
		std::cout << "Firmware update failed" << std::endl;
	}
    
    std::cout << "\n9. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }*/
    return 0;

}
int ConnectTest() {
    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token = "IIO001234ANS IOBOX";

    std::cout << "\n2. Connect to 192.168.1.34\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    
    int connectStatus;
    for (int i = 0; i < 100; i++) {
        connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
        if (connectStatus == 1) {
            std::cout << "Connected to IOBox successfully" << std::endl;
            std::cout << "Device Info: " << deviceInfo << std::endl;
        }
        else {
            std::cout << "Connection to IOBox failed" << std::endl;
        }
    }
    int setValueStatus = 0;
	for (int i = 0; i < 100; i++) {
        std::cout << "\n3. Set Value 1 to Channel D01\n";
        value = "1";
        setValueStatus = SetValueANSIOHandle(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value.c_str());
        if (setValueStatus == 1) {
            std::cout << "Value set successfully" << std::endl;
        }
        else {
            std::cout << "Value set failed" << std::endl;
        }
        value = "";
        std::cout << "\n4. Get Value from Channel D01\n";

        GetValueANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value);
        std::cout << "Value of " << channelName << ": " << value << std::endl;
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        
        value = "0";
        setValueStatus = SetValueANSIOHandle(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value.c_str());
        if (setValueStatus == 1) {
            std::cout << "Value set successfully" << std::endl;
        }
        else {
            std::cout << "Value set failed" << std::endl;
        }
        value = "";
        std::cout << "\n4. Get Value from Channel D01\n";

        GetValueANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), channelName.c_str(), value);
        std::cout << "Value of " << channelName << ": " << value << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
	}
   
    std::cout << "\n4.1. Scan ANSDAQ devices from LAN\n";
    std::string deviceAddresses;
    ScanANSIOHandle_CPP(&infHandle, 5, deviceAddresses);
    std::cout << "Found devices: " << deviceAddresses << std::endl;

    std::cout << "\n5. Disconnect from device 192.168.1.34\n";

    int disconnectStatus = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
    if (disconnectStatus == 1) {
        std::cout << "Disconnected from IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Disconnection from IOBox failed" << std::endl;
    }

    std::cout << "\n6. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}
int StressTest() {
    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token = "IIO001234ANS IOBOX";
    std::string deviceAddresses;
	std::string unicastDeviceAddresses;
    std::cout << "\n2. Connect to 192.168.1.34\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;

    int connectStatus;
    for (int i = 0; i < 100; i++) {
       
        std::cout << "\n3.1.1 Scan ANSDAQ devices from LAN multicast\n";
        ScanANSIOHandle_CPP(&infHandle, 5, deviceAddresses);
        std::cout << "Found devices: " << deviceAddresses << std::endl;
        std::cout << "\n3.1.2 Scan ANSDAQ devices from LAN Unicast\n";

        ScanANSIOUnicastHandle_CPP(&infHandle, 5, unicastDeviceAddresses);
        std::cout << "Found devices: " << unicastDeviceAddresses << std::endl;

        std::cout << "\n3.2. Connect to device\n";

        connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
        if (connectStatus == 1) {
            std::cout << "Connected to IOBox successfully" << std::endl;
            std::cout << "Device Info: " << deviceInfo << std::endl;
        }
        else {
            std::cout << "Connection to IOBox failed" << std::endl;
        }
        std::cout << "\n3.3. Get device channel names\n";
        
        GetChannelNamesANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 5, ChannelNames);
        std::cout << "Channel Names: " << ChannelNames << std::endl;
        std::cout << "\n3.4. Disconnect from device\n";

        int disconnectStatus = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
        if (disconnectStatus == 1) {
            std::cout << "Disconnected from IOBox successfully" << std::endl;
        }
        else {
            std::cout << "Disconnection from IOBox failed" << std::endl;
        }
    }
    


    

    std::cout << "\n4. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}
int AdvancedConnectionTest() {
    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "";// "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token = "IIO001234ANS IOBOX";
    std::string deviceAddresses;
    std::cout << "\n2. Connect to 192.168.1.34\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;

	int connection = AdvancedConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502,"e831cd6e2163", username.c_str(), password.c_str(), deviceAddresses);
	if (connection == 1) {
		std::cout << "Connected to IOBox successfully" << std::endl;
		std::cout << "Device Info: " << deviceAddresses << std::endl;
	}
	else {
		std::cout << "Connection to IOBox failed" << std::endl;
	}


    std::cout << "\n4. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}

int AdvancedScan() {
    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
    }
    std::string ioBoxIP = "";// "192.168.1.34";
    std::string channelName = "DO1";
    std::string value = "1";
    std::string ChannelNames;
    std::string username = "admin";
    std::string password = "1234";
    std::string deviceInfo;
    std::string token = "IIO001234ANS IOBOX";
    std::string deviceAddresses;
    std::cout << "\n2. Connect to 192.168.1.34\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;

    int connection = AdvancedScanANSIOHandle_CPP(&infHandle,5, deviceAddresses);
    if (connection == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceAddresses << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }


    std::cout << "\n4. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}
int AdvancedStaticScan() {
    std::string deviceAddresses;
    int connection = AdvancedStaticScanANSIOHandle_CPP(5, deviceAddresses);
    if (connection == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceAddresses << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }

    return 0;

}
int TestSetGet() {
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;


    std::cout << "1. Create ANSDAQ object\n";
    ANSCENTER::iobox_api* infHandle= new ANSCENTER::iobox_api(multicastIPAddress, multicastPort);



    std::string ioBoxIP = "192.168.1.34"; // Set your actual IP
    std::string username = "admin";
    std::string password = "1234";

    std::cout << "\n2. Connect to " << ioBoxIP << "\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    std::string deviceInfo =infHandle->connectToIobox(ioBoxIP, 502, username, password);

    if (!deviceInfo.empty()) {
        std::cout << "Connected to IOBox successfully\n";
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed\n";
	}

    std::string channelName = "DO1";
    std::string value = "1";
    bool setValueStatus;
    for (int i = 0; i <= 2000; i++) {
		std::cout << "\nIteration: " << i+1 << "\n";
        channelName = "DO1";
        value = "1";
        std::cout << "\n Set Value 1 to Channel D01\n";
        setValueStatus = infHandle->setValue(ioBoxIP, channelName, value);     
         infHandle->getValue(ioBoxIP, channelName, value);
        if (value!="1") {
            std::cout << "FAILED TO SET VALUE 1\n";
            break;
        }
        Sleep(2000);
        value = "0";
        std::cout << "\n Set Value 0 to Channel D01\n";
        setValueStatus = infHandle->setValue(ioBoxIP, channelName, value); 
        infHandle->getValue(ioBoxIP, channelName, value);
        if (value != "0") {
            std::cout << "FAILED TO SET VALUE 0\n";
            break;
        }
    }
   

    std::cout << "\n5. Disconnect from device: " << ioBoxIP << "\n";
    bool disconnectStatus = infHandle->disconnectToIoboxWithResetOutputs(ioBoxIP);
    if (disconnectStatus) {
        std::cout << "Disconnected from IOBox successfully\n";
    }
    else {
        std::cout << "Disconnection from IOBox failed\n";
    }
    std::cout << "\n6. Release ANSDAQ object\n";
    delete infHandle;
    std::cout << "Handle released successfully\n";
	return 0;
}
int SimpleToggleTest() {

    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "=== MULTITHREAD TOGGLE TEST START ===\n\n";

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
        return -1;
    }

    std::string ioBoxIP = "192.168.1.34"; // Set your actual IP
    std::string username = "admin";
    std::string password = "1234";

    std::cout << "\n2. Connect to " << ioBoxIP << "\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    std::string deviceInfo;
    int connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }
    std::cout << "\n3. Testing toggle scenarios for multiple channels\n\n";

    for (int i = 0; i < 1000; i++) {
        bool toggleResult=ToggleIoboxHandle(&infHandle, ioBoxIP.c_str(), "DO1", 5000, false, true);
        if (!toggleResult) break;
		std::cout << "\n--- Toggle iteration " << i + 1 << " completed ---\n" << std::endl;
    
    }
    
    int disconnectStatus = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
    if (disconnectStatus == 1) {
        std::cout << "Disconnected from IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Disconnection from IOBox failed" << std::endl;
    }
    std::cout << "\n5. Reset OI BOX " << ioBoxIP << std::endl;

 

    std::cout << "\n6. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}

int AsyncToggleTest() {

    ANSCENTER::iobox_api* infHandle;
    std::string multicastIPAddress = "239.255.255.250";
    int multicastPort = 12345;

    std::cout << "=== MULTITHREAD TOGGLE TEST START ===\n\n";

    std::cout << "1. Create ANSDAQ object\n";
    int createHandle = CreateANSIOHandle(&infHandle, multicastIPAddress.c_str(), multicastPort);
    if (createHandle == 1) {
        std::cout << "Handle created successfully" << std::endl;
    }
    else {
        std::cout << "Handle creation failed" << std::endl;
        return -1;
    }

    std::string ioBoxIP = "192.168.1.34"; // Set your actual IP
    std::string username = "admin";
    std::string password = "1234";

    std::cout << "\n2. Connect to " << ioBoxIP << "\n";
    std::cout << "Username:" << username << " Password:" << password << std::endl;
    std::string deviceInfo;
    int connectStatus = ConnectANSIOHandle_CPP(&infHandle, ioBoxIP.c_str(), 502, username.c_str(), password.c_str(), deviceInfo);
    if (connectStatus == 1) {
        std::cout << "Connected to IOBox successfully" << std::endl;
        std::cout << "Device Info: " << deviceInfo << std::endl;
    }
    else {
        std::cout << "Connection to IOBox failed" << std::endl;
    }
    std::cout << "\n3. Testing toggle scenarios for 5s channels\n\n";
    bool toggleResult = false;
    for (int i = 0; i < 1000; i++) {
        toggleResult = ToggleIoboxHandleAsync(&infHandle, ioBoxIP.c_str(), "DO1", 5000, false, true);
        Sleep(6000); // Let the async toggle run for a while
        if (!toggleResult) {
            std::cout << "Toggle operation failed to start." << std::endl;
        }
        else {
            std::cout << "Toggle operation started successfully." << std::endl;
        }
    }


    int disconnectStatus = DisconnectANSIOHandle(&infHandle, ioBoxIP.c_str());
    if (disconnectStatus == 1) {
        std::cout << "Disconnected from IOBox successfully" << std::endl;
    }
    else {
        std::cout << "Disconnection from IOBox failed" << std::endl;
    }
    std::cout << "\n5. Reset OI BOX " << ioBoxIP << std::endl;



    std::cout << "\n6. Release ANSDAQ object\n";
    int releaseStatus = ReleaseANSIOHandle(&infHandle);
    if (releaseStatus == 1) {
        std::cout << "Handle released successfully" << std::endl;
    }
    else {
        std::cout << "Handle release failed" << std::endl;
    }
    return 0;

}
int main() {
    
    //AsyncToggleTest();
    //SimpleToggleTest();
    //TestSetGet();
    //ToggleTest();//
   // AdvancedStaticScan();
    //AdvancedScan();
    //AdvancedConnectionTest();
    //StressTest();
    //ConnectTest();
    //UpdateFirmwareTest();
	//ConnectTest();
    //GenTokenTest();
    FullTest();
   // testTimeStamp();
    //ListWaveOutDevices();

    // List devices and store them
    //std::vector<DeviceInfo> deviceList;
    //ListWaveOutDevices(deviceList);

    //// Ask the user to choose a device by name
    //std::wcout << "Enter the device name to use for playback: ";
    //std::wstring deviceName;
    //std::getline(std::wcin, deviceName);  // Get the device name as a string

    //// Play a WAV file on the selected device
    //std::string filePath = "test.wav"; // Replace with the actual WAV file path
    //PlayWavOnDevice(filePath, deviceName);

    return 0;
}
