/*
 *   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 "optionsdialog.h"


/*
 *   Constructor, called on startup even if options dialog is never shown
 *
 */
OptionsDialog::OptionsDialog(QWidget *parent) : QWidget(parent)
{
    QSettings settings;
    this->setWindowTitle(tr("Game options"));
    this->setWindowIcon(QIcon::fromTheme("configure",
                                         QIcon(":/images/button-configure.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);

    this->resize(settings.value("optionsDialogSize",
                                QSize(700, 380)).toSize());


    playMode = false;


    // FIXME: check if musicdir == home, here too
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    this->musicDirectory = settings.value("musicDirectory",
                                          QDesktopServices::storageLocation(QDesktopServices::MusicLocation)).toString();
#else
    this->musicDirectory = settings.value("musicDirectory",
                                          QStandardPaths::standardLocations(QStandardPaths::MusicLocation)
                                          .first())
                                   .toString();
#endif

    this->reload = false;


    // TOP layout
    musicFromLabel = new QLabel(tr("Using music from:") + " ", this);

    currentMusicDirectoryLabel = new QLabel(this->musicDirectory, this);

    selectMusicDirectoryButton = new QPushButton(QIcon::fromTheme("folder-sound"),
                                                 tr("Select your &music folder..."),
                                                 this);
    connect(selectMusicDirectoryButton, SIGNAL(clicked()),
            this, SLOT(selectMusicDirectory()));

    topLayout = new QHBoxLayout();
    topLayout->addWidget(musicFromLabel);
    topLayout->addWidget(currentMusicDirectoryLabel);
    topLayout->addSpacing(16);
    topLayout->addWidget(selectMusicDirectoryButton);


    // MIDDLE layout
    middleLayout = new QHBoxLayout();

    // left side
    difficultyTopLayout = new QHBoxLayout();

    //// difficulty sub-layout
    difficultyEasy = new QPushButton("< " + tr("&Easier"), this);
    //difficultyEasy->setFlat(true);
    connect(difficultyEasy, SIGNAL(clicked()),
            this, SLOT(setDifficultyEasier()));
    difficultyTopLayout->addWidget(difficultyEasy);

    difficultyLevel = new QSlider(Qt::Horizontal, this);
    difficultyLevel->setRange(0, 5); // 0 = very easy, 5 = hardcore
    difficultyLevel->setValue(settings.value("difficultyLevel", 2).toInt());
    difficultyLevel->setTickInterval(1); // One tick mark for every difficulty level
    difficultyLevel->setTickPosition(QSlider::TicksBothSides);
    connect(difficultyLevel, SIGNAL(valueChanged(int)),
            this, SLOT(updateDifficultyName(int)));
    difficultyTopLayout->addWidget(difficultyLevel);

    difficultyHard = new QPushButton(tr("&Harder") + " >", this);
    //difficultyHard->setFlat(true);
    difficultyTopLayout->addWidget(difficultyHard);
    connect(difficultyHard, SIGNAL(clicked()),
            this, SLOT(setDifficultyHarder()));


    QFont difficultyFont;
    difficultyFont.setPointSize(14);
    difficultyFont.setBold(true);
    difficultyName = new QLabel(this);
    difficultyName->setFont(difficultyFont);
    difficultyName->setAlignment(Qt::AlignCenter);

    difficultyLayout = new QVBoxLayout();
    difficultyLayout->setAlignment(Qt::AlignCenter);
    difficultyLayout->addLayout(difficultyTopLayout);
    difficultyLayout->addWidget(difficultyName);

    middleLayout->addLayout(difficultyLayout);

    updateDifficultyName(this->difficultyLevel->value()); // update difficulty label initially

    middleLayout->addSpacing(32);




    numQuestionsLabel = new QLabel(tr("How many &questions?"), this);

    numQuestions = new QSpinBox(this);
    numQuestions->setRange(1, 99);
    numQuestions->setValue(settings.value("numQuestions", 25).toInt());
    numQuestions->setSuffix(" " + tr("questions"));

    numQuestionsLabel->setBuddy(this->numQuestions);

    numPlayersLabel = new QLabel(tr("How many &players?"), this);

    numPlayers = new QSpinBox(this);
    numPlayers->setRange(1, 8); // up to 8 players
    numPlayers->setValue(settings.value(("numPlayers"), 1).toInt());
    numPlayers->setSuffix(" " + tr("players"));

    numPlayersLabel->setBuddy(this->numPlayers);

    useOwnColors = new QCheckBox(tr("Use own color theme"), this);
    useOwnColors->setChecked(settings.value("useOwnColorTheme",
                                            false).toBool());


    // right side
    rightSideLayout = new QGridLayout();
    rightSideLayout->addWidget(numQuestionsLabel, 0, 0);
    rightSideLayout->addWidget(numQuestions,      0, 1);
    rightSideLayout->addWidget(numPlayersLabel,   1, 0);
    rightSideLayout->addWidget(numPlayers,        1, 1);
    rightSideLayout->addWidget(useOwnColors,      2, 0);

    middleLayout->addLayout(this->rightSideLayout);


    // PLAYER NAMES layout

    playerNamesLayout = new QGridLayout();


    playerNames = settings.value("playerNames",
                                 QStringList() << "Prime"
                                               << "Jazz"
                                               << "Wheeljack"
                                               << "Skyfire"
                                               << "Megatron"
                                               << "Starscream"
                                               << "Soundwave"
                                               << "Astrotrain").toStringList();

    player1Number = new QLabel(" <b>1</b>", this);
    player1Name = new QLineEdit(playerNames.at(0), this);
    player2Number = new QLabel(" <b>2</b>", this);
    player2Name = new QLineEdit(playerNames.at(1), this);
    player3Number = new QLabel(" <b>3</b>", this);
    player3Name = new QLineEdit(playerNames.at(2), this);
    player4Number = new QLabel(" <b>4</b>", this);
    player4Name = new QLineEdit(playerNames.at(3), this);
    player5Number = new QLabel(" <b>5</b>", this);
    player5Name = new QLineEdit(playerNames.at(4), this);
    player6Number = new QLabel(" <b>6</b>", this);
    player6Name = new QLineEdit(playerNames.at(5), this);
    player7Number = new QLabel(" <b>7</b>", this);
    player7Name = new QLineEdit(playerNames.at(6), this);
    player8Number = new QLabel(" <b>8</b>", this);
    player8Name = new QLineEdit(playerNames.at(7), this);

    playerNamesLayout->addWidget(player1Number, 2, 0);
    playerNamesLayout->addWidget(player1Name,   2, 1);
    playerNamesLayout->addWidget(player2Number, 2, 2);
    playerNamesLayout->addWidget(player2Name,   2, 3);
    playerNamesLayout->addWidget(player3Number, 3, 0);
    playerNamesLayout->addWidget(player3Name,   3, 1);
    playerNamesLayout->addWidget(player4Number, 3, 2);
    playerNamesLayout->addWidget(player4Name,   3, 3);
    playerNamesLayout->addWidget(player5Number, 4, 0);
    playerNamesLayout->addWidget(player5Name,   4, 1);
    playerNamesLayout->addWidget(player6Number, 4, 2);
    playerNamesLayout->addWidget(player6Name,   4, 3);
    playerNamesLayout->addWidget(player7Number, 5, 0);
    playerNamesLayout->addWidget(player7Name,   5, 1);
    playerNamesLayout->addWidget(player8Number, 5, 2);
    playerNamesLayout->addWidget(player8Name,   5, 3);

    playerNamesGroup = new QGroupBox(tr("Player names"), this);
    playerNamesGroup->setLayout(playerNamesLayout);



    // BOTTOM layout
    bottomLayout = new QHBoxLayout();

    // This button's text can be START or SAVE CONFIG
    saveButton = new QPushButton("*SAVE/START*", this);
    connect(saveButton, SIGNAL(clicked()),
            this, SLOT(saveOptions()));
    bottomLayout->addWidget(saveButton);

    reloadMusicInfoButton = new QPushButton(QIcon::fromTheme("view-refresh",
                                                             QIcon(":/images/button-refresh.png")),
                                            tr("Save and &reload music"),
                                            this);
    connect(reloadMusicInfoButton, SIGNAL(clicked()),
            this, SLOT(saveAndReload()));
    bottomLayout->addWidget(reloadMusicInfoButton);


    cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                    QIcon(":/images/button-cancel.png")),
                                   tr("&Cancel"),
                                   this);
    connect(cancelButton, SIGNAL(clicked()),
            this, SLOT(close()));
    bottomLayout->addWidget(cancelButton);


    startAction = new QAction(this);
    startAction->setShortcut(Qt::Key_Return);
    connect(startAction, SIGNAL(triggered()),
            this, SLOT(saveOptions()));
    this->addAction(startAction);

    closeAction = new QAction(this);
    closeAction->setShortcut(Qt::Key_Escape);
    connect(closeAction, SIGNAL(triggered()),
            this, SLOT(close()));
    this->addAction(closeAction);


    mainLayout = new QVBoxLayout();
    mainLayout->addLayout(topLayout);
    mainLayout->addStretch(1);
    mainLayout->addLayout(middleLayout);
    mainLayout->addStretch(2);
    mainLayout->addWidget(playerNamesGroup);
    mainLayout->addStretch(3);
    mainLayout->addLayout(bottomLayout);
    this->setLayout(mainLayout);


    qDebug() << "Options window created";
}


OptionsDialog::~OptionsDialog()
{
    qDebug() << "Options window destroyed";
}


void OptionsDialog::showEvent(QShowEvent *event)
{
    this->reload = false; // make forceReload false again
                          // until Reload button is clicked

    qDebug() << "Options window shown";
    event->accept();
}


void OptionsDialog::closeEvent(QCloseEvent *event)
{
    QSettings settings;
    settings.setValue("optionsDialogSize", this->size());

    qDebug() << "Options dialog closed";
    event->accept();
}



/*
 *   Open dialog to select directory where music is located
 *
 */
void OptionsDialog::selectMusicDirectory()
{
    QString newMusicDir;
    newMusicDir = QFileDialog::getExistingDirectory(this,
                                                    tr("Select where your music is located"),
                                                    this->musicDirectory,
                                                    QFileDialog::ShowDirsOnly);
    if (!newMusicDir.isEmpty()) // if user DID NOT cancel the "select directory" dialog
    {
        musicDirectory = newMusicDir;
        if (!musicDirectory.endsWith("/"))
        {
            // Adding final "/" if it's not present in chosen path
            musicDirectory.append("/");
        }
        // update label indicating current path for music
        currentMusicDirectoryLabel->setText(this->musicDirectory);
    }
}



/*
 *   Set difficulty to 1 point less, easier
 *
 */
void OptionsDialog::setDifficultyEasier()
{
    this->difficultyLevel->setValue(this->difficultyLevel->value() - 1);
}


/*
 *   Set difficulty to 1 point more, harder
 *
 */
void OptionsDialog::setDifficultyHarder()
{
    this->difficultyLevel->setValue(this->difficultyLevel->value() + 1);
}




/*
 *   Update the label with the description of the selected difficulty level
 *
 */
void OptionsDialog::updateDifficultyName(int newValue)
{
    qDebug() << "new difficulty level:" << newValue;
    QStringList levels = QStringList(tr("Piece of cake"))
                         << tr("Let's rock")
                         << tr("Come get some")
                         << tr("Damn I'm good")
                         << tr("HARD!!")
                         << tr("Hardcore! Type the answer");

    this->difficultyName->setText("[ " + levels.at(newValue) + " ]");

    if (newValue == 5) // Hardcore level
    {
        difficultyName->setToolTip("<b></b>"
                                   + tr("In this level you'll have to type "
                                        "the answer.")
                                   + "<br>"
                                   + tr("It's not too strict, so you don't "
                                        "have to worry about caps, commas "
                                        "and such."));
    }
    else
    {
        difficultyName->setToolTip("<b></b>"
                                   + tr("In this level you'll have to click "
                                        "the correct button, or press the "
                                        "1, 2, 3 and 4 keys in your keyboard."));
    }
}



/*
 *   Emit signal with new option values to AuralWindow
 *
 */
void OptionsDialog::saveOptions()
{
    playerNames.clear();
    playerNames << player1Name->text()
                << player2Name->text()
                << player3Name->text()
                << player4Name->text()
                << player5Name->text()
                << player6Name->text()
                << player7Name->text()
                << player8Name->text();

    // If a player name from the list is empty, replace with number
    for (int counter=0; counter < playerNames.length(); ++counter)
    {
        if (playerNames.at(counter).trimmed().isEmpty())
        {
            playerNames[counter] = QString("[%1]").arg(counter+1);
        }
    }



    // FIXME: this IF code is duplicated 3 times
    if (!musicDirectory.endsWith("/"))
    {
        // Adding final "/" if it's not present in chosen path
        musicDirectory.append("/");
    }


    emit optionsChanged(this->playMode,
                        this->musicDirectory,
                        this->reload,
                        this->difficultyLevel->value(),
                        this->numQuestions->value(),
                        this->numPlayers->value(),
                        this->playerNames,
                        this->useOwnColors->isChecked());


    qDebug() << "Options saved";
    qDebug() << "playMode:" << this->playMode;
    this->close();
}


void OptionsDialog::saveAndReload()
{
    this->reload = true;
    qDebug() << "Save and reload music pressed";

    saveOptions();
}


/*
 *  Show Options window in full configuration mode
 *  Used from the "Options" button
 */
void OptionsDialog::showConfigMode()
{
    playMode = false;

    this->musicFromLabel->show();
    this->currentMusicDirectoryLabel->show();
    this->selectMusicDirectoryButton->show();
    this->reloadMusicInfoButton->show();

    this->useOwnColors->show();

    bottomLayout->setAlignment(Qt::AlignBottom | Qt::AlignRight);

    this->saveButton->setIcon(QIcon::fromTheme("document-save",
                                               QIcon(":/images/button-save.png")));
    this->saveButton->setText(tr("&Save options"));
    this->saveButton->setMinimumSize(1, 1);
    this->cancelButton->show();

    this->startAction->setDisabled(true);

    this->show();
}


/*
 *  Show Options window in a "light mode"
 *  This will be used from Start Game button, to set players and difficulty only
 *  (music config and theme options will be hidden)
 */
void OptionsDialog::showPlayMode()
{
    playMode = true;

    this->musicFromLabel->hide();
    this->currentMusicDirectoryLabel->hide();
    this->selectMusicDirectoryButton->hide();
    this->reloadMusicInfoButton->hide();

    this->useOwnColors->hide();

    bottomLayout->setAlignment(Qt::AlignBottom | Qt::AlignCenter);

    this->saveButton->setIcon(QIcon::fromTheme("media-playback-start",
                                               QIcon(":/images/button-arrow.png")));
    this->saveButton->setText(tr("Start!"));
    this->saveButton->setMinimumSize(240, 60);
    this->cancelButton->hide();

    this->startAction->setEnabled(true); // Allows 'Enter' to continue

    this->show();
}
