/****************************************************************************
 ** ScStw Libraries
 ** Copyright (C) 2020  Itsblue development
 **
 ** 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/>.
 ****************************************************************************/

#ifndef SCSTWSTARTSOUNDPLAYER_H
#define SCSTWSTARTSOUNDPLAYER_H

#include <QObject>
#include <QFile>
#include <QAudioOutput>
#include <QDebug>
#include <QEventLoop>
#include <QTimer>
#include <QDateTime>
#include <QSoundEffect>
#include <QAudioDeviceInfo>

#ifdef ScStwLibraries_Raspi
#include <alsa/asoundlib.h>
#endif

/*!
 * \brief The ScStwSoundPlayer class is used for ultra low latency sound playback of the speed clibing start tones and commands
 */
class ScStwSoundPlayer : public QObject
{
    Q_OBJECT
public:
    /*!
     * \brief ScStwSoundPlayer constructor
     * \param parent
     */
    explicit ScStwSoundPlayer(QObject *parent = nullptr);

    enum StartSound {
        None = -1,
        AtYourMarks = 0,
        Ready = 1,
        Start = 2,
        FalseStart = 3
    };

    enum PlayResult {
        Success = 0,
        Cancelled = -1,
        Error = -2
    };

private:

    bool _setSoundVolume(double volume);

    void _initializeSondEffect();

    /*!
     * \brief A map containing all sound files
     * 0: AtYourMarksSound
     * 1: ReadySound
     * 2: StartSound
     * 3: FalseStartSound
     */
    QMap<StartSound, QVariantMap> soundFiles;

    /*!
     * \brief The sound effect object
     */
    QSoundEffect *soundEffect;

    QAudioDeviceInfo *_audioOutputDevice;

    /*!
     * \brief The QEventLoop used to wait for the sound to finish
     */
    QEventLoop *waitLoop;

    /*!
     * \brief The QTimer to wait for the sound to finish
     */
    QTimer *waitTimer;

    /*!
     * \brief The action that is currently played
     */
    StartSound currentlyPlayingSound;

    /*!
     * \brief Holds the time the playback started at
     */
    double playingStartedAt;

public slots:

    /*!
     * \brief Function to begin playing the sound of a certain state
     * \param action The action to play (0: AtYourMarks, 1:Ready, 2:Start)
     * \param volume The volume to play at
     * \param timeOfStop The time the playback actually started (msecs since epoch)
     * \return TODO true if the playback was successfully started, false otherwise
     */
    ScStwSoundPlayer::PlayResult play(StartSound sound, double volume, double *timeOfStart = nullptr);

    /*!
     * \brief Function to wait for the playback to finish
     * \param timeOfStop the point in time when the plyback actually stopped (msecs since epoch)
     * \return false if there was any error (eg. there was no playback currently), true otherwise
     */
    ScStwSoundPlayer::PlayResult waitForSoundFinish(double *timeOfStop = nullptr);

    /*!
     * \brief Function to cancel the current playback
     *
     * Note that this function will automatically play the false start tone if the currently playing action is 2
     *
     * \param volume the volume to play the false start sound at
     * \return true if the playback was successfully stopped, false otherwise
     */
    bool cancel();

    bool isPlaying();

private slots:

signals:

    /*!
     * \brief Emitted whenever a playback started
     */
    void playbackStarted();

};

#endif // SCSTWSTARTSOUNDPLAYER_H
