/***
 * Warthog Robotics
 * University of Sao Paulo (USP) at Sao Carlos
 * http://www.warthog.sc.usp.br/
 *
 * This file is part of WRJoy project.
 *
 * 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/>.
 ***/

// Includes class header
#include <WRJoy/JoystickGUI/basicsettings.hh>
#include <iostream>

// Includes Qt library
#include <QtCore/QtCore>
#include <QtWidgets/QtWidgets>

// Includes WRJoy
#include <WRJoy/wrjoy.hh>

// Selects WRJoy namespace
using namespace WRJoy;


WRJoy::JoystickGUI::BasicSettings::BasicSettings(Joystick* joystick) {
    // Sets the controlled joystick
    _joystick = joystick;

    // Sets this object name
    this->setObjectName(QString::fromUtf8("Basic settings widget"));

    // Configures widget elements
    configureMainWindow();
    configureToolBar();
    configureCentralWidget();

    // Configures elements connections
    configureConnections();
}


void WRJoy::JoystickGUI::BasicSettings::configureMainWindow() {
    // Creates the tool bar
    _toolBar = this->addToolBar(QString::fromUtf8("Basic settings tool bar"));
    _toolBar->setObjectName(QString::fromUtf8("Basic settings tool bar"));

    // Creates the central widget
    this->setCentralWidget(new QWidget());
    _centralWidget = this->centralWidget();
    _centralWidget->setObjectName(QString::fromUtf8("Basic settings central widget"));
}


void WRJoy::JoystickGUI::BasicSettings::configureToolBar() {
    // Configures the tool bar
    _toolBar->setMovable(false);
    _toolBar->setFloatable(false);
    _toolBar->setIconSize(QSize(24,24));
    _toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);

    // Adds SDL actions
    this->configureSDLActions(_toolBar);
}


void WRJoy::JoystickGUI::BasicSettings::configureSDLActions(QToolBar* toolBar) {
    // Adds the open joystick button
    _openJoystickAction = new QAction(QIcon(QString::fromUtf8(":/open.png")), QString::fromUtf8("Open joystick"), toolBar);
    _openJoystickAction->setObjectName(QString::fromUtf8("Basic settings open joystick action"));
    _openJoystickAction->setCheckable(false);
    _openJoystickAction->setEnabled(true);
    toolBar->addAction(_openJoystickAction);

    // Adds the close joystick button
    _closeJoystickAction = new QAction(QIcon(QString::fromUtf8(":/close.png")), QString::fromUtf8("Close joystick"), toolBar);
    _closeJoystickAction->setObjectName(QString::fromUtf8("Basic settings close joystick action"));
    _closeJoystickAction->setCheckable(false);
    _closeJoystickAction->setEnabled(false);
    toolBar->addAction(_closeJoystickAction);

    toolBar->addSeparator();

    // Adds the update joystick list button
    _updateJoystickListAction = new QAction(QIcon(QString::fromUtf8(":/update.png")), QString::fromUtf8("Update joystick list"), toolBar);
    _updateJoystickListAction->setObjectName(QString::fromUtf8("Basic settings update joysticks list action"));
    _updateJoystickListAction->setCheckable(false);
    _updateJoystickListAction->setEnabled(true);
    toolBar->addAction(_updateJoystickListAction);
}


void WRJoy::JoystickGUI::BasicSettings::configureCentralWidget() {
    // Configures the central widget
    QFormLayout* layout = new QFormLayout(_centralWidget);
    layout->setFormAlignment(Qt::AlignCenter);
    layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
    _centralWidget->setLayout(layout);

    // Creates and configures the joysticks list combo box
    _joysticksComboBox = new QComboBox();
    _joysticksComboBox->setObjectName(QString::fromUtf8("Basic settings joysticks combo box"));
    _joysticksComboBox->setMinimumWidth(360);

    layout->addRow(QString::fromUtf8("Joystick:"), _joysticksComboBox);
    this->updateJoysticksList();
}


void WRJoy::JoystickGUI::BasicSettings::configureConnections() {
    // Configures connections for the actions
    QObject::connect(_openJoystickAction, &QAction::triggered, this, &WRJoy::JoystickGUI::BasicSettings::openJoystick);
    QObject::connect(_closeJoystickAction, &QAction::triggered, this, &WRJoy::JoystickGUI::BasicSettings::closeJoystick);
    QObject::connect(_updateJoystickListAction, &QAction::triggered, this, &WRJoy::JoystickGUI::BasicSettings::updateJoysticksList);

    // Configures connections for the joystick signals
    QObject::connect(_joystick, &Joystick::opened, this, &WRJoy::JoystickGUI::BasicSettings::joystickOpened);
    QObject::connect(_joystick, &Joystick::openFail, this, &WRJoy::JoystickGUI::BasicSettings::joystickOpenFail);
    QObject::connect(_joystick, &Joystick::closed, this, &WRJoy::JoystickGUI::BasicSettings::joystickClosed);
}


void WRJoy::JoystickGUI::BasicSettings::openJoystick() {
    // Opens the joystick
    if (_joysticksComboBox->currentIndex() != -1) {
        _joystick->open(_joysticksComboBox->currentIndex());
        _updateJoystickListAction->setEnabled(false);

    }
    // Shows an error dialog
    else {
        QString dialogTitle   = _joystick->name().append(QString::fromUtf8(" - Open joystick"));
        QString dialogMessage = QString::fromUtf8("Please select a joystick to open!");

        QMessageBox::warning(this, dialogTitle, dialogMessage,
                                        QMessageBox::StandardButtons(QMessageBox::Ok),
                                        QMessageBox::Ok);
    }
}


void WRJoy::JoystickGUI::BasicSettings::closeJoystick() {
    // Shows a confirmation dialog
    QString dialogTitle   = _joystick->name().append(QString::fromUtf8(" - Close joystick"));
    QString dialogMessage = QString::fromUtf8("Are you sure you want to close ").append(_joystick->name()).append(QString::fromUtf8("?"));

    QMessageBox::StandardButton response;
    response = QMessageBox::warning(this, dialogTitle, dialogMessage,
                                    QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
                                    QMessageBox::No);

    // Closes the joystick
    if (response == QMessageBox::Yes) {
        _joystick->close();
        _updateJoystickListAction->setEnabled(true);
    }
}


void WRJoy::JoystickGUI::BasicSettings::updateJoysticksList() {
    // Clears the current joystick list
    _joysticksComboBox->clear();

    // Gets the joysticks list and adds it to the combo box
    QStringList joysticksList = this->availableJoysticks();
    _joysticksComboBox->addItems(joysticksList);
}


void WRJoy::JoystickGUI::BasicSettings::joystickOpened() {
    // Toogles SDL actions
    _openJoystickAction->setEnabled(false);
    _closeJoystickAction->setEnabled(true);
}


void WRJoy::JoystickGUI::BasicSettings::joystickOpenFail(QString sdlError) {
    QString dialogTitle   = _joystick->name().append(QString::fromUtf8(" - Open joystick"));
    QString dialogMessage = QString::fromUtf8("Failed to open ").append(_joystick->name().append(QString::fromUtf8(": ")).append(sdlError));

    QMessageBox::warning(this, dialogTitle, dialogMessage,
                         QMessageBox::StandardButtons(QMessageBox::Ok),
                         QMessageBox::Ok);
}


void WRJoy::JoystickGUI::BasicSettings::joystickClosed() {
    // Toogles SDL actions
    _openJoystickAction->setEnabled(true);
    _closeJoystickAction->setEnabled(false);
}


QStringList WRJoy::JoystickGUI::BasicSettings::availableJoysticks() {
    // Variables
    QStringList joystickList;

    // Gets the number of joysticks
    SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
    SDL_InitSubSystem(SDL_INIT_JOYSTICK);
    int numJoystick = SDL_NumJoysticks();

    // Adds all joysticks to the list
    int i;
    QString str;
    for (i = 0; i < numJoystick; i++) {
        // Creates the joystick string
        str.clear();
        str.append(QString("%1 - %2").arg(i).arg(SDL_JoystickNameForIndex(i)));

        // Adds it to the list
        joystickList << str;
    }

    // Returns the list
    return(joystickList);
}
