{{!
SPDX-FileCopyrightText: 2020 Kitsune Ral <Kitsune-Ral@users.sf.net>
SPDX-License-Identifier: LGPL-2.1-or-later
}}{{>preamble}}
#pragma once

#include <Quotient/jobs/basejob.h>
{{#imports}}
#include {{_}}{{/imports}}
{{#operations.producesNonJson?}}
#include <QtNetwork/QNetworkReply>{{/operations.producesNonJson?}}

namespace Quotient {
{{>define_models}}

{{#operations.operation}}

//! \brief {{summary}}{{#description?}}
//!{{#description}}
//! {{_}}{{/description}}{{/description?}}
class {{>maybeDeprecated}} QUOTIENT_API {{>titleCaseOperationId}}Job : public BaseJob {
public:
    {{#models}}{{#model?}}
    // Inner data structures
        {{#model}}

    {{>structDefinition}}
        {{/model}}

    // Construction/destruction

    {{/model?}}{{/models}}
    {{#allParams}}{{#description?}}
    //! \param {{nameCamelCase}} {{#description}}
    //!   {{_}}{{/description}}{{/description?}}{{#_join}}
    //!{{/_join}}{{/allParams}}
    explicit {{>titleCaseOperationId}}Job({{#allParams}}{{>joinedParamDecl}}{{/allParams}});
    {{^hasBody?}}

    //! \brief Construct a URL without creating a full-fledged job object
    //!
    //! This function can be used when a URL for {{>titleCaseOperationId}}Job
    //! is necessary but the job itself isn't.
    static QUrl makeRequestUrl(const HomeserverData& hsData{{#allParams?}},
                    {{#allParams}}{{>joinedParamDecl}}{{/allParams}}{{/allParams?}});
    {{/hasBody?}}
    {{#responses}}{{#normalResponse?}}{{#allProperties?}}

    // Result properties
        {{#headers}}

    {{>nonInlineResponseSignature}}
    {
        return QString::fromUtf8(reply()->rawHeader("{{baseName}}"));
    }
        {{/headers}}{{#inlineResponse}}

    {{>docCommentShort}}
    {{dataType.name}} {{paramName}}(){{^moveOnly}}{{^producesNonJson?}}
    const{{/producesNonJson?}}{{/moveOnly}}
    {
        return {{#producesNonJson?}}reply(){{/producesNonJson?}}
            {{^producesNonJson?
                }}fromJson<{{dataType.name}}>(jsonData()){{/producesNonJson?
            }};
    }
        {{/inlineResponse}}{{#properties}}
            {{!there's nothing in #properties if the response is inline}}

    {{>nonInlineResponseSignature}}
    {
        return {{>takeOrLoad}}FromJson<{{>maybeOptionalType}}>("{{baseName}}"_L1);
    }
        {{/properties}}{{^singleValue?}}{{#properties?}}

    struct Response { {{#properties}}
        {{>docCommentShort}}
        {{>maybeOptionalType}} {{paramName}}{};

            {{/properties}}
    };
        {{/properties?}}{{/singleValue?}}
    {{/allProperties?}}{{/normalResponse?}}{{/responses}}
};
    {{#responses}}{{#normalResponse?}}{{#allProperties?}}
        {{#inlineResponse}}{{^producesNonJson?}}
            {{>overloadCollectResponse}}
        {{/producesNonJson?}}{{/inlineResponse}}{{#singleValue?}}{{#properties}}
            {{>overloadCollectResponse}}
        {{/properties}}{{/singleValue?}}{{^singleValue?}}{{#properties?}}

        {{>openIgnoreDeprecations}}
template <std::derived_from<{{>titleCaseOperationId}}Job> JobT>
constexpr inline auto doCollectResponse<JobT> =
    [](JobT* j) -> {{>titleCaseOperationId}}Job::Response {
        return { {{#properties}}j->{{paramName}}(){{>cjoin}}{{/properties}} };
    };
    {{>closeIgnoreDeprecations}}{{/properties?}}{{/singleValue?}}
    {{/allProperties?}}{{/normalResponse?}}{{/responses}}
    {{#models.model}}

        {{>openIgnoreDeprecations}}
template <> struct QUOTIENT_API JsonObjectConverter<{{qualifiedName}}> {
        {{#in?}}
    static void dumpTo(QJsonObject& jo, const {{qualifiedName}}& pod)
        {   {{#propertyMap}}
        fillJson(jo, pod.{{nameCamelCase}});
            {{/propertyMap}}{{#parents}}
        fillJson<{{name}}>(jo, pod);
            {{/parents}}{{#vars}}
        addParam{{^required?}}<IfNotEmpty>{{/required?}}(jo, "{{baseName}}"_L1,
                                                         pod.{{nameCamelCase}});
            {{/vars}}
    }
        {{/in?}}
        {{#out?}}
    static void fillFrom({{>maybeCrefJsonObject}} jo, {{qualifiedName}}& result)
        {   {{#parents}}
        fillFromJson<{{name}}{{!of the parent!}}>(jo, result);
            {{/parents}}{{#vars}}
        fillFromJson(jo.{{>takeOrValue}}("{{baseName}}"_L1), result.{{nameCamelCase}});
            {{/vars}}{{#propertyMap}}
        fromJson(jo, result.{{nameCamelCase}});
            {{/propertyMap}}
    }
        {{/out?}}
};
        {{>closeIgnoreDeprecations}}
    {{/models.model}}
{{/operations.operation}}

} // namespace Quotient
