#include <QMutexLocker>

#include "DaemonThreadManager.h"
#include "TenkinetDiscoveryThread.h"
#include "discovery.h"

#define DISCOVERY_INTERVAL 100
#define DISCOVERY_COUNT 50

static void callback(TenkinetServerInfo *info);

TenkinetDiscoveryThread::TenkinetDiscoveryThread() { DaemonThreadManager::instance().addThread(this); }

void TenkinetDiscoveryThread::run() {

    int error = tenkinet_discovery_init(TENKINET_SERVER_PORT, callback);

    if (error) {
        emit discoveryError(error);
        return;
    }

    emit discoveryInitialized();

    while (processEvents())
        ;

    tenkinet_discovery_exit();
}

bool TenkinetDiscoveryThread::processEvents() {

    {
        QMutexLocker locker(&mutex);

        while (state == IDLE) {
            condition.wait(&mutex);
        }

        if (state == SHUTDOWN) {
            return false;
        }

        state = IDLE;
    }

    emit discoveryStarted();

    tenkinet_discovery_loop(DISCOVERY_INTERVAL, DISCOVERY_COUNT);
    tenkinet_discovery_results_free();

    emit discoveryEnded();

    return true;
}

void TenkinetDiscoveryThread::shutdown() {

    mutex.lock();

    state = SHUTDOWN;
    condition.wakeOne();

    mutex.unlock();
}

void TenkinetDiscoveryThread::discover() {

    mutex.lock();

    if (state == IDLE) {
        state = DISCOVERY;
        condition.wakeOne();
    }

    mutex.unlock();
}

static void callback(TenkinetServerInfo *info) {

    QString host(info->address_str);
    QString port(info->port_str);
    TenkinetProvider *provider = new TenkinetProvider(host, port);
    provider->setServerAddress(QString(info->address_str));
    provider->setServerSerialNumber(QString(info->serial_number));
    provider->setServerName(QString(info->name_str));
    provider->setServerVersion(info->version);

    emit TenkinetDiscoveryThread::instance().discovered(provider);
}
