/*
 * Copyright (C) 2014-2026 CZ.NIC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#pragma once

#include <QMetaType>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
#  include <memory> /* ::std::unique_ptr */
#else /* < Qt-5.12 */
#  include <QScopedPointer>
#endif /* >= Qt-5.12 */

#include <QList>
#include <QStringList>

#include "src/datovka_shared/isds/message_interface.h"
#include "src/datovka_shared/json/object.h"

class QByteArray; /* Forward declaration. */
class QJsonValue; /* Forward declaration. */
class QString; /* Forward declaration. */

namespace Json {

	class DmDraftPrivate;
	/*!
	 * @brief JSON structure to store message drafts.
	 */
	class DmDraft : public Object {
#ifdef QT_QML_LIB
		Q_GADGET
#endif /* QT_QML_LIB */
		Q_DECLARE_PRIVATE(DmDraft)

	public:
		class AttachmentPrivate;
		/*!
		 * @brief Attachment information.
		 */
		class Attachment : public Object {
			Q_DECLARE_PRIVATE(Attachment)

		public:
			Attachment(void);
			Attachment(const Attachment &other);
#ifdef Q_COMPILER_RVALUE_REFS
			Attachment(Attachment &&other) Q_DECL_NOEXCEPT;
#endif /* Q_COMPILER_RVALUE_REFS */
			~Attachment(void);

			Attachment &operator=(const Attachment &other) Q_DECL_NOTHROW;
#ifdef Q_COMPILER_RVALUE_REFS
			Attachment &operator=(Attachment &&other) Q_DECL_NOTHROW;
#endif /* Q_COMPILER_RVALUE_REFS */

			bool operator==(const Attachment &other) const;
			bool operator!=(const Attachment &other) const;

			static
			void swap(Attachment &first, Attachment &second) Q_DECL_NOTHROW;

			bool isNull(void) const;

			/* Attachment name. */
			const QString &name(void) const;
			void setName(const QString &n);
#ifdef Q_COMPILER_RVALUE_REFS
			void setName(QString &&n);
#endif /* Q_COMPILER_RVALUE_REFS */

			/* Attachment data. */
			const QByteArray &data(void) const;
			void setData(const QByteArray &da);
#ifdef Q_COMPILER_RVALUE_REFS
			void setData(QByteArray &&da);
#endif /* Q_COMPILER_RVALUE_REFS */

			/* Attachment path. */
			const QString &path(void) const;
			void setPath(const QString &p);
#ifdef Q_COMPILER_RVALUE_REFS
			void setPath(QString &&p);
#endif /* Q_COMPILER_RVALUE_REFS */

			/* Created from short message text. */
			bool createdFromText(void) const;
			void setCreatedFromText(bool cft);

			/*!
			 * @brief Creates an instance from supplied JSON document.
			 *
			 * @param[in]  json JSON data.
			 * @param[out] ok Set to true on success.
			 * @return Invalid value on error a valid structure else.
			 */
			static
			Attachment fromJson(const QByteArray &json, bool *ok = Q_NULLPTR);

			/*!
			 * @brief Creates an instance from supplied JSON data.
			 *
			 * @param[in]  jsonVal JSON object value.
			 * @param[out] ok Set to true on success.
			 * @return Invalid value on error a valid structure else.
			 */
			static
			Attachment fromJsonVal(const QJsonValue &jsonVal, bool *ok = Q_NULLPTR);

			/*!
			 * @brief Writes content of JSON object.
			 *
			 * @note Unspecified values are omitted.
			 *
			 * @param[out] jsonValue JSON value to write to.
			 * @return True on success.
			 */
			virtual
			bool toJsonVal(QJsonValue &jsonVal) const Q_DECL_OVERRIDE;

		private:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
			::std::unique_ptr<AttachmentPrivate> d_ptr;
#else /* < Qt-5.12 */
			QScopedPointer<AttachmentPrivate> d_ptr;
#endif /* >= Qt-5.12 */
		};

		/*!
		 * @brief List of attachments.
		 */
		class AttachmentList : public Object, public QList<Attachment> {
		public:
			/* Expose list constructors. */
			using QList<Attachment>::QList;

			/* Some older compilers complain about missing constructor. */
			AttachmentList(void);

			AttachmentList(const QList<Attachment> &other);
#ifdef Q_COMPILER_RVALUE_REFS
			AttachmentList(QList<Attachment> &&other);
#endif /* Q_COMPILER_RVALUE_REFS */

			static
			AttachmentList fromJson(const QByteArray &json, bool *ok = Q_NULLPTR);
			static
			AttachmentList fromJsonVal(const QJsonValue &jsonVal, bool *ok = Q_NULLPTR);

			virtual
			bool toJsonVal(QJsonValue &jsonVal) const Q_DECL_OVERRIDE;
		};

		/*
		 * Don't forget to declare types in order to make them work with
		 * the meta-object system.
		 */
		static
		void declareTypes(void);

#ifdef QT_QML_LIB
		Q_PROPERTY(Isds::Envelope dmEnvelope READ dmEnvelope WRITE setDmEnvelope)
		Q_PROPERTY(QStringList dmRecipients READ dmRecipients WRITE setDmRecipients)
		Q_PROPERTY(AttachmentList dmAttachments READ dmAttachments WRITE setDmAttachments)
		Q_PROPERTY(QString shortMessageText READ shortMessageText WRITE setShortMessageText)
		Q_PROPERTY(qint64 shortMessageTextFmt READ shortMessageTextFmt WRITE setShortMessageTextFmt)
		Q_PROPERTY(bool cntrlDowmloadMessage READ cntrlDowmloadMessage WRITE setCntrlDowmloadMessage)
		Q_PROPERTY(bool cntrlUploadMessageRm READ cntrlUploadMessageRm WRITE setCntrlUploadMessageRm)
#endif /* QT_QML_LIB */

		DmDraft(void);
		DmDraft(const DmDraft &other);
#ifdef Q_COMPILER_RVALUE_REFS
		DmDraft(DmDraft &&other) Q_DECL_NOEXCEPT;
#endif /* Q_COMPILER_RVALUE_REFS */
		~DmDraft(void);

		DmDraft &operator=(const DmDraft &other) Q_DECL_NOTHROW;
#ifdef Q_COMPILER_RVALUE_REFS
		DmDraft &operator=(DmDraft &&other) Q_DECL_NOTHROW;
#endif /* Q_COMPILER_RVALUE_REFS */

		bool operator==(const DmDraft &other) const;
		bool operator!=(const DmDraft &other) const;

		static
		void swap(DmDraft &first, DmDraft &second) Q_DECL_NOTHROW;

		bool isNull(void) const;

		/* Message envelope */
		const Isds::Envelope &dmEnvelope(void) const;
		void setDmEnvelope(const Isds::Envelope &e);
#ifdef Q_COMPILER_RVALUE_REFS
		void setDmEnvelope(Isds::Envelope &&e);
#endif /* Q_COMPILER_RVALUE_REFS */

		/* Recipient list */
		const QStringList &dmRecipients(void) const;
		void setDmRecipients(const QStringList &rl);
#ifdef Q_COMPILER_RVALUE_REFS
		void setDmRecipients(QStringList &&rl);
#endif /* Q_COMPILER_RVALUE_REFS */

		/* Attachment list */
		const AttachmentList &dmAttachments(void) const;
		void setDmAttachments(const AttachmentList &al);
#ifdef Q_COMPILER_RVALUE_REFS
		void setDmAttachments(AttachmentList &&al);
#endif /* Q_COMPILER_RVALUE_REFS */

		/* Short message text */
		const QString &shortMessageText(void) const;
		void setShortMessageText(const QString &smt);
#ifdef Q_COMPILER_RVALUE_REFS
		void setShortMessageText(QString &&smt);
#endif /* Q_COMPILER_RVALUE_REFS */

		/* TODO - should be enum, no magic numeric values here */
		/*
		 * Short message text format
		 * Utility::PLAIN_TEXT, Utility::MARKDOWN_TEXT
		 */
		qint64 shortMessageTextFmt(void) const;
		void setShortMessageTextFmt(qint64 smtf);

		/* Immediately download sent message checkbox */
		bool cntrlDowmloadMessage(void) const;
		void setCntrlDowmloadMessage(bool cdm);

		/* Immediately upload to records management checkbox */
		bool cntrlUploadMessageRm(void) const;
		void setCntrlUploadMessageRm(bool cum);

		/*!
		 * @brief Creates an instance from supplied JSON document.
		 *
		 * @param[in]  json JSON data.
		 * @param[out] ok Set to true on success.
		 * @return Invalid value on error a valid structure else.
		 */
		static
		DmDraft fromJson(const QByteArray &json, bool *ok = Q_NULLPTR);

		/*!
		 * @brief Creates an instance from supplied JSON data.
		 *
		 * @param[in]  jsonVal JSON object value.
		 * @param[out] ok Set to true on success.
		 * @return Invalid value on error a valid structure else.
		 */
		static
		DmDraft fromJsonVal(const QJsonValue &jsonVal, bool *ok = Q_NULLPTR);

		/*!
		 * @brief Writes content of JSON object.
		 *
		 * @note Unspecified values are omitted.
		 *
		 * @param[out] jsonValue JSON value to write to.
		 * @return True on success.
		 */
		virtual
		bool toJsonVal(QJsonValue &jsonVal) const Q_DECL_OVERRIDE;

	private:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
		::std::unique_ptr<DmDraftPrivate> d_ptr;
#else /* < Qt-5.12 */
		QScopedPointer<DmDraftPrivate> d_ptr;
#endif /* >= Qt-5.12 */
	};

}

Q_DECLARE_METATYPE(Json::DmDraft)
Q_DECLARE_METATYPE(Json::DmDraft::AttachmentList)
Q_DECLARE_METATYPE(Json::DmDraft::Attachment)
Q_DECLARE_METATYPE(Isds::Envelope)
