// SPDX-FileCopyrightText: 2019 Linus Jahn <lnj@kaidan.im>
// SPDX-FileCopyrightText: 2020 Melvin Keskin <melvo@olomono.de>
// SPDX-FileCopyrightText: 2020 Jonah Brüchert <jbb@kaidan.im>
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

// Qt
#include <QObject>
#include <QUrl>

class QGeoCoordinate;

const auto MESSAGE_BUBBLE_PADDING_CHARACTER = u'⠀';

constexpr auto EMOJI_PREFIX = u':';
constexpr auto EMOJI_SEPARATOR = u' ';

constexpr auto GROUP_CHAT_USER_MENTION_PREFIX = u'@';
constexpr auto GROUP_CHAT_USER_MENTION_SEPARATOR = u' ';

/**
 * This class contains C++ utilities to be used in QML.
 */
class QmlUtils : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QChar messageBubblePaddingCharacter READ messageBubblePaddingCharacter CONSTANT)
    Q_PROPERTY(QChar emojiPrefix READ emojiPrefix CONSTANT)
    Q_PROPERTY(QChar emojiSeparator READ emojiSeparator CONSTANT)
    Q_PROPERTY(QChar groupChatUserMentionPrefix READ groupChatUserMentionPrefix CONSTANT)
    Q_PROPERTY(QChar groupChatUserMentionSeparator READ groupChatUserMentionSeparator CONSTANT)
    Q_PROPERTY(QString versionString READ versionString CONSTANT)
    Q_PROPERTY(QString applicationDisplayName READ applicationDisplayName CONSTANT)
    Q_PROPERTY(QUrl applicationWebsiteUrl READ applicationWebsiteUrl CONSTANT)
    Q_PROPERTY(QUrl applicationSourceCodeUrl READ applicationSourceCodeUrl CONSTANT)
    Q_PROPERTY(QUrl issueTrackingUrl READ issueTrackingUrl CONSTANT)
    Q_PROPERTY(QUrl donationUrl READ donationUrl CONSTANT)
    Q_PROPERTY(QUrl mastodonUrl READ mastodonUrl CONSTANT)

public:
    static QmlUtils *instance();

    explicit QmlUtils(QObject *parent = nullptr);
    ~QmlUtils() override;

    static QChar messageBubblePaddingCharacter();

    static QChar emojiPrefix();
    static QChar emojiSeparator();

    static QChar groupChatUserMentionPrefix();
    static QChar groupChatUserMentionSeparator();

    Q_INVOKABLE static QString systemCountryCode();

    /**
     * Returns a URL to a given resource file name
     *
     * This will check various paths which could contain the searched file.
     * If the file was found, it'll return a `file://` or a `qrc:/` url to
     * the file.
     */
    Q_INVOKABLE static QString getResourcePath(const QString &resourceName);

    /**
     * Returns the version of the current build.
     */
    static QString versionString();

    /**
     * Returns the name of this application as it should be displayed to users.
     */
    static QString applicationDisplayName();

    /**
     * Returns the URL of this application's website.
     */
    Q_INVOKABLE static QUrl applicationWebsiteUrl();

    /**
     * Returns the URL where the source code of this application can be found.
     */
    static QUrl applicationSourceCodeUrl();

    /**
     * Returns the URL to view and report issues.
     */
    static QUrl issueTrackingUrl();

    /**
     * Returns the URL for donations.
     */
    static QUrl donationUrl();

    /**
     * Returns the URL of this application's Mastodon page.
     */
    static QUrl mastodonUrl();

    /**
     * Returns the URL of an XMPP provider's details page.
     *
     * @param providerJid JID of the XMPP provider
     */
    Q_INVOKABLE static QUrl providerDetailsUrl(const QString &providerJid);

    /**
     * Returns an invitation URL as a string for the given XMPP URI.
     */
    Q_INVOKABLE static QString invitationUrlString(const QString &uri);

    /**
     * Returns the JID of an XMPP URI.
     *
     * If the URI is not valid, a default-constructed string is returned.
     */
    Q_INVOKABLE static QString jid(const QString &uriString);

    /**
     * Returns an XMPP URI for opening a group chat.
     *
     * @param groupChatJid JID of the group chat
     */
    Q_INVOKABLE static QUrl groupChatUri(const QString &groupChatJid);

    /**
     * Returns an XMPP URI as a string for opening a group chat.
     *
     * @param groupChatJid JID of the group chat
     */
    Q_INVOKABLE static QString groupChatUriString(const QString &groupChatJid);

    /**
     * Validates the ID of an encryption key.
     *
     * @param keyId encryption key ID
     *
     * @return whether the key ID is valid
     */
    Q_INVOKABLE static bool validateEncryptionKeyId(const QString &keyId);

    /**
     * Creates a variant of an encryption key ID to be displayed making it easier to read.
     *
     * @param keyId encryption key ID
     *
     * @return displayable key ID
     */
    Q_INVOKABLE static QString displayableEncryptionKeyId(QString keyId);

    /**
     * Returns a string without new lines, unneeded spaces, etc..
     *
     * See QString::simplified for more information.
     */
    Q_INVOKABLE static QString removeNewLinesFromString(const QString &input);

    Q_INVOKABLE static QString quote(QString text);

    /**
     * Copies a URL to the clipboard.
     */
    Q_INVOKABLE static void copyToClipboard(const QUrl &url);

    /**
     * Copies a text to the clipboard.
     */
    Q_INVOKABLE static void copyToClipboard(const QString &text);

    /**
     * Copies an image to the clipboard.
     */
    Q_INVOKABLE static void copyToClipboard(const QImage &image);

    /**
     * Returns a pretty formatted localized data size string.
     */
    Q_INVOKABLE static QString formattedDataSize(qint64 fileSize);

    /**
     * Returns a consistent user color generated from the nickname.
     */
    Q_INVOKABLE static QColor userColor(const QString &id, const QString &name);

    Q_INVOKABLE static QString osmUserAgent();

    Q_INVOKABLE static QString geoUri(const QGeoCoordinate &geoCoordinate);
    Q_INVOKABLE static QGeoCoordinate geoCoordinate(const QString &geoUri);
};
