#ifndef QABSTRACTTDOBJECT_H
#define QABSTRACTTDOBJECT_H

#include <QObject>
#include <QJsonObject>
#include <QJsonArray>

/**
 * @brief The QTdObject class
 *
 * Abstract base class all tdlib objects should inherit.
 *
 * All subclasses should call setType() during construction to indicate
 * the message type the class represents.
 */
class QTdObject : public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(QTdObject)
    Q_PROPERTY(Type type READ type NOTIFY typeChanged)
    Q_PROPERTY(QString typeString READ typeString NOTIFY typeChanged)
    
public:
    explicit QTdObject(QObject *parent = nullptr);

    /**
     * @brief Telegram Message Types
     */
    enum Type {
        UNKNOWN = -1, // Uninitialized state
        ANIMATION,
        AUDIO,
        AUTHENTICATION_CODE_INFO,
        AUTHENTICATION_CODE_TYPE_SMS,
        AUTHENTICATION_CODE_TYPE_TELEGRAM_MESSAGE,
        AUTHENTICATION_CODE_TYPE_CALL,
        AUTHENTICATION_CODE_TYPE_FLASH_CALL,
        AUTHORIZATION_STATE_CLOSED,
        AUTHORIZATION_STATE_CLOSING,
        AUTHORIZATION_STATE_LOGGING_OUT,
        AUTHORIZATION_STATE_READY,
        AUTHORIZATION_STATE_WAIT_CODE,
        AUTHORIZATION_STATE_WAIT_ENCRYPTION_KEY,
        AUTHORIZATION_STATE_WAIT_REGISTRATION,
        AUTHORIZATION_STATE_WAIT_PASSWORD,
        AUTHORIZATION_STATE_WAIT_PHONE_NUMBER,
        AUTHORIZATION_STATE_WAIT_TDLIB_PARAMETERS,
        CALL,
        CALL_DISCARD_REASON,
        CALL_DISCARD_REASON_DECLINED,
        CALL_DISCARD_REASON_DISCONNECTED,
        CALL_DISCARD_REASON_EMPTY,
        CALL_DISCARD_REASON_HUNG_UP,
        CALL_DISCARD_REASON_MISSED,
        CHAT,
        CHAT_ACTION_CANCEL,
        CHAT_ACTION_CHOOSING_CONTACT,
        CHAT_ACTION_CHOOSING_LOCATION,
        CHAT_ACTION_RECORDING_VIDEO,
        CHAT_ACTION_RECORDING_AUDIO,
        CHAT_ACTION_RECORDING_VIDEO_NOTE,
        CHAT_ACTION_RECORDING_VOICE_NOTE,
        CHAT_ACTION_START_PLAYING_GAME,
        CHAT_ACTION_TYPING,
        CHAT_ACTION_UPLOADING_DOCUMENT,
        CHAT_ACTION_UPLOADING_PHOTO,
        CHAT_ACTION_UPLOADING_VIDEO,
        CHAT_ACTION_UPLOADING_AUDIO,
        CHAT_ACTION_UPLOADING_VIDEO_NOTE,
        CHAT_ACTION_UPLOADING_VOICE_NOTE,
        CHAT_ACTION_CHOOSING_STICKER,
        CHAT_ACTION_UNKNOWN,
        CHAT_ACTIONBAR_ADDCONTACT,
        CHAT_ACTIONBAR_INVITEMEMBERS,
        CHAT_ACTIONBAR_JOINREQUEST,
        CHAT_ACTIONBAR_REPORTADDBLOCK,
        CHAT_ACTIONBAR_REPORTSPAM,
        CHAT_ACTIONBAR_REPORTUNRELATEDLOCATION,
        CHAT_ACTIONBAR_SHAREPHONENUMBER,
        CHAT_MEMBER,
        CHAT_MEMBER_STATUS_ADMIN,
        CHAT_MEMBER_STATUS_BANNED,
        CHAT_MEMBER_STATUS_CREATOR,
        CHAT_MEMBER_STATUS_LEFT,
        CHAT_MEMBER_STATUS_MEMBER,
        CHAT_MEMBER_STATUS_RESTRICTED,
        CHAT_PHOTO,
        CHAT_TYPE_PRIVATE,
        CHAT_TYPE_BASIC_GROUP,
        CHAT_TYPE_SUPERGROUP,
        CHAT_TYPE_SECRET,
        CHAT_LIST_MAIN,
        CHAT_LIST_ARCHIVE,
        CHAT_LIST_FILTER,
        CONNECTION_STATE_CONNECTING,
        CONNECTION_STATE_CONNECTING_TO_PROXY,
        CONNECTION_STATE_READY,
        CONNECTION_STATE_UPDATING,
        CONNECTION_STATE_WAITING_FOR_NETWORK,
        CONTACT,
        DOCUMENT,
        FILE,
        FORMATTED_TEXT,
        INPUT_MESSAGE,
        LINK_STATE_IS_CONTACT,
        LINK_STATE_KNOWS_PHONE_NUMBER,
        LINK_STATE_NONE,
        LOCAL_FILE,
        MESSAGE,
        MESSAGE_ACTION,
        MESSAGE_ANIMATION,
        MESSAGE_UNREAD_LABEL,
        MESSAGE_AUDIO,
        MESSAGE_BASIC_GROUP_CHAT_CREATE,
        MESSAGE_SUPER_GROUP_CHAT_CREATE,
        MESSAGE_CALL,
        MESSAGE_CHAT_ADD_MEMBERS,
        MESSAGE_CHAT_CHANGE_PHOTO,
        MESSAGE_CHAT_CHANGE_TITLE,
        MESSAGE_CHAT_DELETE_MEMBER,
        MESSAGE_CHAT_DELETE_PHOTO,
        MESSAGE_CHAT_JOIN_BY_LINK,
        MESSAGE_CHAT_SET_MESSAGE_AUTO_DELETE_TIME,
        MESSAGE_CHAT_UPGRADE_FROM,
        MESSAGE_CHAT_UPGRADE_TO,
        MESSAGE_CUSTOM_SERVICE_ACTION,
        MESSAGE_CONTACT_REGISTERED,
        MESSAGE_CONTACT,
        MESSAGE_DATE,
        MESSAGE_DOCUMENT,
        MESSAGE_HIDDEN,
        MESSAGE_LOCATION,
        MESSAGE_PIN_MESSAGE,
        MESSAGE_POLL,
        MESSAGE_SCREENSHOT_TAKEN,
        MESSAGE_TEXT,
        MESSAGE_PHOTO,
        MESSAGE_STICKER,
        MESSAGE_VIDEO,
        MESSAGE_VIDEO_NOTE,
        MESSAGE_VOICE_NOTE,
        MESSAGE_SENDING_STATE_FAILED,
        MESSAGE_SENDING_STATE_PENDING,
        MESSAGE_SCHEDULING_STATE_AT_DATE,
        MESSAGE_SCHEDULING_STATE_WHEN_ONLINE,
        MESSAGE_UNSUPPORTED,
        MESSAGE_SEND_OPTIONS,
        NETWORK_TYPE_MOBILE,
        NETWORK_TYPE_MOBILE_ROAMING,
        NETWORK_TYPE_NONE,
        NETWORK_TYPE_OTHER,
        NETWORK_TYPE_WIFI,
        NOTIFICATION_SETTINGS,
        PHOTO,
        PHOTO_SIZE,
        POLL,
        POLL_OPTION,
        POLL_TYPE_QUIZ,
        POLL_TYPE_REGULAR,
        PROFILE_PHOTO,
        PROXY_TYPE_HTTP,
        PROXY_TYPE_MTPROTO,
        PROXY_TYPE_SOCKS5,
        REMOTE_FILE,
        SECRET_CHAT_STATE_CLOSED,
        SECRET_CHAT_STATE_PENDING,
        SECRET_CHAT_STATE_READY,
        STICKER,
        STICKER_FORMAT_WEBP,
        STICKER_FORMAT_TGS,
        STICKER_FORMAT_WEBM,
        STICKER_SET_INFO,
        STICKER_TYPE_REGULAR,
        STICKER_TYPE_MASK,
        STICKER_TYPE_CUSTOM_EMOJI,
        TEXT_ENTITY,
        TEXT_ENTITY_TYPE_MENTION,
        TEXT_ENTITY_TYPE_HASHTAG,
        TEXT_ENTITY_TYPE_BOT_COMMAND,
        TEXT_ENTITY_TYPE_URL,
        TEXT_ENTITY_TYPE_EMAIL_ADDRESS,
        TEXT_ENTITY_TYPE_BOLD,
        TEXT_ENTITY_TYPE_ITALIC,
        TEXT_ENTITY_TYPE_CODE,
        TEXT_ENTITY_TYPE_PRE,
        TEXT_ENTITY_TYPE_PRE_CODE,
        TEXT_ENTITY_TYPE_TEXT_URL,
        TEXT_ENTITY_TYPE_MENTION_NAME,
        TEXT_ENTITY_TYPE_PHONE_NUMBER,
        TEXT_ENTITY_TYPE_CASHTAG,
        TEXT_ENTITY_TYPE_SPOILER,
        TEXT_ENTITY_TYPE_STRIKETHROUGH,
        TEXT_ENTITY_TYPE_UNDERLINE,
        TEXT_ENTITY_TYPE_CUSTOM_EMOJI,
        USER,
        USER_FULL_INFO,
        USER_STATUS_EMPTY,
        USER_STATUS_LAST_MONTH,
        USER_STATUS_LAST_WEEK,
        USER_STATUS_OFFLINE,
        USER_STATUS_ONLINE,
        USER_STATUS_RECENTLY,
        USER_TYPE_BOT,
        USER_TYPE_DELETED,
        USER_TYPE_REGULAR,
        USER_TYPE_UNKNOWN,
        VIDEO,
        VIDEO_NOTE,
        VOICE_NOTE,
        WEB_PAGE,
        REPLY_MARKUP_FORCE_REPLY,
        REPLY_MARKUP_INLINE_KEYBOARD,
        REPLY_MARKUP_REMOVE_KEYBOARD,
        REPLY_MARKUP_SHOW_KEYBOARD,
        MESSAGE_FORWARD_ORIGIN_CHAT,
        MESSAGE_FORWARD_ORIGIN_CHANNEL,
        MESSAGE_FORWARD_ORIGIN_HIDDEN_USER,
        MESSAGE_FORWARD_ORIGIN_USER,
        MESSAGE_INTERACTION_INFO,
        MESSAGE_LINK,
        MESSAGE_SENDER_USER,
        MESSAGE_SENDER_CHAT,
        THUMBNAIL,
        THUMBNAIL_FORMAT_GIF,
        THUMBNAIL_FORMAT_JPEG,
        THUMBNAIL_FORMAT_MPEG4,
        THUMBNAIL_FORMAT_PNG,
        THUMBNAIL_FORMAT_TGS,
        THUMBNAIL_FORMAT_WEBP,
        MINITHUMBNAIL,
    };
    Q_ENUM(Type)

    Type type() const;
    QString typeString() const;

    virtual void unmarshalJson(const QJsonObject &json);
    virtual QJsonObject marshalJson();

signals:
    void typeChanged(Type type);

protected:
    void setType(const Type type);

    template <typename T>
    QJsonArray marshalArrayValue(QList<T> inputValues) {
        QJsonArray resultArray;

        for (auto &inputValue : inputValues) {
            resultArray << QJsonValue(inputValue);
        }
        return resultArray;
    }

    Type m_type;
    QString m_typeString;
};

#endif // QABSTRACTTDOBJECT_H
