#include "../headers/scstwstartsoundplayer.h"

ScStwStartSoundPlayer::ScStwStartSoundPlayer(QObject *parent) : QObject(parent)
{
    this->waitLoop = new QEventLoop();

    this->startSoundFile = new QFile(":/sound/StartsignalSound.wav", this);

    if(!this->startSoundFile->open(QFile::ReadOnly)) {
        qWarning() << "Cannot open audio File!!";
        return;
    }

    // init sound format
    QAudioFormat format;
    format.setSampleRate(44100);
    format.setChannelCount(2);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);

    // check if format is valid
    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format)) {
        qWarning() << "Raw audio format not supported by backend, cannot play audio.";
        return;
    }

    this->audioOutput = new QAudioOutput(format);
    this->audioOutput->setCategory("ScStw start sound");

    connect(this->audioOutput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
}

bool ScStwStartSoundPlayer::play(double volume, double *timeOfStop) {

    double st = QDateTime::currentMSecsSinceEpoch();

    // update volume
    this->audioOutput->setVolume(volume);

    // start
    this->audioOutput->start(this->startSoundFile);

    double ed = QDateTime::currentMSecsSinceEpoch();
    qDebug() << "time passed: " << ed-st << " playback elapsed: " << this->audioOutput->elapsedUSecs();

    // wait until the audio output reports the sound is over
    waitLoop->exec();

    qDebug() << "waitLoop exited!! elapsed: " << this->audioOutput->elapsedUSecs() << " processed: " << this->audioOutput->processedUSecs();
    // wait until the sound is actually over
    // the timeOffset is the buffer time before the audio started!
    int timeOffset = ((this->audioOutput->processedUSecs() - this->audioOutput->elapsedUSecs()) / 1000);
    if(timeOffset > 0) {
        QTimer timer;
        timer.singleShot(timeOffset, this->waitLoop, &QEventLoop::quit);
        waitLoop->exec();
    }

    // calculate the point in time where the sound playback actually ended
    if(timeOfStop != nullptr) {
        int latency = (this->audioOutput->processedUSecs() - this->audioOutput->elapsedUSecs()) / 1000;
        *timeOfStop = QDateTime::currentMSecsSinceEpoch() - latency;
    }

    // check for errors and return
    if(this->audioOutput->state() == QAudio::IdleState)
        return true;
    return false;
}

void ScStwStartSoundPlayer::handleStateChanged(QAudio::State newState)
{
    switch (newState) {
        case QAudio::IdleState:
            // Finished playing (no more data)
            qDebug() << "sound reported over!! elapsed: " << this->audioOutput->elapsedUSecs() << " processed: " << this->audioOutput->processedUSecs();
            waitLoop->exit();
            break;

        case QAudio::StoppedState:
            // Stopped for other reasons
            if (this->audioOutput->error() != QAudio::NoError) {
                // Error handling
            }
            break;

        default:
            // ... other cases as appropriate
            break;
    }
}
