/**
 * Qt6 Common library
 *
 * The Qt6 Common library is auto-generated and available to users under the same license as the Qt which it is used with or built with. See available licenses below. 
 * SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#ifndef QOAI_BASEAPI_H
#define QOAI_BASEAPI_H

#include "qoaiopenapicommoncommonexports.h"
#include "qoaihelpers.h"
#include "qoaihttprequest.h"
#include "qoaiserverconfiguration.h"
#include "qoaiservervariable.h"

#include <QtCore/qanystringview.h>
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qobject.h>
#include <QtCore/qpointer.h>

#include <QtNetwork/qhttpheaders.h>
#include <QtNetwork/qnetworkrequestfactory.h>
#if QT_CONFIG(ssl)
#include <QtNetwork/qsslconfiguration.h>
#endif // ssl

#include <memory>
#include <optional>

QT_BEGIN_NAMESPACE
class QNetworkAccessManager;
class QNetworkReply;
class QRestAccessManager;
QT_END_NAMESPACE

/*! is a list of typed data. */
#define QOAI_VA_LIST(...) __VA_ARGS__
/**
* \def QOAI_ADD_EMPTY_OPERATION_IMPL(OPERATION, DEPRECATED)
* Add an OPERATION with no input arguments and without any additional datatype content
* responded by the server. The expected OPERATION response is HTTP code.
*
* See ./doc/html/index.html for operations implementation details.
*
* @param[in] OPERATION - the API name that will be added by this macro.
* @param[in] DEPRECATED - sets Q_DECL_DEPRECATED if operation is deprecated.
**/
#define QOAI_ADD_EMPTY_OPERATION_IMPL(OPERATION, DEPRECATED)                      \
public Q_SLOTS:                                                                         \
DEPRECATED virtual void OPERATION() \
{                                                                                       \
    OPERATION##WithDataImpl(nullptr, nullptr);                                          \
}                                                                                       \
protected:                                                                              \
virtual                             \
void OPERATION##WithDataImpl(const QObject *context, QtPrivate::QSlotObjectBase *slot); \
void OPERATION##Callback(const QRestReply &reply);                                      \
public:                                                                                 \
template <typename Functor, if_compatible_callback<Functor> = true>                     \
DEPRECATED void OPERATION(const ContextTypeForFunctor<Functor> *context, Functor &&callback)       \
{                                                                                                  \
    OPERATION##WithDataImpl(context,                                                               \
    QtPrivate::makeCallableObject<QOAIEmptyCallbackReply>(std::forward<Functor>(callback))); \
}                                                                                                  \

/**
* \def QOAI_ADD_NO_PARAMS_OPERATION_WITH_RESPONSE_IMPL(OPERATION, RESPONSE, DEPRECATED)
* Add an OPERATION with no input arguments, but with RESPONSE datatypes responded by the server.
*
* See ./doc/html/index.html for operations implementation details.
*
* @param[in] OPERATION - the API name that will be added by this macro.
* @param[in] RESPONSE  - the list objects that the server provides as a response to the OPERATION call.
* @param[in] DEPRECATED - sets Q_DECL_DEPRECATED if operation is deprecated.
**/
#define QOAI_ADD_NO_PARAMS_OPERATION_WITH_RESPONSE_IMPL(OPERATION, RESPONSE, DEPRECATED)       \
public Q_SLOTS:                                                                                      \
DEPRECATED virtual void OPERATION()              \
{                                                                                                    \
    OPERATION##WithDataImpl(nullptr, nullptr);                                                       \
}                                                                                                    \
protected:                                                                                           \
using OPERATION##CallbackReply = void(*)(const QRestReply &, QOAI_VA_LIST RESPONSE);           \
template <typename Functor>                                                                          \
using OPERATION##_compatible_callback =                                                              \
std::enable_if_t<QtPrivate::AreFunctionsCompatible<OPERATION##CallbackReply, Functor>::value, bool>; \
virtual                                    \
void OPERATION##WithDataImpl(const QObject *context, QtPrivate::QSlotObjectBase *slot);        \
void OPERATION##Callback(const QRestReply &reply);                                             \
public:                                                                                        \
template <typename Functor, OPERATION##_compatible_callback<Functor> = true>                   \
DEPRECATED void OPERATION(const ContextTypeForFunctor<Functor> *context, Functor &&callback)   \
{                                                                                              \
    OPERATION##WithDataImpl(context,                                                           \
    QtPrivate::makeCallableObject<OPERATION##CallbackReply>(std::forward<Functor>(callback))); \
}                                                                                              \

/**
* \def QOAI_ADD_OPERATION_IMPL(OPERATION, PARAMS, ARGS, RESPONSE, DEPRECATED)
* Add an OPERATION with input parameters PARAMS and arguments ARGS and with RESPONSE datatypes
* responded by the server.
*
* See ./doc/html/index.html for operations implementation details.
*
* @param[in] OPERATION - the API name that will be added by this macro.
* @param[in] PARAMS    - the list of OPERATION data types.
* @param[in] ARGS      - the list of OPERATION arguments.
* @param[in] RESPONSE  - the list objects that the server provides as a response to the OPERATION call.
* @param[in] DEPRECATED - sets Q_DECL_DEPRECATED if operation is deprecated.
**/
#define QOAI_ADD_OPERATION_IMPL(OPERATION, PARAMS, ARGS, RESPONSE, DEPRECATED)      \
public Q_SLOTS:                                                                           \
DEPRECATED virtual void OPERATION(QOAI_VA_LIST PARAMS) \
{                                                                                         \
    OPERATION##WithDataImpl(QOAI_VA_LIST ARGS, nullptr, nullptr);                   \
}                                                                                         \
protected:                                                                                \
virtual                               \
void OPERATION##WithDataImpl(QOAI_VA_LIST PARAMS, const QObject *context = nullptr, \
                            QtPrivate::QSlotObjectBase *slot = nullptr);                  \
void OPERATION##Callback(const QRestReply &reply);                                        \
using OPERATION##CallbackReply = void(*)(const QRestReply &, QOAI_VA_LIST RESPONSE);           \
template <typename Functor>                                                                          \
using OPERATION##_compatible_callback =                                                              \
std::enable_if_t<QtPrivate::AreFunctionsCompatible<OPERATION##CallbackReply, Functor>::value, bool>; \
public:                                                                                              \
template <typename Functor, OPERATION##_compatible_callback<Functor> = true>                         \
DEPRECATED void OPERATION(QOAI_VA_LIST PARAMS, const ContextTypeForFunctor<Functor> *context = nullptr,   \
                    Functor &&callback = [](const QRestReply &, QOAI_VA_LIST RESPONSE){})      \
{                                                                                                    \
    OPERATION##WithDataImpl(QOAI_VA_LIST ARGS, context,                                        \
    QtPrivate::makeCallableObject<OPERATION##CallbackReply>(std::forward<Functor>(callback)));       \
}                                                                                                    \

/**
* \def QOAI_ADD_OPERATION_WITH_NO_RESPONSE_IMPL(OPERATION, PARAMS, ARGS, DEPRECATED)
* Add an OPERATION with input arguments ARGS, but without any additional datatype content
* responded by the server. The expected OPERATION response is HTTP code.
*
* See ./doc/html/index.html for operations implementation details.
*
* @param[in] OPERATION - the API name that will be added by this macro.
* @param[in] PARAMS    - the list of OPERATION data types.
* @param[in] ARGS      - the list of OPERATION arguments.
* @param[in] DEPRECATED - sets Q_DECL_DEPRECATED if operation is deprecated.
**/
#define QOAI_ADD_OPERATION_WITH_NO_RESPONSE_IMPL(OPERATION, PARAMS, ARGS, DEPRECATED)                      \
public Q_SLOTS:                                                                                                  \
DEPRECATED virtual void OPERATION(QOAI_VA_LIST PARAMS) \
{                                                                                         \
    OPERATION##WithDataImpl(QOAI_VA_LIST ARGS, nullptr, nullptr);                   \
}                                                                                         \
protected:                                                                                \
virtual                               \
void OPERATION##WithDataImpl(QOAI_VA_LIST PARAMS, const QObject *context = nullptr, \
                            QtPrivate::QSlotObjectBase *slot = nullptr);                  \
void OPERATION##Callback(const QRestReply &reply);                                        \
public:                                                                                   \
template <typename Functor, if_compatible_callback<Functor> = true>                       \
DEPRECATED void OPERATION(QOAI_VA_LIST PARAMS, const ContextTypeForFunctor<Functor> *context = nullptr, \
                    Functor &&callback = [](const QRestReply &){})                              \
{                                                                                         \
    OPERATION##WithDataImpl(QOAI_VA_LIST ARGS, context,                             \
    QtPrivate::makeCallableObject<QOAIEmptyCallbackReply>(std::forward<Functor>(callback))); \
}                                                                                                  \

QT_BEGIN_NAMESPACE

namespace QtOpenApiCommon {

class QOAIBaseApiPrivate;

class OPENAPICOMMON_COMMON_EXPORT QOAIBaseApi : public QObject {
    Q_OBJECT
public:
    using ServerError = QOAIServerVariable::ServerError;
    Q_ENUM(ServerError)

    QOAIBaseApi() : QOAIBaseApi(nullptr) {}
    explicit QOAIBaseApi(QObject *parent);
    ~QOAIBaseApi() override;
public Q_SLOTS:
    QList<QString> operations() const;
    QList<QOAIServerConfiguration> serverConfigurations(const QString &operation) const;

    ServerError setServerVariable(const QString &operation, qsizetype serverIndex,
                                  const QString &variable, const QString &value);
    ServerError setServer(const QString &operation, qsizetype serverIndex);
    std::optional<qsizetype> activeServer(const QString &operation) const;

    void setApiKey(const QString &apiKeyName, const QString &apiKey);
    std::optional<QString> apiKey(const QString &name) const;
    void setBearerToken(const QString &token);
    QString bearerToken() const;
    void setUsername(const QString &username);
    QString username() const;
    void setPassword(const QString &password);
    QString password() const;
    void setTimeOut(std::chrono::milliseconds timeOut);
#if QT_CONFIG(ssl)
    void setSslConfiguration(QSslConfiguration config);
    QSslConfiguration sslConfiguration() const;
#endif // ssl
    void setWorkingDirectory(const QString &path);
    QString workingDirectory() const;
    void setRestAccessManager(QRestAccessManager *ram);
    QRestAccessManager *restAccessManager() const;
    void setNetworkRequestFactory(QNetworkRequestFactory factory);
    QNetworkRequestFactory networkRequestFactory() const;

    void setHeader(QHttpHeaders::WellKnownHeader key, QAnyStringView value);
    void setHeader(QAnyStringView key, QAnyStringView value);

    void setRequestCompressionEnabled(bool enabled);
    bool requestCompressionEnabled() const;
    void setResponseCompressionEnabled(bool enabled);
    bool responseCompressionEnabled() const;

    QString errorString(ServerError error) const;

protected:
    struct QOAICallerInfo
    {
        QPointer<const QObject> contextObject = nullptr;
        QtPrivate::SlotObjSharedPtr slot;
    };
    using QOAIEmptyCallbackReply = void(*)(QRestReply&);
    template <typename Functor>
    using ContextTypeForFunctor = typename QtPrivate::ContextTypeForFunctor<Functor>::ContextType;
    template <typename Functor>
    using if_compatible_callback = std::enable_if_t<QtPrivate::AreFunctionsCompatible<QOAIEmptyCallbackReply, Functor>::value, bool>;

    QNetworkReply *execute(QOAIHttpRequestInput &input, QNetworkRequest &request, QByteArray &requestContent);
    void setServersForOperation(const QString &operation, const QList<QOAIServerConfiguration> &configs);
    void setBaseServerUrl(const QString &operation);
    void setCallerInfo(QNetworkReply *reply, const QOAICallerInfo &info);
    QOAICallerInfo takeCallerInfo(QNetworkReply *reply);

private:
    // Note that d_ptr refers to QObjectPrivate, which we cannot use because
    // we do not want to link to CorePrivate
    friend class QOAIBaseApiPrivate;
    std::unique_ptr<QOAIBaseApiPrivate> d;
};

} // namespace QtOpenApiCommon

QT_END_NAMESPACE

#endif

