/*
 *   This file is part of Auralquiz
 *   Copyright 2011-2017  JanKusanagi JRR <jancoding@gmx.com>
 *
 *   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 2 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, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "auralwindow.h"


/*****************************************************************************************
 *
 * Constructor
 */
AuralWindow::AuralWindow(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("Auralquiz");
    this->setWindowIcon(QIcon(":/icon/64x64/auralquiz.png"));

    QSettings settings;
    this->resize(settings.value("size", QSize(800, 540)).toSize());
    this->firstRun = settings.value("firstRun", true).toBool();


    if (firstRun)
    {
        qDebug() << "This is the first run";
        QMessageBox::about(this,
                           "Auralquiz - " + tr("First usage"),
                           tr("This seems to be the first time you use Auralquiz.\n"
                              "Before playing, your music will be analyzed.\n"
                              "If needed, you should click the Options button "
                              "and select the folder where your "
                              "Ogg, FLAC and MP3 files are stored.\n\n"
                              "This folder, and sub-folders will be scanned "
                              "so Auralquiz can generate questions and answers "
                              "about your music.\n"
                              "\n"
                              "You need files correctly tagged in order for "
                              "the game to work correctly.\n"
                              "\n"
                              "The scan can take some time, and the program "
                              "will not be responsive until it is complete. "
                              "Please be patient."));
    }

    useOwnColorTheme = settings.value("useOwnColorTheme", false).toBool();
    if (useOwnColorTheme)
    {
        qDebug() << "Using own color theme";
    }
    else
    {
        qDebug() << "Using system colors";
    }


    QString defaultMusicDirectory;
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    defaultMusicDirectory = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
#else
    defaultMusicDirectory = QStandardPaths::standardLocations(QStandardPaths::MusicLocation).first();
#endif

    // If MusicLocation is the same as HOME, don't use it.
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    if (defaultMusicDirectory == QDesktopServices::storageLocation(QDesktopServices::HomeLocation))
    {
        defaultMusicDirectory.clear();
    }
#else
    if (defaultMusicDirectory == QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first())
    {
        defaultMusicDirectory.clear();
    }
#endif

    musicDirectory = settings.value("musicDirectory",
                                    defaultMusicDirectory).toString();
    if (!musicDirectory.isEmpty() && !musicDirectory.endsWith("/"))
    {
        // Adding final "/" if it's not present in chosen path
        musicDirectory.append("/");
    }
    qDebug() << "Music directory:" << this->musicDirectory;


    // Get data directory path
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    this->dataDirectory = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
    this->dataDirectory = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
    qDebug() << "Data directory:" << this->dataDirectory;


    // Create data directory if needed, to store music info later...
    QDir dataDir;
    if (!dataDir.exists(this->dataDirectory))
    {
        qDebug() << "Data directory did not exist. Creating...";
        if (dataDir.mkpath(this->dataDirectory))
        {
            qDebug() << this->dataDirectory << "directory created successfully!";
        }
        else
        {
            qDebug() << this->dataDirectory << "directory could NOT be created";
        }
    }

    difficultyLevel = settings.value("difficultyLevel",
                                     2).toInt(); // normal(2) by default
    numQuestions = settings.value("numQuestions",
                                  25).toInt(); // 25 questions by default
    numPlayers = settings.value("numPlayers",
                                1).toInt(); // 1 player by default


    qDebug() << "Phonon runtime version:" << Phonon::phononVersion();
    qDebug() << "Built with Phonon:" << PHONON_VERSION_STR;
    qDebug() << "* Backend::audioEffects:"
             << Phonon::BackendCapabilities::availableAudioEffects();
    qDebug() << "* Backend::mimeTypes:"
             << Phonon::BackendCapabilities::availableMimeTypes();
    //qDebug() << "* Backend::audioOutputDevices:"
    //         << Phonon::BackendCapabilities::availableAudioOutputDevices();


    playing = false;

    mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(3, 1, 3, 1);

    initWelcomeScreen();
    initPlayingScreen();


    this->playerNames.clear();
    playerNames = settings.value("playerNames",
                                 QStringList() << "1" << "2"  // overriden
                                               << "3" << "4"  // in OptionsDialog
                                               << "5" << "6"
                                               << "7" << "8").toStringList();


    this->setLayout(mainLayout);

    musicAnalyzer = new MusicAnalyzer(musicDirectory, dataDirectory,
                                      musicFiles, this);
    connect(musicAnalyzer, SIGNAL(setStartGameButton(bool,QString,QString)),
            this, SLOT(modifyStartGameButton(bool,QString,QString)));


    postInitTimer = new QTimer(this);
    postInitTimer->setSingleShot(true);
    postInitTimer->setInterval(500);
    connect(postInitTimer, SIGNAL(timeout()),
            musicAnalyzer, SLOT(loadSongList()));
    postInitTimer->start(); // Call loadSongList() from the timer, to avoid the
                            // first-run analyzing all songs without visible window


    // this timer will call createSongList() to reload music, after config update
    postConfigUpdatedTimer = new QTimer(this);
    postConfigUpdatedTimer->setSingleShot(true);
    postConfigUpdatedTimer->setInterval(500);
    connect(postConfigUpdatedTimer, SIGNAL(timeout()),
            musicAnalyzer, SLOT(createSongList()));


    // Timer used to show the Ranking window after a moment
    rankingTimer = new QTimer(this);


    // TEMPORARY ranking tests - START
#if 0
    this->goodAnswers.clear();
    goodAnswers << 3 << 17 << 3 << 4 << 5 << 6 << 8 << 8;
    this->badAnswers.clear();
    badAnswers << 11 << 22 << 33 << 44 << 55 << 66 << 77 << 88;
    this->timedOutAnswers.clear();
    timedOutAnswers << 111 << 222 << 333 << 444 << 555 << 666 << 777 << 888;
    this->score.clear();
    score << goodAnswers[0]*123 << goodAnswers[1]*123 << goodAnswers[2]*123
          << goodAnswers[3]*123 << goodAnswers[4]*123 << goodAnswers[5]*123
          << goodAnswers[6]*123 << goodAnswers[7]*123;

    qDebug() << "Testing scores:" << score;
    Ranking *rankingTest;
    rankingTest = new Ranking(this->score.length(), this->playerNames, this->score,
                          this->goodAnswers, this->badAnswers, this->timedOutAnswers);
    rankingTest->show();
    qDebug() << "test ranking created and shown";
#endif
    // TEMPORARY ranking tests - END
}


/*********************************************************************************
 *
 *  Destructor
 */
AuralWindow::~AuralWindow()
{
    qDebug() << "AuralWindow destroyed";
}




/*******************************************************************************
 *
 * Shuffle song list
 */
void AuralWindow::shuffleMusicFiles()
{
    uint randomSeed;
    randomSeed = (QTime::currentTime().hour())
               + (QTime::currentTime().minute() * 4)
               + (QTime::currentTime().second() * 5)
               + (QTime::currentTime().msec() * 6);
    randomSeed *= 8;
    randomSeed += qrand() % (randomSeed / (QTime::currentTime().second()+1));


    qsrand(randomSeed); // ensure decent randomness based on current time



    int newPosition;
    for (int counter=0; counter != musicFiles[0].length(); ++counter)
    {   newPosition = qrand() % musicFiles[0].length();
        musicFiles[0].swap(0, newPosition); // filename
        musicFiles[1].swap(0, newPosition); // artist
        musicFiles[2].swap(0, newPosition); // title
    }
    qDebug() << "Music Files shuffled. randomSeed:" << randomSeed;
}



/*
 * Update statistics panel
 */
void AuralWindow::updateStatistics()
{
    QString statsTable;
    statsTable = "<table width=95%>"
                 "<tr>"
                 "<td valign=middle>" + tr("Good") + "</td>"
                 "<td>&nbsp;</td>"
                 "<td valign=middle align=right>"
                 + QString("<b>%1</b>").arg(this->goodAnswers[currentPlayer])
                 + "</td></tr>"

                   "<tr></tr>"

                   "<tr>"
                   "<td valign=middle>" + tr("Bad") + "</td>"
                   "<td>&nbsp;</td>"
                   "<td valign=middle align=right>"
                 + QString("<b>%1</b>").arg(this->badAnswers[currentPlayer])
                 + "</td></tr>"

                   "<tr></tr>"

                   "<tr>"
                   "<td valign=middle>" + tr("Timed out") + "</td>"
                   "<td>&nbsp;</td>"
                   "<td valign=middle align=right>"
                 + QString("<b>%1</b>").arg(this->timedOutAnswers[currentPlayer])
                 + "</tr>"
                   "</table>";

    this->statisticsLabel->setText(statsTable);
}


/*****************************************************************************************
 *
 *  Set up the welcome screen, with the logo and main menu
 */
void AuralWindow::initWelcomeScreen()
{
    qDebug() << "Init welcome screen";

    optionsDialog = new OptionsDialog(this);
    connect(optionsDialog, SIGNAL(optionsChanged(bool,QString,bool,int,int,int,QStringList,bool)),
            this, SLOT(updateConfig(bool,QString,bool,int,int,int,QStringList,bool)));


    logoLabel = new QLabel(this);
    logoLabel->setPixmap(QPixmap(":/images/logo.png"));


    startGameButton = new QPushButton(QIcon::fromTheme("media-playback-start",
                                                       QIcon(":/images/button-arrow.png")),
                                      "\n" + tr("&Start game") + "\n",
                                      this);
    connect(startGameButton, SIGNAL(clicked()),
            optionsDialog, SLOT(showPlayMode()));
    startGameButton->setDisabled(true);


    configureButton = new QPushButton(QIcon::fromTheme("configure",
                                                       QIcon(":/images/button-configure.png")),
                                      tr("&Options"),
                                      this);
    connect(configureButton, SIGNAL(clicked()),
            optionsDialog, SLOT(showConfigMode()));


    aboutButton = new QPushButton(QIcon::fromTheme("help-about"),
                                  tr("&About..."),
                                  this);
    connect(aboutButton, SIGNAL(clicked()),
            this, SLOT(showAbout()));

    quitButton = new QPushButton(QIcon::fromTheme("application-exit"),
                                 tr("&Quit"),
                                 this);
    connect(quitButton, SIGNAL(clicked()),
            this, SLOT(close()));

    // Control+Q is handled separately to avoid disabling Alt+Q (or translated equivalent)
    quitAction = new QAction(this);
    quitAction->setShortcut(QKeySequence("Ctrl+Q"));
    connect(quitAction, SIGNAL(triggered()),
            this, SLOT(close()));
    this->addAction(quitAction);


    welcomeLayout = new QVBoxLayout();
    welcomeLayout->setAlignment(Qt::AlignHCenter);

    welcomeLayout->addWidget(logoLabel);
    welcomeLayout->addSpacing(24);

    welcomeLayout->addWidget(startGameButton);
    welcomeLayout->addSpacing(16);

    welcomeLayout->addWidget(configureButton);
    welcomeLayout->addWidget(aboutButton);
    welcomeLayout->addWidget(quitButton);
    welcomeLayout->addSpacing(16);

    welcomeWidget = new QWidget(this);
    welcomeWidget->setLayout(welcomeLayout);

    mainLayout->addWidget(welcomeWidget);
}



/*****************************************************************************************
 *
 *  Set up the playing screen, with progress bar, time bar, score, etc.
 */
void AuralWindow::initPlayingScreen()
{
    qDebug() << "Init playing screen";
    playingWidget = new QWidget(this);


    QFont playerFont;
    playerFont.setPointSize(12);
    playerFont.setBold(true);
    playerNameLabel = new QLabel(":: PLAYER ::", this);
    playerNameLabel->setAlignment(Qt::AlignRight | Qt::AlignTop);
    playerNameLabel->setFont(playerFont);

    QFont questionFont;
    questionFont.setPointSize(20);
    questionFont.setBold(true);
    questionLabel = new QLabel(":: QUESTION ::", this);
    questionLabel->setAlignment(Qt::AlignCenter);
    questionLabel->setFont(questionFont);
    questionLabel->setFrameStyle(QFrame::Raised | QFrame::StyledPanel);


    QFont infoFont;
    infoFont.setPointSize(14);
    infoFont.setBold(true);
    infoFont.setItalic(true);
    infoLabel = new QLabel(":: INFO ::", this);
    infoLabel->setAlignment(Qt::AlignCenter);
    infoLabel->setWordWrap(true);
    infoLabel->setFont(infoFont);


    gameTimer = new QTimer(this);
    gameTimer->setInterval(100); // every 100ms, so it moves fast
    connect(gameTimer, SIGNAL(timeout()), this, SLOT(timerTick()));


    // This will call newQuestion
    preQuestionTimer = new QTimer(this);
    preQuestionTimer->setSingleShot(true);
    connect(preQuestionTimer, SIGNAL(timeout()), this, SLOT(newQuestion()));


    // This will call preQuestion
    postQuestionTimer = new QTimer(this);
    postQuestionTimer->setSingleShot(true);
    postQuestionTimer->setInterval(1500); // 1,5 seconds
    connect(postQuestionTimer, SIGNAL(timeout()), this, SLOT(preQuestion()));



    ///////////////////////////////////////////////////////////////////// Right
    timeBar = new QProgressBar(this);
    timeBar->setOrientation(Qt::Vertical);
    timeBar->setFormat(tr("Time")); // "%v seconds"
    // timeBar's range() and value() will be set upon game start, on toggleScreen()
    timeBar->setToolTip("<b></b>" // HTMLized for wordwrap
                        + tr("Remaining time to answer this question"));

    //////////////////////////////////////////////////////////////////// Bottom
    gameProgressBar = new QProgressBar(this);
    gameProgressBar->setFormat(tr("%v out of %m questions - %p%"));
    // gameProgressBar's range() and value() will be set upon game start, on toggleScreen()
    gameProgressBar->setToolTip("<b></b>"
                                + tr("How many questions you've answered"));

    gameScoreLabel = new QLabel(tr("Score"), this);
    gameScoreLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

    gameScore = new QLCDNumber(5, this);
    gameScore->setSegmentStyle(QLCDNumber::Flat);
    gameScore->display(0);
    gameScore->setToolTip("<b></b>"
                          + tr("Your current score"));


    statusLabel = new QLabel(this);


    endGameButton = new QPushButton(QIcon::fromTheme("media-playback-stop",
                                                     QIcon(":/images/button-cancel.png")),
                                    tr("&End game"),
                                    this);
    endGameButton->setFlat(true);
    connect(endGameButton, SIGNAL(clicked()),
            this, SLOT(confirmEndGame()));



    ///////////////////////////////////////////////////////////////// Left side
    aniNoteMovie.setFileName(":/images/aninote.gif");

    aniNoteLabel = new QLabel(this);
    aniNoteLabel->setMovie(&aniNoteMovie);
    aniNoteLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
    aniNoteLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);


    QFont statsFont;
    statsFont.setPointSize(12);

    statisticsLabel = new QLabel("**STATS**", this);
    statisticsLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
    statisticsLabel->setFont(statsFont);


    statisticsBoxLayout = new QVBoxLayout();
    statisticsBoxLayout->addWidget(statisticsLabel);

    statisticsBox = new QGroupBox(tr("Statistics"), this);
    statisticsBox->setLayout(statisticsBoxLayout);



    //////////////////////////////////////////////////////////////////// Center
    ////       Add the 4 answer buttons, and their font
    answerButton[0] = new QPushButton(QIcon::fromTheme("arrow-right",
                                                       QIcon(":/images/button-arrow.png")),
                                      "ANSWER 1 ----------------",
                                      this);
    connect(answerButton[0], SIGNAL(clicked()),
            this, SLOT(answer1()));

    answerButton[1] = new QPushButton(QIcon::fromTheme("arrow-right",
                                                       QIcon(":/images/button-arrow.png")),
                                      "ANSWER 2 ----------------",
                                      this);
    connect(answerButton[1], SIGNAL(clicked()),
            this, SLOT(answer2()));

    answerButton[2] = new QPushButton(QIcon::fromTheme("arrow-right",
                                                       QIcon(":/images/button-arrow.png")),
                                      "ANSWER 3 ----------------",
                                      this);
    connect(answerButton[2], SIGNAL(clicked()),
            this, SLOT(answer3()));

    answerButton[3] = new QPushButton(QIcon::fromTheme("arrow-right",
                                                       QIcon(":/images/button-arrow.png")),
                                      "ANSWER 4 ----------------",
                                      this);
    connect(answerButton[3], SIGNAL(clicked()),
            this, SLOT(answer4()));

    QFont buttonFont;
    buttonFont.setPointSize(13);
    buttonFont.setBold(true);
    // set font and minimum height in all 4 buttons
    for (int counter = 0; counter != 4; ++counter)
    {
        answerButton[counter]->setFont(buttonFont);

        // Set a minimum width, so it's ok for most titles/names
        answerButton[counter]->setMinimumWidth(512);

        // Make buttons use all space available
        answerButton[counter]->setSizePolicy(QSizePolicy::MinimumExpanding,
                                             QSizePolicy::MinimumExpanding);
    }


    /* Matching QActions to allow independent shortcuts.
     *
     * Using these independent shortcuts avoids a problem with autogenerated
     * shortcuts under Plasma 5.
     *
     * Shortcut blocks are 1/2/3/4, Z/X/C/V, 7/8/9/0 and U/I/O/P
     *
     */
    answerAction1 = new QAction(this);
    answerAction1->setShortcuts(QList<QKeySequence>()
                                << Qt::Key_1 << Qt::Key_Z
                                << Qt::Key_7 << Qt::Key_U);
    connect(answerAction1, SIGNAL(triggered()),
            this, SLOT(answer1()));

    answerAction2 = new QAction(this);
    answerAction2->setShortcuts(QList<QKeySequence>()
                                << Qt::Key_2 << Qt::Key_X
                                << Qt::Key_8 << Qt::Key_I);
    connect(answerAction2, SIGNAL(triggered()),
            this, SLOT(answer2()));

    answerAction3 = new QAction(this);
    answerAction3->setShortcuts(QList<QKeySequence>()
                                << Qt::Key_3 << Qt::Key_C
                                << Qt::Key_9 << Qt::Key_O);
    connect(answerAction3, SIGNAL(triggered()),
            this, SLOT(answer3()));

    answerAction4 = new QAction(this);
    answerAction4->setShortcuts(QList<QKeySequence>()
                                << Qt::Key_4 << Qt::Key_V
                                << Qt::Key_0 << Qt::Key_P);
    connect(answerAction4, SIGNAL(triggered()),
            this, SLOT(answer4()));

    this->addAction(answerAction1);
    this->addAction(answerAction2);
    this->addAction(answerAction3);
    this->addAction(answerAction4);


    // Add the AnswerBox, used in the highest difficulty mode, type-the-answer
    answerBox = new AnswerBox(this);
    answerBox->setFont(buttonFont);
    answerBox->setMinimumWidth(512);
    connect(answerBox, SIGNAL(answered(bool)),
            this, SLOT(answerFromAnswerBox(bool)));

    // Disable player input initially, to avoid problems in the title screen
    this->enablePlayerInput(false);


    /////////////////////////////////////////////////////////////////// Layouts

    playingTopLayout = new QVBoxLayout();
    playingTopLayout->setContentsMargins(0, 0, 0, 0);
    playingTopLayout->addWidget(playerNameLabel);
    playingTopLayout->addWidget(questionLabel,    1);
    playingTopLayout->addWidget(infoLabel,        1);

    statisticsLayout = new QVBoxLayout();
    statisticsLayout->addWidget(aniNoteLabel,  1, Qt::AlignTop | Qt::AlignHCenter);
    statisticsLayout->addSpacing(2);
    statisticsLayout->addStretch(1);
    statisticsLayout->addWidget(statisticsBox, 1);

    answersLayout = new QVBoxLayout();
    answersLayout->addWidget(answerButton[0], 4);
    answersLayout->addSpacing(2);
    answersLayout->addStretch(1);
    answersLayout->addWidget(answerButton[1], 4);
    answersLayout->addSpacing(2);
    answersLayout->addStretch(1);
    answersLayout->addWidget(answerButton[2], 4);
    answersLayout->addSpacing(2);
    answersLayout->addStretch(1);
    answersLayout->addWidget(answerButton[3], 4);

    // TMP FIXME: adding answerBox with great stretch factor to make it look almost centered
    answersLayout->addWidget(answerBox, 22, Qt::AlignVCenter);


    playingMiddleLayout = new QHBoxLayout();
    playingMiddleLayout->addLayout(statisticsLayout, 2);
    playingMiddleLayout->addSpacing(4);
    playingMiddleLayout->addLayout(answersLayout,    9);
    playingMiddleLayout->addSpacing(4);
    playingMiddleLayout->addWidget(timeBar);


    playingProgressLayout = new QHBoxLayout();
    playingProgressLayout->addWidget(gameProgressBar);
    playingProgressLayout->addSpacing(32);
    playingProgressLayout->addWidget(gameScoreLabel);
    playingProgressLayout->addSpacing(16);
    playingProgressLayout->addWidget(gameScore);


    playingBottomLayout = new QHBoxLayout();
    playingBottomLayout->addWidget(statusLabel,   1);
    playingBottomLayout->addWidget(endGameButton, 0, Qt::AlignRight);


    playingLayout = new QVBoxLayout();
    playingLayout->setAlignment(Qt::AlignRight);
    playingLayout->addLayout(playingTopLayout);
    playingLayout->addSpacing(2);
    playingLayout->addStretch(0);
    playingLayout->addLayout(playingMiddleLayout, 1);
    playingLayout->addSpacing(8);
    playingLayout->addStretch(0);
    playingLayout->addLayout(playingProgressLayout);
    playingLayout->addSpacing(4);
    playingLayout->addStretch(0);
    playingLayout->addLayout(playingBottomLayout);
    playingWidget->setLayout(playingLayout);

    mainLayout->addWidget(playingWidget);
    if (useOwnColorTheme)
    {
        this->setThemedColors();
    }


    musicPlayer = Phonon::createPlayer(Phonon::MusicCategory,
                                       Phonon::MediaSource());
    qDebug() << "Phonon::createPlayer()->isValid()? " << musicPlayer->isValid();
    if (!musicPlayer->isValid())
    {
        QMessageBox::warning(this, tr("Sound system error"),
                             tr("There seems to be a problem with "
                                "your sound system.")
                             + "<br><br>"
                             + tr("Maybe you don't have any Phonon backends "
                                  "installed."));
    }

    connect(musicPlayer, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
            this, SLOT(playerStateChanged(Phonon::State,Phonon::State)));




    playingWidget->hide();
}



/******************************************************************************
 *
 *  Switch between the welcome screen and the playing screen, in either way
 *
 */
void AuralWindow::toggleScreen()
{
    if (!playing)
    {   // START game!
        qDebug() << "Starting game";
        welcomeWidget->hide();

        shuffleMusicFiles();

        // Reset everything...
        currentMusicFile = 0;
        this->gameProgressBar->setRange(0, this->numQuestions);
        this->gameProgressBar->setValue(0);
        this->gameScore->display(0); // reset score


        maxTime = 500 / (difficultyLevel + 1);  // In millisec/10
        if (difficultyLevel == 5)
        {
            maxTime += 100;  // Extra time in Hardcore/type-the-answer mode!
        }
        warningTime = maxTime / 4;
        dangerTime = maxTime / 8;

        //this->pieceDuration = maxTime - (maxTime / (difficultyLevel+1));
        this->pieceDuration = maxTime - ( 90 / (difficultyLevel+1) );
                                       // +1 becausec difficulty level can be 0
        if (difficultyLevel == 5)
        {
            pieceDuration -= 5;  // Extra duration in Hardcore level!
        }

        qDebug() << "Max/Warning/Danger times:" << maxTime/6 << warningTime/6
                                                << dangerTime/6 << "secs";
        qDebug() << "Piece duration:" << (maxTime - pieceDuration) / 6 << "secs";

        timeBar->setRange(0, this->maxTime);
        timeBar->setValue(this->maxTime);


        if (difficultyLevel < 5) // Regular mode: show buttons, hide AnswerBox
        {
            answerButton[0]->show();
            answerButton[1]->show();
            answerButton[2]->show();
            answerButton[3]->show();

            answerBox->hide();
        }
        else // Type-the-answer mode: hide buttons and show AnswerBox
        {
            answerBox->show();

            answerButton[0]->hide();
            answerButton[1]->hide();
            answerButton[2]->hide();
            answerButton[3]->hide();
        }

        this->enablePlayerInput(true);

        if (numPlayers > 1)
        {
            this->playerNameLabel->show();
        }
        else
        {
            this->playerNameLabel->hide();
        }


        // Reset stats for all players
        this->score.clear();
        this->goodAnswers.clear();
        this->badAnswers.clear();
        this->timedOutAnswers.clear();
        for (int counter = 0; counter != numPlayers; ++counter)
        {
            score << 0;
            goodAnswers << 0;
            badAnswers << 0;
            timedOutAnswers << 0;
        }


        this->currentPlayer = 0;


        QStringList startStrings; // Randomly choose from a list of "get ready" strings
        startStrings << tr("Starting!")
                     << tr("Let's go!")
                     << tr("GO!!")
                     << tr("Good luck!");
        this->infoLabel->setStyleSheet("background: qradialgradient(spread:pad, "
                                       "cx:0.5, cy:0.5, radius:0.5, fx:0.5, "
                                       "fy:0.5, stop:0 rgba(0, 64, 64, 255) "
                                       "stop:1 rgba(0, 255, 255, 255)); "
                                       "color: white");
        this->infoLabel->setText(startStrings.at(qrand() % startStrings.length()));

        QString totalSongs = QLocale::system()
                                      .toString(this->musicFiles[0].length());
        this->statusLabel->setText(tr("%1 songs available").arg(totalSongs));


        playingWidget->show();

        playing = true;
        this->updateStatistics();


        newQuestion();
    }
    else
    {   // STOP game
        qDebug() << "Stopping game";
        musicPlayer->stop();    // stop music, if any

        gameTimer->stop();

        preQuestionTimer->stop();  // These 2 lines fix problems when clicking
        postQuestionTimer->stop(); // "End Game" right after answering
                                   // (Music in title screen)

        this->enablePlayerInput(false);

        playingWidget->hide();
        welcomeWidget->show();
        playing = false;
    }
}


/*
 *  Set styles to app-specific, or set them empty for user/system-defined
 *
 */
void AuralWindow::setThemedColors() // everything here is quite temporary
{
    // set transparency
    this->setWindowOpacity(0.98);

    // set dark-blue style to the program in general
    this->setStyleSheet("background: qlineargradient(spread:pad,  "
                        "x1:0, y1:0, x2:1, y2:1,           "
                        "stop:0.0 rgba(20, 40, 40,  255),  "
                        "stop:1.0 rgba(20, 40, 120, 255) );"

                        "color: qlineargradient(spread:pad,  "
                        "x1:0, y1:0, x2:1, y2:1,             "
                        "stop:0.0 rgba(140, 140, 220, 255),  "
                        "stop:0.5 rgba(160, 250, 160, 255),  "
                        "stop:1.0 rgba(220, 140, 140, 255) );");

    logoLabel->setStyleSheet("background: transparent");

    aniNoteLabel->setStyleSheet("background: transparent");

    // set colors on answer buttons and answer box
    answerButton[0]->setStyleSheet("background: #20DD20; color: darkBlue");
    answerButton[1]->setStyleSheet("background: #20CC20; color: darkBlue");
    answerButton[2]->setStyleSheet("background: #20BB20; color: darkBlue");
    answerButton[3]->setStyleSheet("background: #20AA20; color: darkBlue");


    answerBox->setStyleSheet("background: #20AA20; color: darkBlue");


    // set color of LCD score indicator
    gameScoreLabel->setStyleSheet("background: transparent");

    gameScore->setStyleSheet("background: black;"
                             "color: lightBlue");


    statisticsBox->setStyleSheet("background: #400000");

    statisticsLabel->setStyleSheet("background: darkRed;"
                                   "color: white");

    statusLabel->setStyleSheet("background: transparent");
}


void AuralWindow::enablePlayerInput(bool state)
{
    if (difficultyLevel < 5)
    {
        // Keyboard keys 1~4, Z~V, 7~0, U~P, and buttons
        answerAction1->setEnabled(state);
        answerAction2->setEnabled(state);
        answerAction3->setEnabled(state);
        answerAction4->setEnabled(state);

        this->answerButton[0]->setEnabled(state);
        this->answerButton[1]->setEnabled(state);
        this->answerButton[2]->setEnabled(state);
        this->answerButton[3]->setEnabled(state);
    }
    else
    {
        this->answerBox->setEnabled(state);
        if (state)
        {
            this->answerBox->setFocus();
        }
    }


    // Always disable the QActions when disabling input; otherwise, they can cause crashes
    if (!state)
    {
        answerAction1->setDisabled(true);
        answerAction2->setDisabled(true);
        answerAction3->setDisabled(true);
        answerAction4->setDisabled(true);
    }
}




///////////////////////////////////////////////////////////////////////////////
////////////////////////////////// SLOTS //////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////




// Used from newQuestion(), via SIGNAL
void AuralWindow::playerStateChanged(Phonon::State newState,
                                     Phonon::State oldState)
{

    qDebug() << "playerStateChanged() (5 means error) -> "
             << oldState << ">" << newState;

    //if (oldState != Phonon::PlayingState
    if ((oldState == Phonon::LoadingState || oldState == Phonon::PausedState)
        && newState == Phonon::StoppedState)
    {
        qDebug() << "Gone from LoadingState to StoppedState";
        this->nextSongLoaded();
    }

    if (newState == Phonon::PausedState)
    {
        qDebug() << "Entered PausedState";
    }

    if (musicPlayer->errorType() != 0) // if some error
    {
        qDebug() << "playerStateChanged(), some error!! State:" << newState;
        qDebug() << "Error string and type:" << musicPlayer->errorString()
                                             << musicPlayer->errorType();
        QMessageBox::warning(this,
                             tr("Error playing sound"),
                             tr("An error occurred while playing sound.\n"
                                "The error message was: %1\n\n"
                                "Maybe your Phonon-backend does not have "
                                "support for the MP3 file "
                                "format.").arg(musicPlayer->errorString()));
    }
}



/*****************************************************************************/



/*
 *  Decrease time left to guess song. Called by gameTimer
 *
 */
void AuralWindow::timerTick()
{
    if (timeBar->value() == this->maxTime-1) // Just once upon start
    {
        // Seek to a random part of the music file
        qint64 seekTime = 10000; // Start at least at 00:10
        // add random ms avoiding last 50 sec, resulting in range 00:10 -> END -01:00
        seekTime += qrand() % (musicPlayer->totalTime() - 50000);

        qDebug() << "Seeking to:" << seekTime / 1000 << "sec /"
                 << "Seekable:" << musicPlayer->isSeekable()
                 << "/ Total time:" << musicPlayer->totalTime() / 1000;

        musicPlayer->play();
        //musicPlayer->pause();
        /*
         *  play() BEFORE seek()
         *  because gstreamer-backend seeks to 0 again on play() apparently...
         */
        musicPlayer->seek(seekTime); // TMPFIX, add error control
        //musicPlayer->play();
    }


    timeBar->setValue(timeBar->value() - 1);

    // Stop music earlier than the time limit to answer the question
    if (timeBar->value() == this->pieceDuration)
    {
        this->musicPlayer->stop();
        this->aniNoteLabel->movie()->stop(); // TMPFIX
        qDebug() << "totalTime, again:" << musicPlayer->totalTime() / 1000; // TMP tests
    }


    // Clear colored info label (good/bad), soon after new question
    if (timeBar->value() == this->maxTime - 10)   // very very TMPFIX
    {
        this->infoLabel->setText("");
        this->infoLabel->setStyleSheet("background: transparent");
    }


    // if remaining time is low, change timeBar colors

    if (timeBar->value() == this->warningTime) // warning level
    {
        timeBar->setStyleSheet("background-color: yellow"); // orange?
    }

    if (timeBar->value() == this->dangerTime)  // danger level
    {
        timeBar->setStyleSheet("background-color: red"); // darkRed?
    }


    // time to answer ended
    if (timeBar->value() == 0)
    {
        qDebug() << "Time's up!";
        musicPlayer->stop();
        this->infoLabel->setStyleSheet("background: "
                                       "qradialgradient(spread:pad, "
                                       "cx:0.5, cy:0.5, radius:0.5, "
                                       "fx:0.5, fy:0.5, stop:0 "
                                       "rgba(64, 0, 0, 255) stop:1 "
                                       "rgba(128, 0, 0, 255)); color: white");
        this->infoLabel->setText(tr("Time's up!!") + "    "
                               + tr("The answer was:") + "  "
                               + musicFiles[questionType].at(currentMusicFile));



        answerQuestion(0);  // 0 means it's timeout, not a button
    }
}



/*
 *  Update configuration from optionsDialog SIGNAL
 *
 */
void AuralWindow::updateConfig(bool startGame, QString directory, bool forceReload,
                               int difficulty, int questions, int players,
                               QStringList playerNameList, bool ownColors)
{
    bool mustReload = false;
    if (this->musicDirectory != directory)
    {
        qDebug() << "musicDirectory has changed, mustReload = true";
        qDebug() << "musicDirectory:" << musicDirectory << "; directory:" << directory;
        mustReload = true; // if music directory's been changed, reload collection info
    }

    this->musicDirectory = directory;
    this->musicAnalyzer->setMusicDirectory(musicDirectory); // inform M.A. about it

    this->difficultyLevel = difficulty;
    this->numQuestions = questions;
    this->numPlayers = players;
    this->playerNames.clear();
    playerNames = playerNameList;
    this->useOwnColorTheme = ownColors;

    qDebug() << "Updated config with: " << startGame << directory << forceReload
                                        << difficulty << questions << players
                                        << playerNameList << ownColors;


    // reload music collection information here if needed
    if (mustReload || forceReload)
    {
        qDebug() << "Reloading music collection information";
        // this->createSongList(); // replaced by a call from a timer
        postConfigUpdatedTimer->start(); // will call createSongList() in 500ms
    }


    // if optionsDialog was called in PlayMode, start game now
    if (startGame)
    {
        if (numPlayers > 1) // in multiplayer, give extra time to prepare
        {
            this->preQuestionTimer->setInterval(2000); // 2 sec
            // FIXME: make configurable?
        }
        else
        {
            this->preQuestionTimer->setInterval(500); // half a sec
        }

        this->toggleScreen();  // Start game!
    }
}



/*
 *  About... box
 */
void AuralWindow::showAbout()
{
    QMessageBox::about(this, tr("About Auralquiz"),
                       QString("<big><b>Auralquiz v%1</b></big>")
                       .arg(qApp->applicationVersion())
                       + "<br />"
                       "Copyright 2011-2017  JanKusanagi"
                       "<br />"
                       "<br />"
                       "<a href=\"https://jancoding.wordpress.com/auralquiz\">"
                       "https://jancoding.wordpress.com/auralquiz</a>"
                       "<br />"
                       "<br />"
                       + tr("Auralquiz loads all your music from a specified "
                            "folder and asks questions about it, playing a "
                            "short piece of each music file as clue.")
                       + "<br />"
                         "<hr />"
                       + tr("English translation by JanKusanagi.",
                            "TRANSLATORS: Change this with your language and name. "
                            "Feel free to add your contact information, such as e-mail. "
                            "If there was another translator before you, add your "
                            "name after theirs ;)")
                       + "<br />"
                         "<br />"
                       + tr("Thanks to all the testers, translators and packagers, "
                            "who help make Auralquiz better!")
                       + "<br />"
                         "<hr />"
                       + tr("Auralquiz is licensed under the GNU GPL license.")
                       + "<br />"
                       + tr("Main screen image and some icons are based on "
                            "Oxygen icons, under LGPL license.")
                       + "<br />"
                         "<br />"
                         "<a href=\"http://www.gnu.org/licenses/gpl-2.0.html\">"
                         "GNU GPL v2</a> - "
                         "<a href=\"http://www.gnu.org/licenses/lgpl-2.1.html\">"
                         "GNU LGPL v2.1</a>"
                         "<br />"
                         "<br />"
                         "<a href=\"https://techbase.kde.org/Projects/Oxygen\">"
                         "techbase.kde.org/Projects/Oxygen</a>"
                         "<br />"
                         "<br />"

                       + QString("<b>Qt</b> v%1 ~ <b>Phonon</b> v%2")
                         .arg(qVersion())
                         .arg(Phonon::phononVersion()));
}




void AuralWindow::modifyStartGameButton(bool enabledState,
                                        QString text,
                                        QString tooltip)
{
    this->startGameButton->setEnabled(enabledState);
    if (!text.isEmpty())
    {
        this->startGameButton->setText("\n" + text + "\n");
        this->startGameButton->setToolTip("<b></b>" // HTMLize, so it gets wordwrap
                                          + tooltip);
    }

    this->startGameButton->setFocus();
}







/******************************************************************************
 *
 *  Prepare a new question, its answers, and play the new song file
 */
void AuralWindow::newQuestion()
{
    qDebug() << "newQuestion()";

    timeBar->setValue(this->maxTime);
    timeBar->setStyleSheet("");

    this->correctAnswer = (qrand() % 4) + 1;  // 1, 2, 3, 4; 0 would mean TIMED UP
    //qDebug() << "correctAnswer:" << this->correctAnswer;

    questionType = (currentMusicFile & 1) + 1; // quite TMPFIX, odd=artist, even=title
    //qDebug() << "questionType: " << questionType;

    if (questionType == 1)
    {
        questionLabel->setText(tr("Who plays this song?"));
    }
    else
    {
        questionLabel->setText(tr("What's the title of this song?"));
    }

    // show current player name in multiplayer mode // FIXME: and avatar!
    if (numPlayers > 1)
    {
        playerNameLabel->setText(tr("Player %1 of %2").arg(currentPlayer + 1)
                                                      .arg(numPlayers)
                                 + "   --   "
                                 + QString("%1").arg(playerNames.at(currentPlayer)));
        gameScore->display(score.at(currentPlayer));
    }


    QString buttonTexts[4];
    int answerCount = 0;

    // FIXME: These checks should be moved to the analyzer, in createSongList()
    int tries = 0;
    while (answerCount < 4)
    {
        buttonTexts[answerCount] = musicFiles[questionType]
                                   .at(qrand() % this->musicFiles[0].length());


        //qDebug() << "answerCount" << answerCount;

        // If text in current button is NOT the correct answer (lowercase comparison!)
        if (buttonTexts[answerCount].toLower() != musicFiles[questionType]
                                                  .at(currentMusicFile).toLower())
        {
            bool isGood = true;
            for (int previousAnswer = 0; previousAnswer != answerCount; ++previousAnswer)
            {
                // Compare strings in LOWERCASE (Metallica ~= metallica)
                if (buttonTexts[answerCount].toLower()
                 != buttonTexts[previousAnswer].toLower())
                {
                    isGood = true;
                    //qDebug() << "is GOOD" << previousAnswer;
                    //qDebug() << "is GOOD" << buttonTexts[answerCount]
                    //                      << buttonTexts[previousAnswer];
                }
                else
                {
                    isGood = false;
                    //qDebug() << "is NOT good; duplicated, break" << previousAnswer;
                    //qDebug() << "is NOT good" << buttonTexts[answerCount]
                    //                          << buttonTexts[previousAnswer];
                    break;
                }
            }

            if (isGood)
            {
                // Set random artists/titles as labels on buttons
                answerButton[answerCount]->setText(buttonTexts[answerCount]);

                ++answerCount;
                tries = 0;
            }

            //qDebug() << "buttonTexts[answerCount]:" << buttonTexts[answerCount];
        }
        ++tries;  /* TMPFIX
                     Temporary way of catching infinite loops
                     if there are not enough different artists or titles */

        if (tries > 50)
        {
            // FIXME: these checks should be done after createSongList()
            qDebug() << "Not enough different titles or artists to create question!";
            answerCount = 999; // "break"
        }
    }

    // quite hacky, TMPFIX
    if (tries < 50) // if no problem with duplicates, meaning we have enough valid files
    {
        // Set correct artist/title on one button
        answerButton[correctAnswer-1]->setText(musicFiles[questionType].at(currentMusicFile));

        // replace "&" by "&&" in buttons, so it doesn't turn into an accelerator
        // Also truncate if answer is too long
        for (int counter=0; counter != 4; ++counter)
        {
            QString fixedAnswer = answerButton[counter]->text();
            fixedAnswer.replace(QRegExp("&"), "&&"); // fix non-accelerator
            fixedAnswer.truncate(64); // avoid wiiiiide buttons
            // FIXME 1.1.x: truncate position should be calculated, not hardcoded
            // For now, 64 seems sane

            answerButton[counter]->setText(fixedAnswer);
        }


        // Set answer for AnswerBox too
        answerBox->setAnswer(musicFiles[questionType].at(currentMusicFile));


        // Re-enable stuff to answer
        this->enablePlayerInput(true);


        musicPlayer->stop();
        musicPlayer->clear(); // Stop playing file and clear queues
        qDebug() << "musicPlayer stopped and cleared";

        musicPlayer->setCurrentSource(QUrl("file://" + musicFiles[0].at(currentMusicFile)));
        qDebug() << "newQuestion(): musicPlayer->setCurrentSource() done";

        qDebug() << "seekable?" << this->musicPlayer->isSeekable(); // checks needed for gstreamer
        qDebug() << "PhononState should change now; "
                    "with Gstreamer-backend it might stop here (BUG)";
    }
    else
    {
        this->toggleScreen();  // Recursive!! :P

        QMessageBox::critical(this, tr("Not enough music files"),
                              tr("You don't have enough music files, "
                                 "or from enough different artists.\n"
                                 "You need music from at least 5 different artists "
                                 "to be able to generate questions."));
    }
}



/*
 *  Called from PlayerStateChanged()
 */
void AuralWindow::nextSongLoaded()
{
    qDebug() << "(playerStateChanged) > nextSongLoaded()";

    /* Put into PlayingState so seeking and getting total time works correctly later
     *
     * A little hacky and maybe unreliable with some backends (TMP / FIXME)
     *
     */
    musicPlayer->play();
    musicPlayer->pause(); // Pause immediately, so the user can't hear anything

    this->aniNoteLabel->movie()->start();
    gameTimer->start(); // will call "timerTick()"
}



void AuralWindow::preQuestion()
{
    if (this->gameProgressBar->value() < this->numQuestions)
    {
        // There are more questions!

        ++currentMusicFile;
        if (currentMusicFile == this->musicFiles[0].length())
        {
            currentMusicFile = 0;
            qDebug() << "Not enough music files to avoid repeating; back to 1st";
        }


        this->updateStatistics();


        infoLabel->setStyleSheet("background: qradialgradient(spread:pad, "
                                 "cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, "
                                 "stop:0 rgba(0, 0, 128, 255) stop:1 "
                                 "rgba(0, 128, 255, 127)); color: white");
        if (numPlayers > 1)
        {
            infoLabel->setText(tr("Go, %1!",
                                  "%1=player's name")
                               .arg(playerNames.at(currentPlayer)));
        }
        else
        {
            infoLabel->setText(tr("Next!"));
        }


        preQuestionTimer->start(); // this will call newQuestion()
    }
    else  // No more questions!
    {
        qDebug() << "End of questions";

        // Show the ranking window
        ranking = new Ranking(numPlayers, playerNames, score,
                              goodAnswers, badAnswers, timedOutAnswers,
                              this);
        connect(ranking, SIGNAL(closed()),
                this, SLOT(killRanking()));

        rankingTimer->setSingleShot(true);
        connect(rankingTimer, SIGNAL(timeout()),
                ranking, SLOT(show()));

        rankingTimer->start(2000); // Wait 2 seconds before showing the ranking


        this->infoLabel->setStyleSheet("background: qradialgradient(spread:pad, "
                                       "cx:0.5, cy:0.5, radius:0.5, fx:0.5, "
                                       "fy:0.5, stop:0 rgba(0, 0, 128, 255) "
                                       "stop:1 rgba(0, 128, 255, 255)); "
                                       "color: white");
        this->infoLabel->setText(tr("All done!"));
    }
}


/**************************************************************************************
 *
 *  Check if answer is correct, give score, and get new question
 */
void AuralWindow::answerQuestion(int numAnswer)
{
    qDebug() << "Answered question with button" << numAnswer;

    this->enablePlayerInput(false);

    this->aniNoteLabel->movie()->stop();

    musicPlayer->stop(); // stop music
                         // This helps Phonon's stateChanged(), avoids silent songs
    gameTimer->stop();



    int questionPoints;
    if (timeBar->value() != 0)
    {
        //questionPoints = (100 * difficultyLevel) + (timeBar->value() / 2); // OLD

        questionPoints = 50 * difficultyLevel+1;
        questionPoints += timeBar->value() / 2;
        questionPoints += 100;
    }
    else
    {
        questionPoints = 0;
        this->timedOutAnswers[currentPlayer]++;
        qDebug() << "Answered by timeout";
    }



    if (questionPoints != 0)
    {
        if (numAnswer == correctAnswer)
        {
            QStringList rightAnswerStrings;
            rightAnswerStrings << tr("Correct!!")
                               << tr("Yeah!")
                               << tr("That's right!")
                               << tr("Good!")
                               << tr("Great!");

            this->infoLabel->setStyleSheet("background: "
                                           "qradialgradient(spread:pad, "
                                           "cx:0.5, cy:0.5, radius:0.5, "
                                           "fx:0.5, fy:0.5, stop:0 "
                                           "rgba(0, 192, 0, 255) "
                                           "stop:1 rgba(0, 255, 0, 0)); "
                                           "color: white");
            this->infoLabel->setText(rightAnswerStrings
                                     .at(qrand() % rightAnswerStrings.length())
                                     + "   ~   "
                                     + tr("%1 by %2",
                                          "1=song title, 2=author name")
                                       .arg("\"" + musicFiles[2].at(currentMusicFile) + "\"")
                                       .arg("\"" + musicFiles[1].at(currentMusicFile) + "\"")
                                     + "   ~   "
                                     + tr("+%1 points!").arg(questionPoints));

            this->score[currentPlayer] += questionPoints;
            gameScore->display(score.at(currentPlayer));
            this->goodAnswers[currentPlayer]++;

            qDebug() << "correct!!" << questionPoints;
        }
        else
        {
            QStringList wrongAnswerStrings;
            wrongAnswerStrings << tr("Wrong!")
                               << tr("No!")
                               << tr("That's not it.")
                               << tr("Ooops!")
                               << tr("FAIL!");

            this->infoLabel->setStyleSheet("background: "
                                           "qradialgradient(spread:pad, "
                                           "cx:0.5, cy:0.5, radius:0.5, "
                                           "fx:0.5, fy:0.5, stop:0 "
                                           "rgba(192, 0, 0, 255) "
                                           "stop:1 rgba(255, 0, 0, 0)); "
                                           "color: white");
            this->infoLabel->setText(wrongAnswerStrings
                                     .at(qrand() % wrongAnswerStrings.length())
                                     + "   " + tr("Correct answer was:") + "  "
                                     + musicFiles[questionType].at(currentMusicFile));
                                    // quite TMPFIX

            this->badAnswers[currentPlayer]++;

            qDebug() << "wrong!";
        }

    }


    this->updateStatistics();


    if (numPlayers > 1)
    {
        this->currentPlayer++;
        if (currentPlayer == numPlayers)
        {
            this->currentPlayer = 0; // back to first player
            qDebug() << "Next question, back to Player 1";
        }
    }



    if (currentPlayer == 0)
    {   // Always on single-player, and after all players answer, in multi
        gameProgressBar->setValue(gameProgressBar->value() + 1);
    }


    postQuestionTimer->start(); // will call preQuestion()
}


// These below... suck
void AuralWindow::answer1()
{
    answerQuestion(1);
}
void AuralWindow::answer2()
{
    answerQuestion(2);
}
void AuralWindow::answer3()
{
    answerQuestion(3);
}
void AuralWindow::answer4()
{
    answerQuestion(4);
}

// This one doesn't suck, actually!
void AuralWindow::answerFromAnswerBox(bool correct)
{
    if (correct)
    {
        answerQuestion(this->correctAnswer);
    }
    else
    {
        answerQuestion(-1); // Answer incorrectly
    }
}

void AuralWindow::confirmEndGame()
{
    int confirm = QMessageBox::question(this,
                                        tr("End game?"),
                                        tr("Are you sure you want to end "
                                           "this game?"),
                                        tr("&Yes, end it"), tr("&No"), "",
                                        1, 1);

    if (confirm == 0 && this->playing) // Ignore if game ended by timeout
    {                                  // while the dialog was present
        qDebug() << "Ending game...";
        this->toggleScreen();
    }
}

void AuralWindow::killRanking()
{
    qDebug() << "deleting Ranking object";
    ranking->deleteLater();

    this->toggleScreen();
}



///////////////////////////////////////////////////////////////////////////////
//////////////////////////////// PROTECTED ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////




/******************************************************************************
 *
 * Store app config upon exit
 */
void AuralWindow::closeEvent(QCloseEvent *event)
{
    QSettings settings;
    settings.setValue("firstRun",         false);
    settings.setValue("size",             this->size());

    settings.setValue("useOwnColorTheme", this->useOwnColorTheme);


    settings.setValue("musicDirectory",   this->musicDirectory);
    settings.setValue("numQuestions",     this->numQuestions);
    settings.setValue("difficultyLevel",  this->difficultyLevel);
    settings.setValue("numPlayers",       this->numPlayers);

    settings.setValue("playerNames",      this->playerNames);

    qDebug("closeEvent: config saved");
    event->accept();
}

