/*
 SPDX-FileCopyrightText: 2005 Tobias Koenig <tokoe@kde.org>

 SPDX-License-Identifier: MIT
*/

#ifndef KWSDL_SOAPBINDING_H
#define KWSDL_SOAPBINDING_H

#include <QDomElement>
#include <QMap>
#include <QUrl>

#include <common/qname.h>
#include <wsdl/abstractbinding.h>

#include <kode_export.h>

namespace KWSDL {

class KWSDL_EXPORT SoapBinding final : public AbstractBinding
{
public:
    enum Style
    {
        RPCStyle,
        DocumentStyle
    };

    enum Use
    {
        LiteralUse,
        EncodedUse
    };

    enum Transport
    {
        HTTPTransport
    };

    class KWSDL_EXPORT Binding
    {
    public:
        Binding();
        ~Binding();

        void setTransport(Transport transport);
        Transport transport() const;

        void setStyle(Style style);
        Style style() const;

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

    private:
        Transport mTransport;
        Style mStyle;
    };

    class KWSDL_EXPORT Body
    {
    public:
        Body();
        ~Body();

#if 0
        void setEncodingStyle(const QString &encodingStyle);
        QString encodingStyle() const;
#endif

        // void setPart( const QString &part );
        QString part() const;

        // void setUse( Use use );
        Use use() const;

        // void setNameSpace( const QString &nameSpace );
        QString nameSpace() const;

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

    private:
#if 0
        QString mEncodingStyle;
#endif
        QString mPart;
        Use mUse;
        QString mNameSpace;
    };

    class KWSDL_EXPORT Fault
    {
    public:
        Fault();
        ~Fault();

#if 0
        void setEncodingStyle(const QString &encodingStyle);
        QString encodingStyle() const;
#endif

        void setUse(Use use);
        Use use() const;

        void setNameSpace(const QString &nameSpace);
        QString nameSpace() const;

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

    private:
#if 0
        QString mEncodingStyle;
#endif
        Use mUse;
        QString mNameSpace;
    };

    class KWSDL_EXPORT HeaderFault
    {
    public:
        HeaderFault();
        ~HeaderFault();

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

        void setMessage(const QName &message);
        QName message() const;

#if 0
        void setEncodingStyle(const QString &encodingStyle);
        QString encodingStyle() const;
#endif

        void setPart(const QString &part);
        QString part() const;

        void setUse(Use use);
        Use use() const;

        void setNameSpace(const QString &nameSpace);
        QString nameSpace() const;

    private:
        QName mMessage;
        QString mPart;
        Use mUse;
#if 0
        QString mEncodingStyle;
#endif
        QString mNameSpace;
    };

    class Headers;

    class KWSDL_EXPORT Header
    {
    public:
        Header();
        ~Header();

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

        void setHeaderFault(const HeaderFault &headerFault);
        HeaderFault headerFault() const;

        void setMessage(const QName &message);
        QName message() const;

        void setPart(const QString &part);
        QString part() const;

        void setUse(Use use);
        Use use() const;

#if 0
        void setEncodingStyle(const QString encodingStyle);
        QString encodingStyle() const;
#endif
        void setNameSpace(const QString &nameSpace);
        QString nameSpace() const;

    private:
        friend class Headers;
        HeaderFault mHeaderFault;
        QName mMessage;
        QString mPart;
        Use mUse;
#if 0
        QString mEncodingStyle;
#endif
        QString mNameSpace;
    };

    class Headers : public QList<Header>
    {
    public:
        bool contains(const Header &header) const;
    };

    /**
     * <operation> as defined in a soap <binding>.
     * Contains some flags for input and output (e.g. <output><soap:body use="literal"/></output>
     * but also the full definition of <soap:headers> for <input>.
     */
    class KWSDL_EXPORT Operation
    {
    public:
        typedef QList<Operation> List;
        typedef QMap<QString, Operation> Map;

        Operation();
        Operation(const QString &name);
        ~Operation();

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

        void setName(const QString &name);
        QString name() const;

        void setAction(const QString &action);
        QString action() const;

        void setStyle(Style style);
        Style style() const;

        void setInput(const Body &input);
        Body input() const;

        void setOutput(const Body &output);
        Body output() const;

        void addInputHeader(const Header &inputHeader);
        Headers inputHeaders() const;

        void addOutputHeader(const Header &outputHeader);
        Headers outputHeaders() const;

        void setFault(const Fault &fault);
        Fault fault() const;

    private:
        QString mName;
        QString mSoapAction;
        Style mStyle;
        Body mInputBody;
        Headers mInputHeaders;
        Body mOutputBody;
        Headers mOutputHeaders;
        Fault mFault;
    };

    class KWSDL_EXPORT Address
    {
    public:
        Address();
        ~Address();

        void setLocation(const QUrl &location);
        QUrl location() const;

        void loadXML(ParserContext *context, const QDomElement &element);
        void saveXML(ParserContext *context, QDomDocument &document, QDomElement &parent) const;

    private:
        QUrl mLocation;
    };

    SoapBinding();
    ~SoapBinding() override;
    SoapBinding(const SoapBinding &other);
    SoapBinding &operator=(const SoapBinding &other);
    void swap(SoapBinding &other) noexcept;

    void setAddress(const Address &address);
    Address address() const;

    void setOperations(const Operation::Map &operations);
    Operation::Map operations() const;

    void setBinding(const Binding &binding);
    Binding binding() const;

    void parseBinding(ParserContext *context, const QDomElement &parent) override;
    void parseOperation(ParserContext *context, const QString &name, const QDomElement &parent) override;
    void parseOperationInput(ParserContext *context, const QString &name, const QDomElement &parent) override;
    void parseOperationOutput(ParserContext *context, const QString &name, const QDomElement &parent) override;
    void parseOperationFault(ParserContext *context, const QString &name, const QDomElement &parent) override;
    void parsePort(ParserContext *context, const QDomElement &parent) override;

    void synthesizeBinding(ParserContext *context, QDomDocument &document, QDomElement &parent) const override;
    void synthesizeOperation(ParserContext *context, const QString &name, QDomDocument &document, QDomElement &parent) const override;
    void synthesizeOperationInput(ParserContext *context, const QString &name, QDomDocument &document, QDomElement &parent) const override;
    void synthesizeOperationOutput(ParserContext *context, const QString &name, QDomDocument &document, QDomElement &parent) const override;
    void synthesizeOperationFault(ParserContext *context, const QString &name, QDomDocument &document, QDomElement &parent) const override;
    void synthesizePort(ParserContext *context, QDomDocument &document, QDomElement &parent) const override;

private:
    Binding mBinding;
    Operation::Map mOperations;
    Address mAddress;
    // if you add members, update the copy constructor and swap()
};

}

#endif // KWSDL_SOAPBINDING_H
