#ifndef SCSTWRACE_H
#define SCSTWRACE_H

#include <QObject>
#include <QDebug>
#include <QTimer>
#include <QEventLoop>
#include "scstwtimer.h"
#include "scstwsoundplayer.h"

/*!
 * \brief The ScStwRace class can be used to measure timings of climbing races with multiple lanes at once.
 *
 * The ScStwRace is a container to manage multiple timers at a time and introduces a propper start sequence
 * with start commands ('At your Marks' and 'Ready') and the official IFSC start signal.
 *
 * ## Basic usage:
 *
 * \code
 * ScStwRace race;
 *
 * // add two timers
 * race.addTimer(new ScStwTimer());
 * race.addTimer(new ScStwTimer());
 *
 * // start a race
 * race.start();
 * \endcode
 *
 */
class ScStwRace : public QObject
{
    Q_OBJECT
    Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged)
    Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY  timersChanged)
    Q_PROPERTY(QVariantList nextStartActionDetails READ getNextStartActionDetails NOTIFY nextStartActionDetailsChanged)

public:
    explicit ScStwRace(QObject *parent = nullptr);

    enum RaceState { IDLE, STARTING, WAITING, RUNNING, STOPPED };
    Q_ENUM(RaceState)

    enum StartAction { None = -1, AtYourMarks = 0, Ready = 1, Start = 2 };
    Q_ENUM(StartAction)

    enum NextStartActionDetailAttributes {
        NextStartAction = 0,
        NextStartActionTotalDelay = 1,
        NextStartActionDelayProgress = 2
    };
    Q_ENUM(NextStartActionDetailAttributes);

protected:
    StartAction nextStartAction;
    QList<ScStwTimer *> timers;
    void setState(RaceState newState);

private:
    RaceState state;

    QList<ScStwTimer*> timerEnableQueque;

    QTimer *nextActionTimer;
    QEventLoop *nextActionLoop;

    // sounds
    ScStwSoundPlayer * soundPlayer;


    // some settings
    double soundVolume;

    /*!
     * \brief stores the start action settings
     *
     * \details Stores the settings for the action ScStwRace::AtYourMarks and ScStwRace::Ready. The settings keys are: "Enabled" and "Delay"
     */
    QMap<StartAction, QVariantMap> startActionSettings;


public slots:
    /*!
     * \brief Function to start the race
     *
     * \param asyncronous if the function should just start the start sequence and then quit (true)
     *                    or if if should wait until the start sequence is over and quit after that (false)
     * \return 200: OK; 904: state not matching
     */
    int start(bool asyncronous = true);

    /*!
     * \brief Function to stop the currently running race
     *
     * \return 200: OK; 904: state not matching
     */
    virtual int stop();

    /*!
     * \brief Function to reset a stopped race
     * \return
     */
    virtual int reset();
    virtual int cancel();

    // setters
    bool writeStartActionSetting(StartAction action, bool enabled, int delay);
    bool setSoundVolume(double volume);
    virtual bool addTimer(ScStwTimer *timer);

    // getters
    RaceState getState();
    StartAction getNextStartAction();
    virtual QVariantList getNextStartActionDetails();
    QVariantList getTimerDetailList();

protected slots:


private slots:
    void refreshTimerStates();
    void handleTimerEnable(ScStwTimer* timer);
    int handleFalseStart();
    bool playSoundsAndStartTimers(StartAction thisAction);


    /**
     * \brief Function to declare the winner and looser timers after a timer has been stopped
     */
    void handleTimerStop();

signals:
    void startTimers();
    void stopTimers(int type);
    void resetTimers();
    void stateChanged(RaceState state);
    void nextStartActionChanged();
    void nextStartActionDetailsChanged();
    void timersChanged();


};

#endif // SCSTWRACE_H
