// SPDX-FileCopyrightText: 2019 Jeremy Lainé <jeremy.laine@m4x.org>
// SPDX-FileCopyrightText: 2019 Linus Jahn <lnj@kaidan.im>
//
// SPDX-License-Identifier: LGPL-2.1-or-later

#include "QXmppPubSubBaseItem.h"

#include "QXmppElement.h"
#include "QXmppUtils_p.h"

#include "StringLiterals.h"
#include "XmlWriter.h"

#include <QDomElement>

using namespace QXmpp::Private;

class QXmppPubSubBaseItemPrivate : public QSharedData
{
public:
    QXmppPubSubBaseItemPrivate(const QString &id, const QString &publisher);

    QString id;
    QString publisher;
};

QXmppPubSubBaseItemPrivate::QXmppPubSubBaseItemPrivate(const QString &id, const QString &publisher)
    : id(id), publisher(publisher)
{
}

/*!
    \class QXmppPubSubBaseItem
    \inmodule QXmpp

    The QXmppPubSubBaseItem class represents a publish-subscribe item as defined by
    \xep{0060}{Publish-Subscribe}.

    To access the payload of an item, you need to create a derived class of this
    and override QXmppPubSubBaseItem::parsePayload() and
    QXmppPubSubBaseItem::serializePayload().

    It is also required that you override QXmppPubSubBaseItem::isItem() and also
    check for the correct payload of the PubSub item. This can be easily done by
    using the protected overload of isItem() with an function that checks the
    tag name and namespace of the payload. The function is only called if a
    payload exists.

    In short, you need to reimplement these methods:
    \list
        \li QXmppPubSubBaseItem::parsePayload()
        \li QXmppPubSubBaseItem::serializePayload()
        \li QXmppPubSubBaseItem::isItem()
    \endlist

    \since QXmpp 1.5
*/

/*!
    Constructs an item with \a id and \a publisher.
*/
QXmppPubSubBaseItem::QXmppPubSubBaseItem(const QString &id, const QString &publisher)
    : d(new QXmppPubSubBaseItemPrivate(id, publisher))
{
}

/*! Default copy-constructor */
QXmppPubSubBaseItem::QXmppPubSubBaseItem(const QXmppPubSubBaseItem &iq) noexcept = default;
/*! Default move-constructor */
QXmppPubSubBaseItem::QXmppPubSubBaseItem(QXmppPubSubBaseItem &&) noexcept = default;
QXmppPubSubBaseItem::~QXmppPubSubBaseItem() noexcept = default;
/*! Default assignment operator, copying \a iq. */
QXmppPubSubBaseItem &QXmppPubSubBaseItem::operator=(const QXmppPubSubBaseItem &iq) noexcept = default;
/*! Default move-assignment operator, moving from \a iq. */
QXmppPubSubBaseItem &QXmppPubSubBaseItem::operator=(QXmppPubSubBaseItem &&iq) noexcept = default;

/*! Returns the ID of the PubSub item. */
QString QXmppPubSubBaseItem::id() const
{
    return d->id;
}

/*!
    Sets the ID of the PubSub item to \a id.
*/
void QXmppPubSubBaseItem::setId(const QString &id)
{
    d->id = id;
}

/*! Returns the JID of the publisher of the item. */
QString QXmppPubSubBaseItem::publisher() const
{
    return d->publisher;
}

/*! Sets the JID of the \a publisher of the item. */
void QXmppPubSubBaseItem::setPublisher(const QString &publisher)
{
    d->publisher = publisher;
}

void QXmppPubSubBaseItem::parse(const QDomElement &element)
{
    d->id = element.attribute(u"id"_s);
    d->publisher = element.attribute(u"publisher"_s);

    parsePayload(element.firstChildElement());
}

void QXmppPubSubBaseItem::toXml(QXmlStreamWriter *writer) const
{
    XmlWriter(writer).write(Element {
        u"item",
        OptionalAttribute { u"id", d->id },
        OptionalAttribute { u"publisher", d->publisher },
        [&] { serializePayload(writer); },
    });
}

/*! Returns true, if the \a element is possibly a PubSub item. */
bool QXmppPubSubBaseItem::isItem(const QDomElement &element)
{
    return element.tagName() == u"item";
}

/*!
    Parses the payload \a payloadElement of the item (the child element of the &lt;item/&gt;).

    This method needs to be overriden to perform the payload-specific parsing.
*/
void QXmppPubSubBaseItem::parsePayload(const QDomElement &)
{
}

/*!
    Serializes the payload of the item (the child element of the &lt;item/&gt;).

    This method needs to be overriden to perform the payload-specific
    serialization.

    \a writer.
*/
void QXmppPubSubBaseItem::serializePayload(QXmlStreamWriter *) const
{
}
