QServiceDiscovery::QServiceDiscovery(QObject *parent) :
    QObject(parent),
    QQmlParserStatus(),
    m_componentCompleted(false),
    m_running(false),
    m_networkReady(false),
    m_lookupReady(false),
    m_lookupMode(MulticastDNS),
    m_unicastLookupInterval(5000),
    m_unicastErrorThreshold(2),
    m_filter(new QServiceDiscoveryFilter(this)),
    m_networkSession(NULL),
    m_networkConfigManager(NULL),
    m_networkConfigTimer(new QTimer(this)),
    m_jdns(NULL),
    m_unicastLookupTimer(new QTimer(this))
{
    m_networkConfigTimer->setInterval(3000);
    connect(m_networkConfigTimer, SIGNAL(timeout()),
            this, SLOT(updateNetConfig()));

    m_unicastLookupTimer->setInterval(m_unicastLookupInterval);
    connect(m_unicastLookupTimer, SIGNAL(timeout()),
            this, SLOT(unicastLookup()));

    connect(this, SIGNAL(nameServersChanged(QQmlListProperty<QNameServer>)),
            this, SLOT(updateNameServers()));
}
bool QServiceDiscovery::initializeMdns()
{
    bool initialized;

    if (m_jdns != NULL) // already initialized
    {
        return true;
    }

#ifdef QT_DEBUG
    QString mode;
    if (m_lookupMode == MulticastDNS)
    {
        mode = "multicast";
    }
    else {
        mode = "unicast";
    }
    DEBUG_TAG(1, "SD", "Initializing JDNS " + mode);
#endif

    m_jdns = new QJDns(this);

    connect(m_jdns, SIGNAL(resultsReady(int,QJDns::Response)),
            this, SLOT(resultsReady(int,QJDns::Response)));
    connect(m_jdns, SIGNAL(error(int,QJDns::Error)),
            this, SLOT(error(int,QJDns::Error)));

    if (m_lookupMode == MulticastDNS)
    {
#if defined(Q_OS_ANDROID)
        QAndroidJniObject::callStaticMethod<void>("io/machinekit/service/MulticastActivator",
                                                  "enable");
#endif
        initialized = m_jdns->init(QJDns::Multicast, QHostAddress::Any);
    }
    else
    {
        initialized = m_jdns->init(QJDns::Unicast, QHostAddress::Any);
    }

    if (!initialized) // something went wrong
    {
#ifdef QT_DEBUG
        DEBUG_TAG(1, "SD", "Initializing JDNS failed");
        DEBUG_TAG(1, "SD", m_jdns->debugLines());
#endif

        m_jdns->deleteLater();
        m_jdns = NULL;
        return false;
    }
    else
    {
        m_lookupReady = true;

        if (m_lookupMode == UnicastDNS)
        {
            updateNameServers();
        }

        if (m_running == true)
        {
            updateServices();

            if (m_lookupMode == UnicastDNS)
            {
                m_unicastLookupTimer->start();
            }
        }

        emit lookupReadyChanged(m_lookupReady);
    }

    return true;
}
bool ServiceDiscovery::initializeMdns()
{
    bool initialized;

    if (!m_jdns.isNull()) // already initialized
    {
        return true;
    }

    DEBUG_TAG(1, "SD", "Initializing JDNS " << ((m_lookupMode == MulticastDNS) ? "multicast" : "unicast"));

    m_jdns = new QJDns(this);

    connect(m_jdns, &QJDns::resultsReady,
            this, &ServiceDiscovery::resultsReady);
    connect(m_jdns, &QJDns::error,
            this, &ServiceDiscovery::error);

    if (m_lookupMode == MulticastDNS)
    {
#if defined(Q_OS_ANDROID)
        QtAndroid::runOnAndroidThreadSync([](){
            QAndroidJniObject::callStaticMethod<void>("io/machinekit/service/MulticastActivator", "enable",
                                                      "(Landroid/content/Context;)V", QtAndroid::androidActivity().object<jobject>());
        });
#endif
        initialized = m_jdns->init(QJDns::Multicast, QHostAddress::Any);
    }
    else
    {
        initialized = m_jdns->init(QJDns::Unicast, QHostAddress::Any);
    }

    if (!initialized) // something went wrong
    {
        DEBUG_TAG(1, "SD", "Initializing JDNS failed");
        DEBUG_TAG(1, "SD", m_jdns->debugLines());

        m_jdns->deleteLater();
        m_jdns.clear();
        return false;
    }
    else
    {
        m_lookupReady = true;

        if (m_lookupMode == UnicastDNS)
        {
            updateNameServers();
        }

        if (m_running == true)
        {
            updateServices();

            if (m_lookupMode == UnicastDNS)
            {
                m_unicastLookupTimer.start();
            }
        }

        emit lookupReadyChanged(m_lookupReady);
    }

    return true;
}