/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QLoggingCategory>
#include <QtCore/QRandomGenerator>
#include <QtDBus/QDBusContext>

#include "qbluetoothlocaldevice.h"
#include "qbluetoothaddress.h"
#include "qbluetoothlocaldevice_p.h"

#include "bluez/manager_p.h"
#include "bluez/adapter_p.h"
#include "bluez/agent_p.h"
#include "bluez/device_p.h"
#include "bluez/bluez5_helper_p.h"
#include "bluez/objectmanager_p.h"
#include "bluez/properties_p.h"
#include "bluez/adapter1_bluez5_p.h"
#include "bluez/device1_bluez5_p.h"

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)

static const QLatin1String agentPath("/qt/agent");

inline uint qHash(const QBluetoothAddress &address)
{
    return ::qHash(address.toUInt64());
}

QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
    QObject(parent),
    d_ptr(new QBluetoothLocalDevicePrivate(this))
{
}

QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) :
    QObject(parent),
    d_ptr(new QBluetoothLocalDevicePrivate(this, address))
{
}

QString QBluetoothLocalDevice::name() const
{
    if (d_ptr->adapter) {
        QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties();
        reply.waitForFinished();
        if (reply.isError())
            return QString();

        return reply.value().value(QStringLiteral("Name")).toString();
    } else if (d_ptr->adapterBluez5) {
        return d_ptr->adapterBluez5->alias();
    }

    return QString();
}

QBluetoothAddress QBluetoothLocalDevice::address() const
{
    if (d_ptr->adapter) {
        QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties();
        reply.waitForFinished();
        if (reply.isError())
            return QBluetoothAddress();

        return QBluetoothAddress(reply.value().value(QStringLiteral("Address")).toString());
    } else if (d_ptr->adapterBluez5) {
        return QBluetoothAddress(d_ptr->adapterBluez5->address());
    }

    return QBluetoothAddress();
}

void QBluetoothLocalDevice::powerOn()
{
    if (d_ptr->adapter)
        d_ptr->adapter->SetProperty(QStringLiteral("Powered"), QDBusVariant(QVariant::fromValue(true)));
    else if (d_ptr->adapterBluez5)
        d_ptr->adapterBluez5->setPowered(true);
}

void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
{
    if (!isValid())
        return;

    Q_D(QBluetoothLocalDevice);

    switch (mode) {
    case HostDiscoverableLimitedInquiry:
    case HostDiscoverable:
        if (hostMode() == HostPoweredOff) {
            // We first have to wait for BT to be powered on,
            // then we can set the host mode correctly
            d->pendingHostModeChange = static_cast<int>(HostDiscoverable);
            if (d->adapter) {
                d->adapter->SetProperty(QStringLiteral("Powered"),
                                        QDBusVariant(QVariant::fromValue(true)));
            } else {
                d->adapterBluez5->setPowered(true);
            }
        } else {
            if (d->adapter) {
                d->adapter->SetProperty(QStringLiteral("Discoverable"),
                                        QDBusVariant(QVariant::fromValue(true)));
            } else {
                d->adapterBluez5->setDiscoverable(true);
            }
        }
        break;
    case HostConnectable:
        if (hostMode() == HostPoweredOff) {
            d->pendingHostModeChange = static_cast<int>(HostConnectable);
            if (d->adapter) {
                d->adapter->SetProperty(QStringLiteral("Powered"),
                                        QDBusVariant(QVariant::fromValue(true)));
            } else {
                d->adapterBluez5->setPowered(true);
            }
        } else {
            if (d->adapter) {
                d->adapter->SetProperty(QStringLiteral("Discoverable"),
                                        QDBusVariant(QVariant::fromValue(false)));
            } else {
                d->adapterBluez5->setDiscoverable(false);
            }
        }
        break;
    case HostPoweredOff:
        if (d->adapter) {
            d->adapter->SetProperty(QStringLiteral("Powered"),
                                    QDBusVariant(QVariant::fromValue(false)));
        } else {
            d->adapterBluez5->setPowered(false);
        }
        break;
    }
}

QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
{
    if (d_ptr->adapter) {
        QDBusPendingReply<QVariantMap> reply = d_ptr->adapter->GetProperties();
        reply.waitForFinished();
        if (reply.isError())
            return HostPoweredOff;

        if (!reply.value().value(QStringLiteral("Powered")).toBool())
            return HostPoweredOff;
        else if (reply.value().value(QStringLiteral("Discoverable")).toBool())
            return HostDiscoverable;
        else if (reply.value().value(QStringLiteral("Powered")).toBool())
            return HostConnectable;
    } else if (d_ptr->adapterBluez5) {
        if (!d_ptr->adapterBluez5->powered())
            return HostPoweredOff;
        else if (d_ptr->adapterBluez5->discoverable())
            return HostDiscoverable;
        else if (d_ptr->adapterBluez5->powered())
            return HostConnectable;
    }

    return HostPoweredOff;
}

QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
{
    return d_ptr->connectedDevices();
}

QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
{
    QList<QBluetoothHostInfo> localDevices;

    if (isBluez5()) {
        OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
                                                         QStringLiteral("/"),
                                                         QDBusConnection::systemBus());
        QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
        reply.waitForFinished();
        if (reply.isError())
            return localDevices;

        ManagedObjectList managedObjectList = reply.value();
        for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
            const InterfaceList &ifaceList = it.value();

            for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
                const QString &iface = jt.key();
                const QVariantMap &ifaceValues = jt.value();

                if (iface == QStringLiteral("org.bluez.Adapter1")) {
                    QBluetoothHostInfo hostInfo;
                    const QString temp = ifaceValues.value(QStringLiteral("Address")).toString();

                    hostInfo.setAddress(QBluetoothAddress(temp));
                    if (hostInfo.address().isNull())
                        continue;
                    hostInfo.setName(ifaceValues.value(QStringLiteral("Name")).toString());
                    localDevices.append(hostInfo);
                }
            }
        }
   } else {
        OrgBluezManagerInterface manager(QStringLiteral("org.bluez"), QStringLiteral("/"),
                                         QDBusConnection::systemBus());

        QDBusPendingReply<QList<QDBusObjectPath> > reply = manager.ListAdapters();
        reply.waitForFinished();
        if (reply.isError())
            return localDevices;

        const QList<QDBusObjectPath> paths = reply.value();
        for (const QDBusObjectPath &path : paths) {
            QBluetoothHostInfo hostinfo;
            OrgBluezAdapterInterface adapter(QStringLiteral("org.bluez"), path.path(),
                                             QDBusConnection::systemBus());

            QDBusPendingReply<QVariantMap> reply = adapter.GetProperties();
            reply.waitForFinished();
            if (reply.isError())
                continue;

            hostinfo.setAddress(QBluetoothAddress(
                                    reply.value().value(QStringLiteral("Address")).toString()));
            hostinfo.setName(reply.value().value(QStringLiteral("Name")).toString());

            localDevices.append(hostinfo);
        }
    }

    return localDevices;
}

static inline OrgBluezDeviceInterface *getDevice(const QBluetoothAddress &address,
                                                 QBluetoothLocalDevicePrivate *d_ptr)
{
    if (!d_ptr || !d_ptr->adapter)
        return nullptr;
    QDBusPendingReply<QDBusObjectPath> reply = d_ptr->adapter->FindDevice(address.toString());
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "reply failed" << reply.error();
        return nullptr;
    }

    QDBusObjectPath path = reply.value();

    return new OrgBluezDeviceInterface(QStringLiteral("org.bluez"), path.path(),
                                       QDBusConnection::systemBus());
}

void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
{
    if (!isValid() || address.isNull()) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QBluetoothLocalDevice::Error,
                                        QBluetoothLocalDevice::PairingError));
        return;
    }

    const Pairing current_pairing = pairingStatus(address);
    if (current_pairing == pairing) {
        if (d_ptr->adapterBluez5) {
            // A possibly running discovery or pending pairing request should be canceled
            if (d_ptr->pairingDiscoveryTimer && d_ptr->pairingDiscoveryTimer->isActive()) {
                d_ptr->pairingDiscoveryTimer->stop();
            }

            if (d_ptr->pairingTarget) {
                qCDebug(QT_BT_BLUEZ) << "Cancelling pending pairing request to" << d_ptr->pairingTarget->address();
                QDBusPendingReply<> cancelReply = d_ptr->pairingTarget->CancelPairing();
                cancelReply.waitForFinished();
                delete d_ptr->pairingTarget;
                d_ptr->pairingTarget = nullptr;
            }

        }
        QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection,
                                  Q_ARG(QBluetoothAddress, address),
                                  Q_ARG(QBluetoothLocalDevice::Pairing, pairing));
        return;
    }

    if (d_ptr->adapterBluez5) {
        d_ptr->requestPairingBluez5(address, pairing);
        return;
    }

    if (pairing == Paired || pairing == AuthorizedPaired) {
        d_ptr->address = address;
        d_ptr->pairing = pairing;

        if (!d_ptr->agent) {
            d_ptr->agent = new OrgBluezAgentAdaptor(d_ptr);
            bool res = QDBusConnection::systemBus().registerObject(d_ptr->agent_path, d_ptr);
            if (!res) {
                QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                          Q_ARG(QBluetoothLocalDevice::Error,
                                                QBluetoothLocalDevice::PairingError));
                qCWarning(QT_BT_BLUEZ) << "Failed to register agent";
                return;
            }
        }

        if (current_pairing == Paired && pairing == AuthorizedPaired) {
            OrgBluezDeviceInterface *device = getDevice(address, d_ptr);
            if (!device) {
                QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                          Q_ARG(QBluetoothLocalDevice::Error,
                                                QBluetoothLocalDevice::PairingError));
                return;
            }
            QDBusPendingReply<> deviceReply
                = device->SetProperty(QStringLiteral("Trusted"), QDBusVariant(true));
            deviceReply.waitForFinished();
            if (deviceReply.isError()) {
                qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "reply failed" << deviceReply.error();
                QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                          Q_ARG(QBluetoothLocalDevice::Error,
                                                QBluetoothLocalDevice::PairingError));
                delete device;
                return;
            }
            delete device;
            QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection,
                                      Q_ARG(QBluetoothAddress, address),
                                      Q_ARG(QBluetoothLocalDevice::Pairing,
                                            QBluetoothLocalDevice::AuthorizedPaired));
        } else if (current_pairing == AuthorizedPaired && pairing == Paired) {
            OrgBluezDeviceInterface *device = getDevice(address, d_ptr);
            if (!device) {
                QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                          Q_ARG(QBluetoothLocalDevice::Error,
                                                QBluetoothLocalDevice::PairingError));
                return;
            }
            QDBusPendingReply<> deviceReply
                = device->SetProperty(QStringLiteral("Trusted"), QDBusVariant(false));
            deviceReply.waitForFinished();
            if (deviceReply.isError()) {
                qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "reply failed" << deviceReply.error();
                QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                          Q_ARG(QBluetoothLocalDevice::Error,
                                                QBluetoothLocalDevice::PairingError));
                delete device;
                return;
            }
            delete device;
            QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection,
                                      Q_ARG(QBluetoothAddress, address),
                                      Q_ARG(QBluetoothLocalDevice::Pairing,
                                            QBluetoothLocalDevice::Paired));
        } else {
            QDBusPendingReply<QDBusObjectPath> reply
                = d_ptr->adapter->CreatePairedDevice(address.toString(),
                                                     QDBusObjectPath(d_ptr->agent_path),
                                                     QStringLiteral("NoInputNoOutput"));

            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
            connect(watcher, &QDBusPendingCallWatcher::finished,
                    d_ptr, &QBluetoothLocalDevicePrivate::pairingCompleted);

            if (reply.isError())
                qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << reply.error() << d_ptr->agent_path;
        }
    } else if (pairing == Unpaired) {
        QDBusPendingReply<QDBusObjectPath> reply = this->d_ptr->adapter->FindDevice(
            address.toString());
        reply.waitForFinished();
        if (reply.isError()) {
            qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "failed to find device" << reply.error();
            QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                      Q_ARG(QBluetoothLocalDevice::Error,
                                            QBluetoothLocalDevice::PairingError));
            return;
        }
        QDBusPendingReply<> removeReply = this->d_ptr->adapter->RemoveDevice(reply.value());
        removeReply.waitForFinished();
        if (removeReply.isError()) {
            qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "failed to remove device"
                                   << removeReply.error();
            QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                      Q_ARG(QBluetoothLocalDevice::Error,
                                            QBluetoothLocalDevice::PairingError));
        } else {
            QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection,
                                      Q_ARG(QBluetoothAddress, address),
                                      Q_ARG(QBluetoothLocalDevice::Pairing,
                                            QBluetoothLocalDevice::Unpaired));
        }
    }
}

void QBluetoothLocalDevicePrivate::requestPairingBluez5(const QBluetoothAddress &targetAddress,
                                                        QBluetoothLocalDevice::Pairing targetPairing)
{
    if (!managerBluez5)
        return;

    //are we already discovering something? -> abort those attempts
    if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) {
        pairingDiscoveryTimer->stop();
        QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(
                    adapterBluez5->path());
    }

    if (pairingTarget) {
        delete pairingTarget;
        pairingTarget = nullptr;
    }

    // pairing implies that the device was found
    // if we cannot find it we may have to turn on Discovery mode for a limited amount of time

    // check device doesn't already exist
    QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
    reply.waitForFinished();
    if (reply.isError()) {
        emit q_ptr->error(QBluetoothLocalDevice::PairingError);
        return;
    }

    ManagedObjectList managedObjectList = reply.value();
    for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
        const QDBusObjectPath &path = it.key();
        const InterfaceList &ifaceList = it.value();

        for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
            const QString &iface = jt.key();

            if (iface == QStringLiteral("org.bluez.Device1")) {

                OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
                                                path.path(),
                                                QDBusConnection::systemBus());
                if (targetAddress == QBluetoothAddress(device.address())) {
                    qCDebug(QT_BT_BLUEZ) << "Initiating direct pair to" << targetAddress.toString();
                    //device exist -> directly work with it
                    processPairingBluez5(path.path(), targetPairing);
                    return;
                }
            }
        }
    }

    //no device matching -> turn on discovery
    QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapterBluez5->path());

    address = targetAddress;
    pairing = targetPairing;
    if (!pairingDiscoveryTimer) {
        pairingDiscoveryTimer = new QTimer(this);
        pairingDiscoveryTimer->setSingleShot(true);
        pairingDiscoveryTimer->setInterval(20000); //20s
        connect(pairingDiscoveryTimer, &QTimer::timeout,
                this, &QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut);
    }

    qCDebug(QT_BT_BLUEZ) << "Initiating discovery for pairing on" << targetAddress.toString();
    pairingDiscoveryTimer->start();
}

/*!
 * \internal
 *
 * Found a matching device. Now we must ensure its pairing/trusted state is as desired.
 * If it has to be paired then we need another roundtrip through the event loop
 * while we wait for the user to accept the pairing dialogs.
 */
void QBluetoothLocalDevicePrivate::processPairingBluez5(const QString &objectPath,
                                                        QBluetoothLocalDevice::Pairing target)
{
    if (pairingTarget)
        delete pairingTarget;

    //stop possibly running discovery
    if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) {
        pairingDiscoveryTimer->stop();

        QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(
                    adapterBluez5->path());
    }

    pairingTarget = new OrgBluezDevice1Interface(QStringLiteral("org.bluez"), objectPath,
                                                 QDBusConnection::systemBus(), this);
    const QBluetoothAddress targetAddress(pairingTarget->address());

    Q_Q(QBluetoothLocalDevice);

    switch (target) {
    case QBluetoothLocalDevice::Unpaired: {
        delete pairingTarget;
        pairingTarget = nullptr;

        QDBusPendingReply<> removeReply = adapterBluez5->RemoveDevice(QDBusObjectPath(objectPath));
        auto watcher = new QDBusPendingCallWatcher(removeReply, this);
        connect(watcher, &QDBusPendingCallWatcher::finished,
                this, [q, targetAddress](QDBusPendingCallWatcher* watcher){
            QDBusPendingReply<> reply = *watcher;
            if (reply.isError())
                emit q->error(QBluetoothLocalDevice::PairingError);
            else
                emit q->pairingFinished(targetAddress, QBluetoothLocalDevice::Unpaired);

            watcher->deleteLater();
        });
        break;
    }
    case QBluetoothLocalDevice::Paired:
    case QBluetoothLocalDevice::AuthorizedPaired:
        pairing = target;

        if (!pairingTarget->paired()) {
            qCDebug(QT_BT_BLUEZ) << "Sending pairing request to" << pairingTarget->address();
            //initiate the pairing
            QDBusPendingReply<> pairReply = pairingTarget->Pair();
            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pairReply, this);
            connect(watcher, &QDBusPendingCallWatcher::finished,
                    this, &QBluetoothLocalDevicePrivate::pairingCompleted);
            return;
        }

        //already paired but Trust level must be adjusted
        if (target == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted())
            pairingTarget->setTrusted(true);
        else if (target == QBluetoothLocalDevice::Paired && pairingTarget->trusted())
            pairingTarget->setTrusted(false);

        delete pairingTarget;
        pairingTarget = nullptr;

        emit q->pairingFinished(targetAddress, target);

        break;
    default:
        break;
    }
}

void QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut()
{
    qCWarning(QT_BT_BLUEZ) << "Discovery for pairing purposes failed. Cannot find parable device.";

    QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(
                adapterBluez5->path());

    emit q_ptr->error(QBluetoothLocalDevice::PairingError);
}

QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
    const QBluetoothAddress &address) const
{
    if (address.isNull())
        return Unpaired;

    if (d_ptr->adapter) {
        OrgBluezDeviceInterface *device = getDevice(address, d_ptr);

        if (!device)
            return Unpaired;

        QDBusPendingReply<QVariantMap> deviceReply = device->GetProperties();
        deviceReply.waitForFinished();
        if (deviceReply.isError()) {
            delete device;
            return Unpaired;
        }

        QVariantMap map = deviceReply.value();

        if (map.value(QStringLiteral("Trusted")).toBool() && map.value(QStringLiteral("Paired")).toBool()) {
            delete device;
            return AuthorizedPaired;
        } else if (map.value(QStringLiteral("Paired")).toBool()) {
            delete device;
            return Paired;
        }
        delete device;
    } else if (d_ptr->adapterBluez5) {

        QDBusPendingReply<ManagedObjectList> reply = d_ptr->managerBluez5->GetManagedObjects();
        reply.waitForFinished();
        if (reply.isError())
            return Unpaired;

        ManagedObjectList managedObjectList = reply.value();
        for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
            const QDBusObjectPath &path = it.key();
            const InterfaceList &ifaceList = it.value();

            for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
                const QString &iface = jt.key();

                if (iface == QStringLiteral("org.bluez.Device1")) {

                    OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
                                                    path.path(),
                                                    QDBusConnection::systemBus());

                    if (address == QBluetoothAddress(device.address())) {
                        if (device.trusted() && device.paired())
                            return AuthorizedPaired;
                        else if (device.paired())
                            return Paired;
                        else
                            return Unpaired;
                    }
                }
            }
        }
    }

    return Unpaired;
}

QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q,
                                                           QBluetoothAddress address) :
        localAddress(address),
        pendingHostModeChange(-1),
        q_ptr(q)
{
    registerQBluetoothLocalDeviceMetaType();

    if (isBluez5())
        initializeAdapterBluez5();
    else
        initializeAdapter();

    connectDeviceChanges();
}

bool objectPathIsForThisDevice(const QString &adapterPath, const QString &objectPath)
{
    return (!adapterPath.isEmpty() && objectPath.startsWith(adapterPath));
}

void QBluetoothLocalDevicePrivate::connectDeviceChanges()
{
    if (adapter) { // invalid QBluetoothLocalDevice due to wrong local adapter address
        createCache();
        connect(adapter, &OrgBluezAdapterInterface::PropertyChanged,
                this, &QBluetoothLocalDevicePrivate::PropertyChanged);
        connect(adapter, &OrgBluezAdapterInterface::DeviceCreated,
                this, &QBluetoothLocalDevicePrivate::_q_deviceCreated);
        connect(adapter, &OrgBluezAdapterInterface::DeviceRemoved,
                this, &QBluetoothLocalDevicePrivate::_q_deviceRemoved);
    } else if (adapterBluez5 && managerBluez5) {
        //setup property change notifications for all existing devices
        QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
        reply.waitForFinished();
        if (reply.isError())
            return;

        OrgFreedesktopDBusPropertiesInterface *monitor = nullptr;

        ManagedObjectList managedObjectList = reply.value();
        for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
            const QDBusObjectPath &path = it.key();
            const InterfaceList &ifaceList = it.value();

            // don't track connected devices from other adapters but the current
            if (!objectPathIsForThisDevice(deviceAdapterPath, path.path()))
                continue;

            for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
                const QString &iface = jt.key();
                const QVariantMap &ifaceValues = jt.value();

                if (iface == QStringLiteral("org.bluez.Device1")) {
                    monitor = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.bluez"),
                                                                        path.path(),
                                                                        QDBusConnection::systemBus(), this);
                    connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
                            this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
                    deviceChangeMonitors.insert(path.path(), monitor);

                    if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) {
                        QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString());
                        connectedDevicesSet.insert(address);
                    }
                }
            }
        }
    }
}

QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
{
    delete msgConnection;
    delete adapter;
    delete adapterBluez5;
    delete adapterProperties;
    delete managerBluez5;
    delete agent;
    delete pairingTarget;
    delete manager;

    qDeleteAll(devices);
    qDeleteAll(deviceChangeMonitors);
}

void QBluetoothLocalDevicePrivate::initializeAdapter()
{
    if (adapter)
        return;

    QScopedPointer<OrgBluezManagerInterface> man(new OrgBluezManagerInterface(
                            QStringLiteral("org.bluez"), QStringLiteral("/"),
                            QDBusConnection::systemBus()));

    if (localAddress == QBluetoothAddress()) {
        QDBusPendingReply<QDBusObjectPath> reply = man->DefaultAdapter();
        reply.waitForFinished();
        if (reply.isError())
            return;

        adapter = new OrgBluezAdapterInterface(QStringLiteral("org.bluez"),
                                               reply.value().path(), QDBusConnection::systemBus());
    } else {
        QDBusPendingReply<QList<QDBusObjectPath> > reply = man->ListAdapters();
        reply.waitForFinished();
        if (reply.isError())
            return;

        const QList<QDBusObjectPath> paths = reply.value();
        for (const QDBusObjectPath &path : paths) {
            OrgBluezAdapterInterface *tmpAdapter
                = new OrgBluezAdapterInterface(QStringLiteral("org.bluez"),
                                               path.path(), QDBusConnection::systemBus());

            QDBusPendingReply<QVariantMap> reply = tmpAdapter->GetProperties();
            reply.waitForFinished();
            if (reply.isError()) {
                delete tmpAdapter;
                continue;
            }

            QBluetoothAddress path_address(reply.value().value(QStringLiteral("Address")).toString());

            if (path_address == localAddress) {
                adapter = tmpAdapter;
                break;
            } else {
                delete tmpAdapter;
            }
        }
    }

    // monitor case when local adapter is removed
    manager = man.take();
    connect(manager, &OrgBluezManagerInterface::AdapterRemoved,
            this, &QBluetoothLocalDevicePrivate::adapterRemoved);

    currentMode = static_cast<QBluetoothLocalDevice::HostMode>(-1);
    if (adapter) {
        connect(adapter, &OrgBluezAdapterInterface::PropertyChanged,
                this, &QBluetoothLocalDevicePrivate::PropertyChanged);

        agent_path = agentPath;
        agent_path.append(QString::fromLatin1("/%1").arg(QRandomGenerator::global()->generate()));
    }
}

void QBluetoothLocalDevicePrivate::initializeAdapterBluez5()
{
    if (adapterBluez5)
        return;

    //get all local adapters
    if (!managerBluez5)
        managerBluez5 = new OrgFreedesktopDBusObjectManagerInterface(
                                                     QStringLiteral("org.bluez"),
                                                     QStringLiteral("/"),
                                                     QDBusConnection::systemBus(), this);

    connect(managerBluez5, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded,
            this, &QBluetoothLocalDevicePrivate::InterfacesAdded);
    connect(managerBluez5, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
            this, &QBluetoothLocalDevicePrivate::InterfacesRemoved);

    bool ok = true;
    const QString adapterPath = findAdapterForAddress(localAddress, &ok);
    if (!ok || adapterPath.isEmpty())
        return;

    deviceAdapterPath = adapterPath;
    adapterBluez5 = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
                                                   adapterPath,
                                                   QDBusConnection::systemBus(), this);

    if (adapterBluez5) {
        //hook up propertiesChanged for current adapter
        adapterProperties = new OrgFreedesktopDBusPropertiesInterface(
                    QStringLiteral("org.bluez"), adapterBluez5->path(),
                    QDBusConnection::systemBus(), this);
        connect(adapterProperties, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
                this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
    }

    currentMode = static_cast<QBluetoothLocalDevice::HostMode>(-1);
}

// Bluez 5
void QBluetoothLocalDevicePrivate::PropertiesChanged(const QString &interface,
                                                     const QVariantMap &changed_properties,
                                                     const QStringList &/*invalidated_properties*/,
                                                     const QDBusMessage &)
{
    //qDebug() << "Change" << interface << changed_properties;
    if (interface == QStringLiteral("org.bluez.Adapter1")) {
        //update host mode
        if (changed_properties.contains(QStringLiteral("Discoverable"))
                || changed_properties.contains(QStringLiteral("Powered"))) {

            QBluetoothLocalDevice::HostMode mode;

            if (!adapterBluez5->powered()) {
                mode = QBluetoothLocalDevice::HostPoweredOff;
            } else {
                if (adapterBluez5->discoverable())
                    mode = QBluetoothLocalDevice::HostDiscoverable;
                else
                    mode = QBluetoothLocalDevice::HostConnectable;

                if (pendingHostModeChange != -1) {

                    if (static_cast<int>(mode) != pendingHostModeChange) {
                        adapterBluez5->setDiscoverable(
                            pendingHostModeChange
                            == static_cast<int>(QBluetoothLocalDevice::HostDiscoverable));
                        pendingHostModeChange = -1;
                        return;
                    }
                    pendingHostModeChange = -1;
                }
            }

            if (mode != currentMode)
                emit q_ptr->hostModeStateChanged(mode);

            currentMode = mode;
        }
    } else if (interface == QStringLiteral("org.bluez.Device1")
               && changed_properties.contains(QStringLiteral("Connected"))) {
        // update list of connected devices
        OrgFreedesktopDBusPropertiesInterface *senderIface =
                qobject_cast<OrgFreedesktopDBusPropertiesInterface*>(sender());
        if (!senderIface)
            return;

        const QString currentPath = senderIface->path();
        bool isConnected = changed_properties.value(QStringLiteral("Connected"), false).toBool();
        OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), currentPath,
                                        QDBusConnection::systemBus());
        const QBluetoothAddress changedAddress(device.address());
        bool isInSet = connectedDevicesSet.contains(changedAddress);
        if (isConnected && !isInSet) {
            connectedDevicesSet.insert(changedAddress);
            emit q_ptr->deviceConnected(changedAddress);
        } else if (!isConnected && isInSet) {
            connectedDevicesSet.remove(changedAddress);
            emit q_ptr->deviceDisconnected(changedAddress);
        }
    }
}

void QBluetoothLocalDevicePrivate::InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties)
{
    if (interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))
        && !deviceChangeMonitors.contains(object_path.path())) {
        // a new device was added which we need to add to list of known devices

        if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) {
            OrgFreedesktopDBusPropertiesInterface *monitor = new OrgFreedesktopDBusPropertiesInterface(
                                               QStringLiteral("org.bluez"),
                                               object_path.path(),
                                               QDBusConnection::systemBus());
            connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
                    this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
            deviceChangeMonitors.insert(object_path.path(), monitor);

            const QVariantMap ifaceValues = interfaces_and_properties.value(QStringLiteral("org.bluez.Device1"));
            if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) {
                QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString());
                connectedDevicesSet.insert(address);
                emit q_ptr->deviceConnected(address);
            }
        }
    }

    if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()
        && interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))) {
        //device discovery for pairing found new remote device
        OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
                                        object_path.path(), QDBusConnection::systemBus());
        if (!address.isNull() && address == QBluetoothAddress(device.address()))
            processPairingBluez5(object_path.path(), pairing);
    }
}

void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &object_path,
                                                     const QStringList &interfaces)
{
    if (deviceChangeMonitors.contains(object_path.path())
            && interfaces.contains(QLatin1String("org.bluez.Device1"))) {

        if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) {
            //a device was removed
            delete deviceChangeMonitors.take(object_path.path());

            //the path contains the address (e.g.: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX)
            //-> use it to update current list of connected devices
            QString addressString = object_path.path().right(17);
            addressString.replace(QStringLiteral("_"), QStringLiteral(":"));
            const QBluetoothAddress address(addressString);
            bool found = connectedDevicesSet.remove(address);
            if (found)
                emit q_ptr->deviceDisconnected(address);
        }
    }

    if (adapterBluez5
            && object_path.path() == adapterBluez5->path()
            && interfaces.contains(QLatin1String("org.bluez.Adapter1"))) {
        qCDebug(QT_BT_BLUEZ) << "Adapter" << adapterBluez5->path() << "was removed";
        // current adapter was removed -> invalidate the instance
        delete adapterBluez5;
        adapterBluez5 = nullptr;
        managerBluez5->deleteLater();
        managerBluez5 = nullptr;
        delete adapterProperties;
        adapterProperties = nullptr;

        delete pairingTarget;
        pairingTarget = nullptr;

        // turn  off connectivity monitoring
        qDeleteAll(deviceChangeMonitors);
        deviceChangeMonitors.clear();
        connectedDevicesSet.clear();
    }
}

bool QBluetoothLocalDevicePrivate::isValid() const
{
    return adapter || adapterBluez5;
}

// Bluez 4
void QBluetoothLocalDevicePrivate::adapterRemoved(const QDBusObjectPath &devicePath)
{
    if (!adapter )
        return;

    if (adapter->path() != devicePath.path())
        return;

    qCDebug(QT_BT_BLUEZ) << "Adapter" << devicePath.path()
                         << "was removed. Invalidating object.";
    // the current adapter was removed
    delete adapter;
    adapter = nullptr;
    manager->deleteLater();
    manager = nullptr;

    // stop all pairing related activities
    if (agent) {
        QDBusConnection::systemBus().unregisterObject(agent_path);
        delete agent;
        agent = nullptr;
    }

    delete msgConnection;
    msgConnection = nullptr;

    // stop all connectivity monitoring
    qDeleteAll(devices);
    devices.clear();
    connectedDevicesSet.clear();
}

void QBluetoothLocalDevicePrivate::RequestConfirmation(const QDBusObjectPath &in0, uint in1)
{
    Q_UNUSED(in0);
    Q_Q(QBluetoothLocalDevice);
    setDelayedReply(true);
    msgConfirmation = message();
    msgConnection = new QDBusConnection(connection());
    emit q->pairingDisplayConfirmation(address, QString::fromLatin1("%1").arg(in1));
}

void QBluetoothLocalDevicePrivate::_q_deviceCreated(const QDBusObjectPath &device)
{
    OrgBluezDeviceInterface *deviceInterface
        = new OrgBluezDeviceInterface(QStringLiteral("org.bluez"),
                                      device.path(),
                                      QDBusConnection::systemBus(), this);
    connect(deviceInterface, &OrgBluezDeviceInterface::PropertyChanged,
            this, &QBluetoothLocalDevicePrivate::_q_devicePropertyChanged);
    devices << deviceInterface;
    QDBusPendingReply<QVariantMap> properties
        = deviceInterface->asyncCall(QStringLiteral("GetProperties"));

    properties.waitForFinished();
    if (!properties.isValid()) {
        qCritical() << "Unable to get device properties from: " << device.path();
        return;
    }
    const QBluetoothAddress address
        = QBluetoothAddress(properties.value().value(QStringLiteral("Address")).toString());
    const bool connected = properties.value().value(QStringLiteral("Connected")).toBool();

    if (connected) {
        connectedDevicesSet.insert(address);
        emit q_ptr->deviceConnected(address);
    } else {
        connectedDevicesSet.remove(address);
        emit q_ptr->deviceDisconnected(address);
    }
}

void QBluetoothLocalDevicePrivate::_q_deviceRemoved(const QDBusObjectPath &device)
{
    for (OrgBluezDeviceInterface *deviceInterface : qAsConst(devices)) {
        if (deviceInterface->path() == device.path()) {
            devices.remove(deviceInterface);
            delete deviceInterface; // deviceDisconnected is already emitted by _q_devicePropertyChanged
            break;
        }
    }
}

void QBluetoothLocalDevicePrivate::_q_devicePropertyChanged(const QString &property,
                                                            const QDBusVariant &value)
{
    OrgBluezDeviceInterface *deviceInterface = qobject_cast<OrgBluezDeviceInterface *>(sender());
    if (deviceInterface && property == QLatin1String("Connected")) {
        QDBusPendingReply<QVariantMap> propertiesReply = deviceInterface->GetProperties();
        propertiesReply.waitForFinished();
        if (propertiesReply.isError()) {
            qCWarning(QT_BT_BLUEZ) << propertiesReply.error().message();
            return;
        }
        const QVariantMap properties = propertiesReply.value();
        const QBluetoothAddress address
            = QBluetoothAddress(properties.value(QStringLiteral("Address")).toString());
        const bool connected = value.variant().toBool();

        if (connected) {
            connectedDevicesSet.insert(address);
            emit q_ptr->deviceConnected(address);
        } else {
            connectedDevicesSet.remove(address);
            emit q_ptr->deviceDisconnected(address);
        }
    }
}

void QBluetoothLocalDevicePrivate::createCache()
{
    if (!adapter)
        return;

    QDBusPendingReply<QList<QDBusObjectPath> > reply = adapter->ListDevices();
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << reply.error().message();
        return;
    }
    const QList<QDBusObjectPath> knownDevices = reply.value();
    for (const QDBusObjectPath &device : knownDevices) {
        OrgBluezDeviceInterface *deviceInterface =
                new OrgBluezDeviceInterface(QStringLiteral("org.bluez"),
                                            device.path(),
                                            QDBusConnection::systemBus(), this);
        connect(deviceInterface, &OrgBluezDeviceInterface::PropertyChanged,
                this, &QBluetoothLocalDevicePrivate::_q_devicePropertyChanged);
        devices << deviceInterface;

        QDBusPendingReply<QVariantMap> properties
            = deviceInterface->asyncCall(QStringLiteral("GetProperties"));
        properties.waitForFinished();
        if (!properties.isValid()) {
            qCWarning(QT_BT_BLUEZ) << "Unable to get properties for device " << device.path();
            return;
        }

        if (properties.value().value(QStringLiteral("Connected")).toBool()) {
            connectedDevicesSet.insert(
                QBluetoothAddress(properties.value().value(QStringLiteral("Address")).toString()));
        }
    }
}

QList<QBluetoothAddress> QBluetoothLocalDevicePrivate::connectedDevices() const
{
    return connectedDevicesSet.values();
}

void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
{
    if (!d_ptr
        || !d_ptr->msgConfirmation.isReplyRequired()
        || !d_ptr->msgConnection)
        return;

    if (confirmation) {
        QDBusMessage msg = d_ptr->msgConfirmation.createReply(QVariant(true));
        d_ptr->msgConnection->send(msg);
    } else {
        QDBusMessage error
            = d_ptr->msgConfirmation.createErrorReply(QDBusError::AccessDenied,
                                                      QStringLiteral("Pairing rejected"));
        d_ptr->msgConnection->send(error);
    }
    delete d_ptr->msgConnection;
    d_ptr->msgConnection = nullptr;
}

QString QBluetoothLocalDevicePrivate::RequestPinCode(const QDBusObjectPath &in0)
{
    Q_UNUSED(in0)
    Q_Q(QBluetoothLocalDevice);
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << in0.path();
    // seeded in constructor, 6 digit pin
    QString pin = QString::fromLatin1("%1").arg(QRandomGenerator::global()->bounded(1000000));
    pin = QString::fromLatin1("%1").arg(pin, 6, QLatin1Char('0'));

    emit q->pairingDisplayPinCode(address, pin);
    return pin;
}

void QBluetoothLocalDevicePrivate::pairingCompleted(QDBusPendingCallWatcher *watcher)
{
    Q_Q(QBluetoothLocalDevice);
    QDBusPendingReply<> reply = *watcher;

    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Failed to create pairing" << reply.error().name();
        if (reply.error().name() != QStringLiteral("org.bluez.Error.AuthenticationCanceled"))
            emit q->error(QBluetoothLocalDevice::PairingError);
        watcher->deleteLater();
        return;
    }

    if (adapter) {
        QDBusPendingReply<QDBusObjectPath> findReply = adapter->FindDevice(address.toString());
        findReply.waitForFinished();
        if (findReply.isError()) {
            qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << "failed to find device" << findReply.error();
            emit q->error(QBluetoothLocalDevice::PairingError);
            watcher->deleteLater();
            return;
        }

        OrgBluezDeviceInterface device(QStringLiteral("org.bluez"), findReply.value().path(),
                                       QDBusConnection::systemBus());

        if (pairing == QBluetoothLocalDevice::AuthorizedPaired) {
            device.SetProperty(QStringLiteral("Trusted"), QDBusVariant(QVariant(true)));
            emit q->pairingFinished(address, QBluetoothLocalDevice::AuthorizedPaired);
        }
        else {
            device.SetProperty(QStringLiteral("Trusted"), QDBusVariant(QVariant(false)));
            emit q->pairingFinished(address, QBluetoothLocalDevice::Paired);
        }
    } else if (adapterBluez5) {
        if (!pairingTarget) {
            qCWarning(QT_BT_BLUEZ) << "Pairing target expected but found null pointer.";
            emit q->error(QBluetoothLocalDevice::PairingError);
            watcher->deleteLater();
            return;
        }

        if (!pairingTarget->paired()) {
            qCWarning(QT_BT_BLUEZ) << "Device was not paired as requested";
            emit q->error(QBluetoothLocalDevice::PairingError);
            watcher->deleteLater();
            return;
        }

        const QBluetoothAddress targetAddress(pairingTarget->address());

        if (pairing == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted())
            pairingTarget->setTrusted(true);
        else if (pairing == QBluetoothLocalDevice::Paired && pairingTarget->trusted())
            pairingTarget->setTrusted(false);

        delete pairingTarget;
        pairingTarget = nullptr;

        emit q->pairingFinished(targetAddress, pairing);
    }

    watcher->deleteLater();
}

void QBluetoothLocalDevicePrivate::Authorize(const QDBusObjectPath &in0, const QString &in1)
{
    Q_UNUSED(in0)
    Q_UNUSED(in1)
    // TODO implement this
    qCDebug(QT_BT_BLUEZ) << "Got authorize for" << in0.path() << in1;
}

void QBluetoothLocalDevicePrivate::Cancel()
{
    // TODO implement this
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
}

void QBluetoothLocalDevicePrivate::Release()
{
    // TODO implement this
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
}

void QBluetoothLocalDevicePrivate::ConfirmModeChange(const QString &in0)
{
    Q_UNUSED(in0)
    // TODO implement this
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << in0;
}

void QBluetoothLocalDevicePrivate::DisplayPasskey(const QDBusObjectPath &in0, uint in1, uchar in2)
{
    Q_UNUSED(in0)
    Q_UNUSED(in1)
    Q_UNUSED(in2)
    // TODO implement this
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << in0.path() << in1 << in2;
}

uint QBluetoothLocalDevicePrivate::RequestPasskey(const QDBusObjectPath &in0)
{
    Q_UNUSED(in0);
    qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
    return (QRandomGenerator::global()->bounded(1000000));
}

// Bluez 4
void QBluetoothLocalDevicePrivate::PropertyChanged(QString property, QDBusVariant value)
{
    Q_UNUSED(value);

    if (property != QLatin1String("Powered")
        && property != QLatin1String("Discoverable"))
        return;

    Q_Q(QBluetoothLocalDevice);
    QBluetoothLocalDevice::HostMode mode;

    QDBusPendingReply<QVariantMap> reply = adapter->GetProperties();
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Failed to get bluetooth properties for mode change";
        return;
    }

    QVariantMap map = reply.value();

    if (!map.value(QStringLiteral("Powered")).toBool()) {
        mode = QBluetoothLocalDevice::HostPoweredOff;
    } else {
        if (map.value(QStringLiteral("Discoverable")).toBool())
            mode = QBluetoothLocalDevice::HostDiscoverable;
        else
            mode = QBluetoothLocalDevice::HostConnectable;

        if (pendingHostModeChange != -1) {
            if ((int)mode != pendingHostModeChange) {
                if (property == QStringLiteral("Powered"))
                    return;
                if (pendingHostModeChange == (int)QBluetoothLocalDevice::HostDiscoverable) {
                    adapter->SetProperty(QStringLiteral("Discoverable"),
                                         QDBusVariant(QVariant::fromValue(true)));
                } else {
                    adapter->SetProperty(QStringLiteral("Discoverable"),
                                         QDBusVariant(QVariant::fromValue(false)));
                }
                pendingHostModeChange = -1;
                return;
            }
        }
    }

    if (mode != currentMode)
        emit q->hostModeStateChanged(mode);

    currentMode = mode;
}

#include "moc_qbluetoothlocaldevice_p.cpp"

QT_END_NAMESPACE
