/****************************************************************************
**
** Copyright (C) 2016 Lauri Laanmets (Proekspert AS) <lauri.laanmets@eesti.ee>
** 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/private/qjnihelpers_p.h>
#include <QtAndroidExtras/QAndroidJniEnvironment>
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtBluetooth/QBluetoothAddress>

#include "qbluetoothlocaldevice_p.h"
#include "android/localdevicebroadcastreceiver_p.h"

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)

QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(
    QBluetoothLocalDevice *q, const QBluetoothAddress &address) :
    q_ptr(q)
{
    registerQBluetoothLocalDeviceMetaType();

    initialize(address);

    receiver = new LocalDeviceBroadcastReceiver(q_ptr);
    connect(receiver, &LocalDeviceBroadcastReceiver::hostModeStateChanged,
            this, &QBluetoothLocalDevicePrivate::processHostModeChange);
    connect(receiver, &LocalDeviceBroadcastReceiver::pairingStateChanged,
            this, &QBluetoothLocalDevicePrivate::processPairingStateChanged);
    connect(receiver, &LocalDeviceBroadcastReceiver::connectDeviceChanges,
            this, &QBluetoothLocalDevicePrivate::processConnectDeviceChanges);
    connect(receiver, &LocalDeviceBroadcastReceiver::pairingDisplayConfirmation,
            this, &QBluetoothLocalDevicePrivate::processDisplayConfirmation);
}

QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
{
    receiver->unregisterReceiver();
    delete receiver;
    delete obj;
}

QAndroidJniObject *QBluetoothLocalDevicePrivate::adapter()
{
    return obj;
}

static QAndroidJniObject getDefaultAdapter()
{
    QAndroidJniObject adapter = QAndroidJniObject::callStaticObjectMethod(
                                    "android/bluetooth/BluetoothAdapter", "getDefaultAdapter",
                                    "()Landroid/bluetooth/BluetoothAdapter;");
    QAndroidJniExceptionCleaner exCleaner{QAndroidJniExceptionCleaner::OutputMode::Verbose};
    if (!adapter.isValid()) {
        exCleaner.clean();

        // workaround stupid bt implementations where first call of BluetoothAdapter.getDefaultAdapter() always fails
        adapter = QAndroidJniObject::callStaticObjectMethod(
                                            "android/bluetooth/BluetoothAdapter", "getDefaultAdapter",
                                            "()Landroid/bluetooth/BluetoothAdapter;");
        if (!adapter.isValid())
            exCleaner.clean();
    }
    return adapter;
}

void QBluetoothLocalDevicePrivate::initialize(const QBluetoothAddress &address)
{
    QAndroidJniObject adapter = getDefaultAdapter();
    if (!adapter.isValid()) {
        qCWarning(QT_BT_ANDROID) <<  "Device does not support Bluetooth";
        return;
    }

    obj = new QAndroidJniObject(adapter);
    if (!address.isNull()) {
        const QString localAddress
            = obj->callObjectMethod("getAddress", "()Ljava/lang/String;").toString();
        if (localAddress != address.toString()) {
            // passed address not local one -> invalid
            delete obj;
            obj = nullptr;
        }
    }
}

bool QBluetoothLocalDevicePrivate::isValid() const
{
    return obj ? true : false;
}

void QBluetoothLocalDevicePrivate::processHostModeChange(QBluetoothLocalDevice::HostMode newMode)
{
    if (!pendingHostModeTransition) {
        // if not in transition -> pass data on
        emit q_ptr->hostModeStateChanged(newMode);
        return;
    }

    if (isValid() && newMode == QBluetoothLocalDevice::HostPoweredOff) {
        bool success = (bool)obj->callMethod<jboolean>("enable", "()Z");
        if (!success)
            emit q_ptr->error(QBluetoothLocalDevice::UnknownError);
    }

    pendingHostModeTransition = false;
}

// Return -1 if address is not part of a pending pairing request
// Otherwise it returns the index of address in pendingPairings
int QBluetoothLocalDevicePrivate::pendingPairing(const QBluetoothAddress &address)
{
    for (int i = 0; i < pendingPairings.count(); i++) {
        if (pendingPairings.at(i).first == address)
            return i;
    }

    return -1;
}

void QBluetoothLocalDevicePrivate::processPairingStateChanged(
    const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
{
    int index = pendingPairing(address);

    if (index < 0)
        return; // ignore unrelated pairing signals

    QPair<QBluetoothAddress, bool> entry = pendingPairings.takeAt(index);
    if ((entry.second && pairing == QBluetoothLocalDevice::Paired)
        || (!entry.second && pairing == QBluetoothLocalDevice::Unpaired)) {
        emit q_ptr->pairingFinished(address, pairing);
    } else {
        emit q_ptr->error(QBluetoothLocalDevice::PairingError);
    }
}

void QBluetoothLocalDevicePrivate::processConnectDeviceChanges(const QBluetoothAddress &address,
                                                               bool isConnectEvent)
{
    int index = -1;
    for (int i = 0; i < connectedDevices.count(); i++) {
        if (connectedDevices.at(i) == address) {
            index = i;
            break;
        }
    }

    if (isConnectEvent) { // connect event
        if (index >= 0)
            return;
        connectedDevices.append(address);
        emit q_ptr->deviceConnected(address);
    } else { // disconnect event
        connectedDevices.removeAll(address);
        emit q_ptr->deviceDisconnected(address);
    }
}

void QBluetoothLocalDevicePrivate::processDisplayConfirmation(const QBluetoothAddress &address,
                                                              const QString &pin)
{
    // only send pairing notification for pairing requests issued by
    // this QBluetoothLocalDevice instance
    if (pendingPairing(address) == -1)
        return;

    emit q_ptr->pairingDisplayConfirmation(address, pin);
    emit q_ptr->pairingDisplayPinCode(address, pin);
}

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

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

QString QBluetoothLocalDevice::name() const
{
    if (d_ptr->adapter())
        return d_ptr->adapter()->callObjectMethod("getName", "()Ljava/lang/String;").toString();

    return QString();
}

QBluetoothAddress QBluetoothLocalDevice::address() const
{
    QString result;
    if (d_ptr->adapter()) {
        result
            = d_ptr->adapter()->callObjectMethod("getAddress", "()Ljava/lang/String;").toString();
    }

    QBluetoothAddress address(result);
    return address;
}

void QBluetoothLocalDevice::powerOn()
{
    if (hostMode() != HostPoweredOff)
        return;

    if (d_ptr->adapter()) {
        bool ret = (bool)d_ptr->adapter()->callMethod<jboolean>("enable", "()Z");
        if (!ret)
            emit error(QBluetoothLocalDevice::UnknownError);
    }
}

void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode requestedMode)
{
    QBluetoothLocalDevice::HostMode mode = requestedMode;
    if (requestedMode == HostDiscoverableLimitedInquiry)
        mode = HostDiscoverable;

    if (mode == hostMode())
        return;

    if (mode == QBluetoothLocalDevice::HostPoweredOff) {
        bool success = false;
        if (d_ptr->adapter())
            success = (bool)d_ptr->adapter()->callMethod<jboolean>("disable", "()Z");

        if (!success)
            emit error(QBluetoothLocalDevice::UnknownError);
    } else if (mode == QBluetoothLocalDevice::HostConnectable) {
        if (hostMode() == QBluetoothLocalDevice::HostDiscoverable) {
            // cannot directly go from Discoverable to Connectable
            // we need to go to disabled mode and enable once disabling came through

            setHostMode(QBluetoothLocalDevice::HostPoweredOff);
            d_ptr->pendingHostModeTransition = true;
        } else {
            QAndroidJniObject::callStaticMethod<void>(
                "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
                "setConnectable");
        }
    } else if (mode == QBluetoothLocalDevice::HostDiscoverable
               || mode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) {
        QAndroidJniObject::callStaticMethod<void>(
            "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver", "setDiscoverable");
    }
}

QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
{
    if (d_ptr->adapter()) {
        jint scanMode = d_ptr->adapter()->callMethod<jint>("getScanMode");

        switch (scanMode) {
        case 20:     // BluetoothAdapter.SCAN_MODE_NONE
            return HostPoweredOff;
        case 21:     // BluetoothAdapter.SCAN_MODE_CONNECTABLE
            return HostConnectable;
        case 23:     // BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
            return HostDiscoverable;
        default:
            break;
        }
    }

    return HostPoweredOff;
}

QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
{
    // Android only supports max of one device (so far)
    QList<QBluetoothHostInfo> localDevices;

    QAndroidJniObject o = getDefaultAdapter();
    if (o.isValid()) {
        QBluetoothHostInfo info;
        info.setName(o.callObjectMethod("getName", "()Ljava/lang/String;").toString());
        info.setAddress(QBluetoothAddress(o.callObjectMethod("getAddress",
                                                             "()Ljava/lang/String;").toString()));
        localDevices.append(info);
    }
    return localDevices;
}

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

    const Pairing previousPairing = pairingStatus(address);
    Pairing newPairing = pairing;
    if (pairing == AuthorizedPaired) // AuthorizedPaired same as Paired on Android
        newPairing = Paired;

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

    // BluetoothDevice::createBond() requires Android API 15
    if (QtAndroidPrivate::androidSdkVersion() < 15 || !d_ptr->adapter()) {
        qCWarning(QT_BT_ANDROID) <<  "Unable to pair: requires Android API 15+";
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QBluetoothLocalDevice::Error,
                                        QBluetoothLocalDevice::PairingError));
        return;
    }

    QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString());
    jboolean success = QAndroidJniObject::callStaticMethod<jboolean>(
        "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
        "setPairingMode",
        "(Ljava/lang/String;Z)Z",
        inputString.object<jstring>(),
        newPairing == Paired ? JNI_TRUE : JNI_FALSE);

    if (!success) {
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QBluetoothLocalDevice::Error,
                                        QBluetoothLocalDevice::PairingError));
    } else {
        d_ptr->pendingPairings.append(qMakePair(address, newPairing == Paired ? true : false));
    }
}

QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
    const QBluetoothAddress &address) const
{
    if (address.isNull() || !d_ptr->adapter())
        return Unpaired;

    QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString());
    QAndroidJniObject remoteDevice
        = d_ptr->adapter()->callObjectMethod("getRemoteDevice",
                                             "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;",
                                             inputString.object<jstring>());
    QAndroidJniEnvironment env;
    if (env->ExceptionCheck()) {
        env->ExceptionClear();
        return Unpaired;
    }

    jint bondState = remoteDevice.callMethod<jint>("getBondState");
    switch (bondState) {
    case 12: // BluetoothDevice.BOND_BONDED
        return Paired;
    default:
        break;
    }

    return Unpaired;
}

void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
{
    if (!d_ptr->adapter())
        return;

    bool success = d_ptr->receiver->pairingConfirmation(confirmation);
    if (!success)
        emit error(PairingError);
}

QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
{
    /*
     * Android does not have an API to list all connected devices. We have to collect
     * the information based on a few indicators.
     *
     * Primarily we detect connected devices by monitoring connect/disconnect signals.
     * Unfortunately the list may only be complete after very long monitoring time.
     * However there are some Android APIs which provide the list of connected devices
     * for specific Bluetooth profiles. QtBluetoothBroadcastReceiver.getConnectedDevices()
     * returns a few connections of common profiles. The returned list is not complete either
     * but at least it can complement our already detected connections.
     */
    QAndroidJniObject connectedDevices = QAndroidJniObject::callStaticObjectMethod(
        "org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver",
        "getConnectedDevices",
        "()[Ljava/lang/String;");

    if (!connectedDevices.isValid())
        return d_ptr->connectedDevices;

    jobjectArray connectedDevicesArray = connectedDevices.object<jobjectArray>();
    if (!connectedDevicesArray)
        return d_ptr->connectedDevices;

    QAndroidJniEnvironment env;
    QList<QBluetoothAddress> knownAddresses = d_ptr->connectedDevices;
    QAndroidJniObject p;

    jint size = env->GetArrayLength(connectedDevicesArray);
    for (int i = 0; i < size; i++) {
        p = env->GetObjectArrayElement(connectedDevicesArray, i);
        QBluetoothAddress address(p.toString());
        if (!address.isNull() && !knownAddresses.contains(address))
            knownAddresses.append(address);
    }

    return knownAddresses;
}

QT_END_NAMESPACE
