#include "unifiedManager.hpp"
#include <cstdio>

UnifiedDeviceManager::UnifiedDeviceManager(int retryIntervalMs)
    : m_serial(std::make_unique<SerialComm>())
    , m_serialConnected(false)
    , m_shouldStop(false)
    , m_retryIntervalMs(retryIntervalMs)
{
    printf("[I][Managr]: Unified device manager created\n");
}

UnifiedDeviceManager::~UnifiedDeviceManager() {
    stop();
}

void UnifiedDeviceManager::serialReconnectThreadFunc() {
    printf("[I][Managr]: Serial reconnect thread started\n");

    while (!m_shouldStop.load()) {
        if (!m_serialConnected.load()) {
            printf("[I][Managr]: Attempting to connect serial port...\n");

            std::lock_guard<std::mutex> lock(m_serialMutex);

            if (m_serial->findFirstTtyUSB() && m_serial->openPort()) {
                m_serialConnected.store(true);
                printf("[I][Managr]: Serial port connected successfully\n");
            } else {
                printf("[W][Managr]: Serial connection failed, retry in %dms\n",
                       m_retryIntervalMs);
            }
        }

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

    printf("[I][Managr]: Serial reconnect thread stopped\n");
}

void UnifiedDeviceManager::start() {
    printf("[I][Managr]: Starting unified device manager\n");

    m_shouldStop.store(false);

    if (!m_serialReconnectThread.joinable()) {
        m_serialReconnectThread = std::thread(&UnifiedDeviceManager::serialReconnectThreadFunc, this);
    }

    printf("[I][Managr]: Unified device manager started\n");
}

void UnifiedDeviceManager::stop() {
    printf("[I][Managr]: Stopping unified device manager\n");

    m_shouldStop.store(true);

    if (m_serialReconnectThread.joinable()) {
        m_serialReconnectThread.join();

        std::lock_guard<std::mutex> lock(m_serialMutex);
        m_serial->closePort();
        m_serialConnected.store(false);
    }

    printf("[I][Managr]: Unified device manager stopped\n");
}

bool UnifiedDeviceManager::sendData(const char* data, size_t length) {
    if (!m_serialConnected.load()) {
        return false;
    }

    std::lock_guard<std::mutex> lock(m_serialMutex);

    if (!m_serial->sendData(data, length)) {
        m_serialConnected.store(false);
        printf("[W][Managr]: Serial send failed, marked as disconnected\n");
        return false;
    }

    return true;
}

int UnifiedDeviceManager::receiveData(uint8_t* buffer, size_t maxLength) {
    if (!m_serialConnected.load()) {
        return -1;
    }

    std::lock_guard<std::mutex> lock(m_serialMutex);
    return m_serial->receiveData(buffer, maxLength);
}