#ifndef SCSTW_HPP
#define SCSTW_HPP

#include <QObject>
#include <QMap>
#include <QMetaEnum>

/*!
 * \mainpage ScStw Libraries documentation
 *
 * \section intro_sec Introduction
 *
 * This library is meant for usage with the Speed climbing stopwatch project.
 * It contains some helper classes to build a client application for the ScStw basestation with Qt.
 *
 * \section section Installation
 * \code{.sh}
 * cd yourRepo
 * git submodule add https://git.itsblue.de/ScStw/shared-libraries/
 * git submodule update --init --recursive
 * \endcode
 *
 * Add to the list of libraries for the Qt-Secret assembly. For an example you can create Main.Pro in which connect Qt-Secret and your project.pro files as subprojects.
 *
 * Main.pro:
 * \code{.pro}
 * TEMPLATE = subdirs
 * CONFIG += ordered
 *
 * SUBDIRS += \
 *          ScStwLibraries \
 *          MyProject
 *
 * ScStwLibraries.file =  shared-libraries/ScStwLibraries/ScStwLibraries.pro
 * \endcode
 *
 * And in your MyProject.pro include the .pri file:
 * \code{.pro}
 * include($$PWD/../shared-libraries/ScStwLibraries/ScStwLibraries.pri)
 * \endcode
 */

/*!
 * \brief The ScStw class provides some shared functions and enums for use in the ScStw project.
 */
class ScStw : public QObject {
    Q_OBJECT
public:

    /*!
     * \brief The SignalKey enum contains all signal keys a client can subscribe to
     *
     * \see ScStw::signalKeyFromInt()
     */
    enum SignalKey {
        InvalidSignal = -1,
        RaceStateChanged = 9000,
        TimersChanged = 9001,
        ExtensionsChanged = 9002,
        NextStartActionChanged = 9003 /*, ProfilesChanged*/
    };
    Q_ENUM(SignalKey)

    /*!
     * \brief The BaseStationSetting enum contains all settings of the base station that can be changed by a client
     *
     * \see ScStw::baseStationSettingFromInt()
     * \see ScStw::baseStationSettingToString()
     * \see ScStw::baseStationSettingFromString()
     * \see ScStw::baseStationSettings
     */
    enum BaseStationSetting {
        InvalidSetting = -1,
        ReadySoundEnableSetting,
        ReadySoundDelaySetting,
        AtYourMarksSoundEnableSetting,
        AtYourMarksSoundDelaySetting,
        SoundVolumeSetting
    };
    Q_ENUM(BaseStationSetting)

    /*!
     * \brief The SocketCommand enum contains all commands the base station can handle
     *
     * \see ScStw::socketCommandFromInt()
     */
    enum SocketCommand {
        InvalidCommand = -1,

        InitializeSessionCommand = 1,

        StartTimersCommand = 1000,
        StopTimersCommand = 1001,
        ResetTimersCommand = 1002,

        GetRaceStateCommand = 2000,
        GetNextStartActionCommand = 2005,
        GetExtensionsCommand = 2006,
        GetTimersCommand = 2007,
        GetNextStartActionDetailsCommand = 2009,

        WriteSettingCommand = 3000,
        ReadSettingCommand = 3001,

        LoginAthleteCommand = 4000,
        CreateAthleteCommand = 4001,
        DeleteAthleteCommand = 4002,
        GetAtheletesCommand = 4003,
        GetAthleteResultsCommand = 4004,

        UpdateFirmwareCommand = 5000,
        UpdateSystemTimeCommand = 5001,
        PairExtensionsCommand = 5002
    };
    Q_ENUM(SocketCommand);

    /*!
     * \brief The ErrorCode enum contains all error codes that can occur when sending a command to the basestation
     */
    enum StatusCode {
        Success = 200,

        FirmwareAlreadyUpToDateInfo = 304,


        CommandNotFoundError = 404,
        ClientSessionAlreadyActiveError = 407,
        UpdateSignatureInvalidError = 402,
        TimestampTooSmallError = 406,
        RequiredParameterNotGivenError = 405,
        CurrentStateNotVaildForOperationError = 403,
        AccessDeniedError = 401,
        NoSessionActiveError = 408,

        Error = 900,
        NotConnectedError = 910,
        TimeoutError = 911,
        SettingNotAccessibleError = 901,
        InternalError = 950,
        InternalErrorTimerOperationFailed = 951
    };
    Q_ENUM(ScStw::StatusCode)

    /*!
     * \brief SOCKET_MESSAGE_START_KEY contains the key, a message is supposed to start with
     */
    static const char* SOCKET_MESSAGE_START_KEY;

    /*!
     * \brief SOCKET_MESSAGE_END_KEY contains the key, a message is supposed to end with
     */
    static const char* SOCKET_MESSAGE_END_KEY;

    /*!
     * \brief baseStationSettings contains a string with reference to all BaseStationSetting values
     *
     * \see ScStw::BaseStationSetting
     * \see ScStw::baseStationSettingToString()
     * \see ScStw::baseStationSettingFromString()
     */
    static const QMap<QString, ScStw::BaseStationSetting> baseStationSettings;

    /*!
     * \brief Function to convert an int to a BaseStationSetting
     * \param i the int to convert
     * \return a BaseStationSetting
     *
     * \see ScStw::BaseStationSetting
     */
    static BaseStationSetting baseStationSettingfromInt(int i);

    /*!
     * \brief Function to convert a QString to a BaseStationSetting
     * \param s the string to convert
     * \return a BaseStationSetting
     *
     * \see ScStw::BaseStationSetting
     * \see ScStw::baseStationSettingToString()
     */
    static BaseStationSetting baseStationSettingFromString(QString s);

    /*!
     * \brief Function to convert BaseStationSetting to a QString
     * \param s the BaseStationSetting to convert
     * \return a QString
     *
     * \see ScStw::BaseStationSetting
     * \see ScStw::baseStationSettingFromString()
     */
    Q_INVOKABLE static QString baseStationSettingToString(BaseStationSetting s);

    /*!
     * \brief Function to convert an int to a SignalKey
     * \param i the int to convert
     * \return a SignalKey
     *
     * \see ScStw::SignalKey
     */
    static SignalKey signalKeyFromInt(int i);

    /*!
     * \brief Function to convert an int to a SocketCommand
     * \param i the int to convert
     * \return a SocketCommand
     *
     * \see ScStw::SocketCommand
     */
    static SocketCommand socketCommandFromInt(int i);

    /*!
     * \brief Function to compare to string firmware versions in <major>.<minor>.<patch> formar
     * \param a version a
     * \param b version b
     * \return -4: a is of invalid format
     *         -3: major of a is lower than b
     *         -2: minor of a is lower than b
     *         -1: patch of a is lower than b
     *         0:  a and b are identical
     *         1: patch b is lower than a
     *         2: minor of b is lower than a
     *         3: major of b is lower than a
     *         4: b is of invalid format
     */
    static int firmwareCompare(QString a, QString b);

    /*!
     *  \brief Function to convert a value to an enum
     */
    template <typename Enum>
    static Enum toEnumValue(const int &value, bool *ok)
    {
        QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
        return static_cast<Enum>(enumeration.keyToValue(enumeration.valueToKey(value), ok));
    }

    ScStw() : QObject(nullptr) {};
private:
};

#endif // SCSTW_HPP
