/****************************************************************************
**
** 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 "qbluetoothservicediscoveryagent.h"
#include "qbluetoothtransferreply_osx_p.h"
#include "osx/osxbtobexsession_p.h"
#include "qbluetoothserviceinfo.h"
#include "osx/osxbtutility_p.h"
#include "osx/uistrings_p.h"
#include "qbluetoothuuid.h"


#include <QtCore/qcoreapplication.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qtemporaryfile.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qdir.h>

QT_BEGIN_NAMESPACE

class QBluetoothTransferReplyOSXPrivate : OSXBluetooth::OBEXSessionDelegate
{
    friend class QBluetoothTransferReplyOSX;
public:
    QBluetoothTransferReplyOSXPrivate(QBluetoothTransferReplyOSX *q, QIODevice *inputStream);

    ~QBluetoothTransferReplyOSXPrivate();

    bool isActive() const;
    bool startOPP(const QBluetoothAddress &device);

    //
    void sendConnect(const QBluetoothAddress &device, quint16 channelID);
    void sendPut();

private:
    // OBEX session delegate:
    void OBEXConnectError(OBEXError errorCode, OBEXOpCode response) override;
    void OBEXConnectSuccess() override;

    void OBEXAbortSuccess() override;

    void OBEXPutDataSent(quint32 current, quint32 total) override;
    void OBEXPutSuccess() override;
    void OBEXPutError(OBEXError error, OBEXOpCode response) override;

    QBluetoothTransferReplyOSX *q_ptr;

    QIODevice *inputStream;

    QBluetoothTransferReply::TransferError error;
    QString errorString;

    // Set requestComplete, error, description, emit error, emit finished.
    // Too many things in one, but not to repeat this code everywhere.
    void setReplyError(QBluetoothTransferReply::TransferError errorCode,
                       const QString &errorMessage);

    // With a given API, we have to discover a service first
    // since we need a channel ID to work with OBEX session.
    // Also, service discovery agent does not have an interface
    // to test discovery mode, that's why we have this bool here.
    bool minimalScan;
    QScopedPointer<QBluetoothServiceDiscoveryAgent> agent;

    // The next step is to create an OBEX session:
    typedef OSXBluetooth::ObjCScopedPointer<ObjCOBEXSession> OBEXSession;
    OBEXSession session;

    // Both success and failure to send - transfer is complete.
    bool requestComplete;

    // We need a temporary file to generate an unique name
    // in case inputStream is not a file. QTemporaryFile not
    // only creates a random name, it also guarantees this name
    // is unique. The amount of code to generate such a name
    // is amaizingly huge (and will require global variables)
    // - so a temporary file can help.
    QScopedPointer<QTemporaryFile> temporaryFile;
};

QBluetoothTransferReplyOSXPrivate::QBluetoothTransferReplyOSXPrivate(QBluetoothTransferReplyOSX *q,
                                                                     QIODevice *input)
    : q_ptr(q),
      inputStream(input),
      error(QBluetoothTransferReply::NoError),
      minimalScan(true),
      requestComplete(false)
{
    Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)");
}

QBluetoothTransferReplyOSXPrivate::~QBluetoothTransferReplyOSXPrivate()
{
    // closeSession will set a delegate to null.
    // The OBEX session will be closed then. If
    // somehow IOBluetooth/OBEX still has a reference to our
    // session, it will not call any of delegate's callbacks.
    if (session.data())
        [session closeSession];
}

bool QBluetoothTransferReplyOSXPrivate::isActive() const
{
    return agent.data() || (session.data() && [session hasActiveRequest]);
}

bool QBluetoothTransferReplyOSXPrivate::startOPP(const QBluetoothAddress &device)
{
    Q_ASSERT_X(!isActive(), Q_FUNC_INFO, "already started");
    Q_ASSERT_X(!device.isNull(), Q_FUNC_INFO, "invalid device address");

    errorString.clear();
    error = QBluetoothTransferReply::NoError;

    agent.reset(new QBluetoothServiceDiscoveryAgent);

    agent->setRemoteAddress(device);
    agent->setUuidFilter(QBluetoothUuid(QBluetoothUuid::ObexObjectPush));

    QObject::connect(agent.data(), SIGNAL(finished()), q_ptr, SLOT(serviceDiscoveryFinished()));
    QObject::connect(agent.data(), SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),
                     q_ptr, SLOT(serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error)));

    minimalScan = true;
    agent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery);

    // We probably failed already.
    return error == QBluetoothTransferReply::NoError;
}

void QBluetoothTransferReplyOSXPrivate::sendConnect(const QBluetoothAddress &device, quint16 channelID)
{
    Q_ASSERT_X(!session, Q_FUNC_INFO, "session is already active");

    error = QBluetoothTransferReply::NoError;
    errorString.clear();

    if (device.isNull() || !channelID) {
        qCWarning(QT_BT_OSX) << "invalid device address or port";
        setReplyError(QBluetoothTransferReply::HostNotFoundError,
                      QCoreApplication::translate(TRANSFER_REPLY, TR_INVAL_TARGET));
        return;
    }

    OBEXSession newSession([[ObjCOBEXSession alloc] initWithDelegate:this
                            remoteDevice:device channelID:channelID]);
    if (!newSession) {
        qCWarning(QT_BT_OSX) << "failed to allocate OSXBTOBEXSession object";

        setReplyError(QBluetoothTransferReply::UnknownError,
                      QCoreApplication::translate(TRANSFER_REPLY, TR_SESSION_NO_START));
        return;
    }

    const OBEXError status = [newSession OBEXConnect];

    if ((status == kOBEXSuccess || status == kOBEXSessionAlreadyConnectedError)
        && error == QBluetoothTransferReply::NoError) {
        session.reset(newSession.take());
        if ([session isConnected])
            sendPut();// Connected, send a PUT request.
    } else {
        qCWarning(QT_BT_OSX) << "OBEXConnect failed";

        if (error == QBluetoothTransferReply::NoError) {
            // The error is not set yet.
            error = QBluetoothTransferReply::SessionError;
            errorString = QCoreApplication::translate(TRANSFER_REPLY, TR_CONNECT_FAILED);
        }

        requestComplete = true;
        emit q_ptr->error(error);
        emit q_ptr->finished(q_ptr);
    }
}

void QBluetoothTransferReplyOSXPrivate::sendPut()
{
    Q_ASSERT_X(inputStream, Q_FUNC_INFO, "invalid input stream (null)");
    Q_ASSERT_X(session.data(), Q_FUNC_INFO, "invalid OBEX session (nil)");
    Q_ASSERT_X([session isConnected], Q_FUNC_INFO, "not connected");
    Q_ASSERT_X(![session hasActiveRequest], Q_FUNC_INFO,
               "session already has an active request");

    QString fileName;
    QFile *const file = qobject_cast<QFile *>(inputStream);
    if (file) {
        if (!file->exists()) {
            setReplyError(QBluetoothTransferReply::FileNotFoundError,
                          QCoreApplication::translate(TRANSFER_REPLY, TR_FILE_NOT_EXIST));
            return;
        } else if (!file->isReadable()) {
            file->open(QIODevice::ReadOnly);
            if (!file->isReadable()) {
                setReplyError(QBluetoothTransferReply::IODeviceNotReadableError,
                              QCoreApplication::translate(TRANSFER_REPLY, TR_NOT_READ_IODEVICE));
                return;
            }
        }

        fileName = file->fileName();
    } else {
        if (!inputStream->isReadable()) {
            setReplyError(QBluetoothTransferReply::IODeviceNotReadableError,
                          QCoreApplication::translate(TRANSFER_REPLY, TR_NOT_READ_IODEVICE));
            return;
        }

        temporaryFile.reset(new QTemporaryFile);
        temporaryFile->open();
        fileName = temporaryFile->fileName();
    }

    const QFileInfo fileInfo(fileName);
    fileName = fileInfo.fileName();

    if ([session OBEXPutFile:inputStream withName:fileName] != kOBEXSuccess) {
        // TODO: convert OBEXError into something reasonable?
        setReplyError(QBluetoothTransferReply::SessionError,
                      QCoreApplication::translate(TRANSFER_REPLY, TR_SESSION_FAILED));
    }
}


void QBluetoothTransferReplyOSXPrivate::OBEXConnectError(OBEXError errorCode, OBEXOpCode response)
{
    Q_UNUSED(errorCode)
    Q_UNUSED(response)

    if (session.data()) {
        setReplyError(QBluetoothTransferReply::SessionError,
                      QCoreApplication::translate(TRANSFER_REPLY, TR_CONNECT_FAILED));
    } else {
        // Else we're still in OBEXConnect, in a call-back
        // and do not want to emit yet (will be done a bit later).
        error = QBluetoothTransferReply::SessionError;
        errorString = QCoreApplication::translate(TRANSFER_REPLY, TR_CONNECT_FAILED);
        requestComplete = true;
    }
}

void QBluetoothTransferReplyOSXPrivate::OBEXConnectSuccess()
{
    // Now that OBEX connect succeeded, we can send an OBEX put request.
    if (!session.data()) {
        // We're still in OBEXConnect(), it'll take care of next steps.
        return;
    }

    sendPut();
}

void QBluetoothTransferReplyOSXPrivate::OBEXAbortSuccess()
{
    // TODO:
}

void QBluetoothTransferReplyOSXPrivate::OBEXPutDataSent(quint32 current, quint32 total)
{
    emit q_ptr->transferProgress(current, total);
}

void QBluetoothTransferReplyOSXPrivate::OBEXPutSuccess()
{
    requestComplete = true;
    emit q_ptr->finished(q_ptr);
}

void QBluetoothTransferReplyOSXPrivate::OBEXPutError(OBEXError errorCode, OBEXOpCode responseCode)
{
    // Error can be reported by errorCode or responseCode
    // (that's how errors are reported in OBEXSession events).
    // errorCode and responseCode are "mutually exclusive".

    Q_UNUSED(responseCode)

    if (errorCode != kOBEXSuccess) {
        // TODO: errorCode -> TransferError.
    } else {
        // TODO: a response code can give some interesting information,
        // like "forbidden" etc. - convert this into more reasonable error.
    }

    setReplyError(QBluetoothTransferReply::SessionError,
                  QCoreApplication::translate(TRANSFER_REPLY, TR_SESSION_FAILED));
}

void QBluetoothTransferReplyOSXPrivate::setReplyError(QBluetoothTransferReply::TransferError errorCode,
                                                      const QString &description)
{
    // Not to be used to clear an error!

    error = errorCode;
    errorString = description;
    requestComplete = true;
    emit q_ptr->error(error);
    emit q_ptr->finished(q_ptr);
}


QBluetoothTransferReplyOSX::QBluetoothTransferReplyOSX(QIODevice *input,
                                                       const QBluetoothTransferRequest &request,
                                                       QBluetoothTransferManager *manager)
                                : QBluetoothTransferReply(manager)

{
    Q_UNUSED(input)

    setManager(manager);
    setRequest(request);

    osx_d_ptr.reset(new QBluetoothTransferReplyOSXPrivate(this, input));

    if (input) {
        QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
    } else {
        qCWarning(QT_BT_OSX) << "invalid input stream (null)";
        osx_d_ptr->requestComplete = true;
        osx_d_ptr->errorString = QCoreApplication::translate(TRANSFER_REPLY, TR_INVALID_DEVICE);
        osx_d_ptr->error = FileNotFoundError;
        QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
                                  Q_ARG(QBluetoothTransferReply::TransferError, FileNotFoundError));
    }
}

QBluetoothTransferReplyOSX::~QBluetoothTransferReplyOSX()
{
    // A dtor to make a scoped pointer with incomplete type happy.
}

QBluetoothTransferReply::TransferError QBluetoothTransferReplyOSX::error() const
{
    return osx_d_ptr->error;
}

QString QBluetoothTransferReplyOSX::errorString() const
{
    return osx_d_ptr->errorString;
}

bool QBluetoothTransferReplyOSX::isFinished() const
{
    return osx_d_ptr->requestComplete;
}

bool QBluetoothTransferReplyOSX::isRunning() const
{
    return osx_d_ptr->isActive();
}

bool QBluetoothTransferReplyOSX::abort()
{
    // Reset a delegate.
    [osx_d_ptr->session closeSession];
    // Should never be called from an OBEX callback!
    osx_d_ptr->session.reset(nullptr);

    // Not setReplyError, we emit finished only!
    osx_d_ptr->requestComplete = true;
    osx_d_ptr->errorString = QCoreApplication::translate(TRANSFER_REPLY, TR_OP_CANCEL);
    osx_d_ptr->error = UserCanceledTransferError;

    emit finished(this);

    return true;
}

bool QBluetoothTransferReplyOSX::start()
{
    // OBEXSession requires a channel ID and we have to find it first,
    // using QBluetoothServiceDiscoveryAgent (singleDevice, OBEX uuid filter, start
    // from MinimalDiscovery mode and continue with FullDiscovery if
    // MinimalDiscovery fails.

    if (!osx_d_ptr->isActive()) {
        // Step 0: find a channelID.
        if (request().address().isNull()) {
            qCWarning(QT_BT_OSX) << "invalid device address";
            osx_d_ptr->setReplyError(HostNotFoundError,
                                     QCoreApplication::translate(TRANSFER_REPLY, TR_INVAL_TARGET));
            return false;
        }

        return osx_d_ptr->startOPP(request().address());
    } else {
        osx_d_ptr->setReplyError(UnknownError,
                                 QCoreApplication::translate(TRANSFER_REPLY, TR_IN_PROGRESS));
        return false;
    }
}

void QBluetoothTransferReplyOSX::serviceDiscoveryFinished()
{
    Q_ASSERT_X(osx_d_ptr->agent.data(), Q_FUNC_INFO,
               "invalid service discovery agent (null)");

    const QList<QBluetoothServiceInfo> services = osx_d_ptr->agent->discoveredServices();
    if (services.size()) {
        // TODO: what if we have several?
        const QBluetoothServiceInfo &foundOBEX = services.front();
        osx_d_ptr->sendConnect(request().address(), foundOBEX.serverChannel());
    } else {
        if (osx_d_ptr->minimalScan) {
            // Try full discovery now.
            osx_d_ptr->minimalScan = false;
            osx_d_ptr->agent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
        } else {
            // No service record, no channel ID, no OBEX session.
            osx_d_ptr->setReplyError(HostNotFoundError,
                                     QCoreApplication::translate(TRANSFER_REPLY, TR_SERVICE_NO_FOUND));
        }
    }
}

void QBluetoothTransferReplyOSX::serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error errorCode)
{
    Q_ASSERT_X(osx_d_ptr->agent.data(), Q_FUNC_INFO,
               "invalid service discovery agent (null)");

    if (errorCode == QBluetoothServiceDiscoveryAgent::PoweredOffError) {
        // There's nothing else we can do.
        osx_d_ptr->setReplyError(UnknownError,
                                 QCoreApplication::translate(DEV_DISCOVERY, DD_POWERED_OFF));
        return;
    }

    if (osx_d_ptr->minimalScan) {// Try again, this time in FullDiscovery mode.
        osx_d_ptr->minimalScan = false;
        osx_d_ptr->agent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
    } else {
        osx_d_ptr->setReplyError(HostNotFoundError,
                                 QCoreApplication::translate(TRANSFER_REPLY, TR_INVAL_TARGET));
    }
}

QT_END_NAMESPACE
