//    TapTempo, a command line tap tempo.
//    Copyright (C) 2017 Francois Mazen
//
//    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 <https://www.gnu.org/licenses/>.

#include "taptempogame.h"

#include <libintl.h>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>

TapTempoGame::TapTempoGame(size_t sampleSize, size_t resetTimeInSecond, size_t precision) :
    TapTempo(sampleSize, resetTimeInSecond, precision),
    secretBPM(50)
{
    this->secretBPM = computeNewSecretBPM();
}

void TapTempoGame::displayBPM(double bpm)
{
    if(areBPMEquals(bpm, this->secretBPM))
    {
        printf(gettext("Congratulation, you've found the secret tempo!\n"));
        TapTempo::displayBPM(bpm);

        this->secretBPM = computeNewSecretBPM();
    }
    else if(bpm < this->secretBPM)
    {
        printf(gettext("Faster!"));
    }
    else
    {
        printf(gettext("Slower..."));
    }
}

double TapTempoGame::computeNewSecretBPM()
{
    // Generate a bpm between 50 and 200.

#ifdef __MINGW32__
    // MSYS GCC implementation of random_device returns always the same value,
    // so we fallback to oldschool "time" function.
    std::mt19937 randomGenerator(time(nullptr));
#else
    std::mt19937 randomGenerator(this->randomDevice());
#endif

    std::uniform_int_distribution<int> uniformDistribution(50, 200);
    return (double)uniformDistribution(randomGenerator);
}

bool TapTempoGame::areBPMEquals(double firstBPM, double secondBPM) const
{
    // Compare the string representations.
    std::stringstream firstBpmRepresentation;
    firstBpmRepresentation << std::fixed << std::setprecision(this->getPrecision()) << firstBPM;

    std::stringstream secondBpmRepresentation;
    secondBpmRepresentation << std::fixed << std::setprecision(this->getPrecision()) << secondBPM;

    return firstBpmRepresentation.str() == secondBpmRepresentation.str();
}


