/***************************************************************************
                              exercisepercentage.cpp
                             -------------------
    begin                : 2008/10/10
    copyright            : (C) 2008 by Tiago Porangaba
    email                : tiago.porangaba@ltia.fc.unesp.br
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "exercisepercentage.h"
#include "exercisepercentage.moc"

/* these includes are needed for KDE support */
#include <kglobal.h>
#include <klineedit.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <knumvalidator.h>

/* these includes are needed for Qt support */
#include <QApplication>
#include <qlabel.h>
#include <qlayout.h>
#include <qpushbutton.h>

//Added by qt3to4:
#include <QGridLayout>

/* standard C++ library includes */
#include <stdlib.h>

#include "rationalwidget.h"
#include "resultwidget.h"
#include "settingsclass.h"

/* ----- public member functions ----- */

/* constructor */
ExercisePercentage::ExercisePercentage(QWidget * parent) :
    ExerciseBase(parent)
{
#ifdef DEBUG
    kDebug() << "constructor ExercisePercentage()";
#endif

    /* create a new task */
    QApplication::setOverrideCursor(Qt::WaitCursor);  /* show the sand clock */
    createTask();
    QApplication::restoreOverrideCursor(); /* show the normal cursor */

    // to validate, that the input is an int
    KIntValidator *valnum = new KIntValidator(this);

    QFont defaultFont = SettingsClass::taskFont();
    defaultFont.setBold(true);
    defaultFont.setPointSize(10);

    // the next thing to do on a button click would be to check the entered
    // result
    m_currentState = _CHECK_TASK;

    taskWidget = new QWidget(this);
    taskWidget->setObjectName("taskWidget");
    checkWidget = new QWidget(this);
    checkWidget->setObjectName("checkWidget");

    baseGrid = new QGridLayout(this);
    baseGrid->setObjectName("baseGrid");
    baseGrid->setColumnStretch(0, 1);

    baseGrid->addWidget(taskWidget, 0, 0);
    baseGrid->addWidget(checkWidget, 0, 1);

    taskLayout = new QGridLayout(taskWidget);
    taskLayout->setObjectName("taskLayout");
    taskLayout->setRowStretch(0, 1);
    taskLayout->setRowStretch(4, 1);
    taskLayout->setColumnStretch(0, 1);
    taskLayout->setColumnStretch(3, 1);

    checkLayout = new QGridLayout(checkWidget);
    checkLayout->setObjectName("checkLayout");

    /* Task: percentage question */
    defaultFont.setPointSize(16);
    m_taskLabel = new QLabel(this);
    m_taskLabel->setObjectName("m_taskLabel");
    m_taskLabel->setFont(defaultFont);
    m_taskLabel->setText(i18nc("%1 percentage of %2", "%1% of %2 = ", m_numberPercentage ,  m_numberPercentageOf));
    taskLayout->addWidget(m_taskLabel, 1, 1, 2, 1);

    /* Input question: result of question */
    answer_edit = new KLineEdit(taskWidget);
    answer_edit->setObjectName("answer_edit");
    answer_edit->setValidator(valnum);   // use the int validator
    answer_edit->setToolTip(i18n("Enter the result of percentage question"));
    answer_edit->setFixedSize(85, 42);
    answer_edit->setAlignment(Qt::AlignHCenter);
    answer_edit->setFont(defaultFont);
    QObject::connect(answer_edit, SIGNAL(returnPressed(const QString &)), this,
                     SLOT(answerReturnPressed(const QString &)));
    taskLayout->addWidget(answer_edit, 1, 2, 2, 1);

    // next is the result widget
    m_resultWidget = new ResultWidget(checkWidget, m_result);
    m_resultWidget->setObjectName("m_resultWidget");
    checkLayout->addWidget(m_resultWidget, 0, 0, 1, 2);

    // the right aligned button
    defaultFont.setPointSize(10);
    m_checkButton = new QPushButton(checkWidget);
    m_checkButton->setObjectName("m_checkButton");
    m_checkButton->setText(i18n("&Check"));
    m_checkButton->setDefault(true);  // is the default button of the dialog
    m_checkButton->setToolTip(i18n("Click on this button to check your result. The button will not work if you have not entered a result yet."));
    m_checkButton->setFont(defaultFont);
    QObject::connect(m_checkButton, SIGNAL(clicked()), this, SLOT(slotCheckButtonClicked()));
    checkLayout->addWidget(m_checkButton, 2, 0);

    // the right aligned button
    m_skipButton = new QPushButton(checkWidget);
    m_skipButton->setObjectName("m_skipButton");
    m_skipButton->setText(i18n("&Skip"));
    m_skipButton->setToolTip(i18n("Click on this button to skip this question."));
    m_skipButton->setFont(defaultFont);
    QObject::connect(m_skipButton, SIGNAL(clicked()), this, SLOT(slotSkipButtonClicked()));
    checkLayout->addWidget(m_skipButton, 2, 1);

    // that the user can start typing without moving the focus
    //numer_edit->setFocus();
    answer_edit->setFocus();

    setLayout(baseGrid);
    taskWidget->setLayout(taskLayout);
    checkWidget->setLayout(checkLayout);

    // add tooltip and qwhatsthis help to the widget
    setToolTip(i18n("In this exercise you have to work with percentage questions."));
    setWhatsThis(i18n("In this exercise you have to enter the fraction of the given number."));

}

/* destructor */
ExercisePercentage::~ExercisePercentage()
{
#ifdef DEBUG
    kDebug() << "destructor ExercisePercentage()";
#endif

    /* no need to delete any child widgets, Qt does it by itself */
}

/** resets the current state, creates a new task and count the last task as
 * wrong, if it wasn't solved (in _NEXT_TASK state) yet
 * mainly used after changing the task parameters */
void ExercisePercentage::forceNewTask()
{
#ifdef DEBUG
    kDebug() << "forceNewTask ExercisePercentage()";
#endif

    if (m_currentState == _CHECK_TASK) {
        // emit the signal for skipped
        signalExerciseSkipped();
    }
    m_currentState = _CHECK_TASK;
    m_checkButton->setText(i18n("&Check"));

    // generate next task
    (void) nextTask();
}


/* ------ public slots ------ */

void ExercisePercentage::update()
{
    // call update of components
    //m_rationalWidget->updateAndRepaint();
    m_resultWidget->updateAndRepaint();

    // update for itself
    ((QWidget *) this)->update();
}


/* ------ private member functions ------ */

void ExercisePercentage::createTask()
{
    // the tasks are hardcoded here; there are some algorithms to convert
    // rational numbers to fractions, but it is not worth the effort here
    switch (int ((double(rand()) / RAND_MAX) * 18 + 1)) {
    case  0 :
        //m_number = KGlobal::locale()->formatNumber(0.5, 1);
        m_numberPercentage = "75";
        m_numberPercentageOf = "1900";
        m_resultPercentage = "1425" ;
        break;
    case  1 :
        //m_number = KGlobal::locale()->formatNumber(0.3, 1);
        m_numberPercentage = "50";
        m_numberPercentageOf = "1800";
        m_resultPercentage = "900" ;
        break;
    case  2 :
        //m_number = KGlobal::locale()->formatNumber(0.6, 1);
        m_numberPercentage = "1";
        m_numberPercentageOf = "1200";
        m_resultPercentage = "12" ;
        break;
    case  3 :
        //m_number = KGlobal::locale()->formatNumber(0.25, 2);
        m_numberPercentage = "10";
        m_numberPercentageOf = "900";
        m_resultPercentage = "90" ;
        break;
    case  4 :
        //m_number = KGlobal::locale()->formatNumber(0.75, 2);
        m_numberPercentage = "100";
        m_numberPercentageOf = "800";
        m_resultPercentage = "800" ;
        break;
    case  5 :
        //m_number = KGlobal::locale()->formatNumber(0.2, 1);
        m_numberPercentage = "75";
        m_numberPercentageOf = "300";
        m_resultPercentage = "225" ;
        break;
    case  6 :
        //m_number = KGlobal::locale()->formatNumber(0.4, 1);
        m_numberPercentage = "10";
        m_numberPercentageOf = "1500";
        m_resultPercentage = "150" ;
        break;
    case  7 :
        //m_number = KGlobal::locale()->formatNumber(0.6, 1);
        m_numberPercentage = "10";
        m_numberPercentageOf = "100";
        m_resultPercentage = "10" ;
        break;
    case  8 :
        //m_number = KGlobal::locale()->formatNumber(0.8, 1);
        m_numberPercentage = "25";
        m_numberPercentageOf = "400";
        m_resultPercentage = "100" ;
        break;
    case  9 :
        //m_number = KGlobal::locale()->formatNumber(0.16, 2);
        m_numberPercentage = "50";
        m_numberPercentageOf = "800";
        m_resultPercentage = "400" ;
        break;
    case 10 :
        //m_number = KGlobal::locale()->formatNumber(0.142857, 6);
        m_numberPercentage = "1";
        m_numberPercentageOf = "400";
        m_resultPercentage = "4" ;
        break;
    case 11 :
        //m_number = KGlobal::locale()->formatNumber(0.125, 3);
        m_numberPercentage = "50";
        m_numberPercentageOf = "600";
        m_resultPercentage = "300" ;
        break;
    case 12 :
        //m_number = KGlobal::locale()->formatNumber(0.375, 3);
        m_numberPercentage = "100";
        m_numberPercentageOf = "1300";
        m_resultPercentage = "1300" ;
        break;
    case 13 :
        //m_number = KGlobal::locale()->formatNumber(0.1, 1);
        m_numberPercentage = "100";
        m_numberPercentageOf = "800";
        m_resultPercentage = "800" ;
        break;
    case 14 :
        //m_number = KGlobal::locale()->formatNumber(0.1, 1);
        m_numberPercentage = "25";
        m_numberPercentageOf = "1400";
        m_resultPercentage = "350" ;
        break;
    case 15 :
        //m_number = KGlobal::locale()->formatNumber(0.05, 2);
        m_numberPercentage = "10";
        m_numberPercentageOf = "1400";
        m_resultPercentage = "140" ;
        break;
    case 16 :
        //m_number = KGlobal::locale()->formatNumber(0.01, 2);
        m_numberPercentage = "1";
        m_numberPercentageOf = "2000";
        m_resultPercentage = "20" ;
        break;
    case 17 :
        //m_number = KGlobal::locale()->formatNumber(0.83, 2);
        m_numberPercentage = "75";
        m_numberPercentageOf = "1000";
        m_resultPercentage = "750" ;
        break;
    default :
    case 18 :
        //m_number = KGlobal::locale()->formatNumber(0.001, 3);
        m_numberPercentage = "75";
        m_numberPercentageOf = "1100";
        m_resultPercentage = "825" ;
        break;
    }

    return;
}

/** - checks, if the user solved the task correctly
        - emits signals if task was solved correctly or wrong */
void ExercisePercentage::showResult()
{
    QString tmp_str; /* to build a string for a label */
    QPalette pal;
    int tmp_result;
    ratio entered_result;
    ratio correct_result;

    // change the tooltip of the check button
    m_checkButton->setToolTip(i18n("Click on this button to get to the next question."));

    answer_edit->setEnabled(false);
    m_skipButton->setEnabled(false);

    //an empty answer field will be interpreted as 0
    if (answer_edit->text().isEmpty() == true)
        answer_edit->setText("0");


    tmp_result = answer_edit->text().toInt();
    entered_result.setNumerator(tmp_result, false);
    entered_result.setDenominator(1, false);
    correct_result.setNumerator(m_resultPercentage.toInt());
    correct_result.setDenominator(1, false);
    if (tmp_result == m_resultPercentage.toInt()) {
        // emit the signal for correct
        signalExerciseSolvedCorrect();
        /* yes, the user entered the correct result */
        m_resultWidget->setResult(entered_result, 1);
    } else {
        // emit the signal for incorrect
        signalExerciseSolvedWrong();
        /* no, the user entered the wrong result */
        m_resultWidget->setResult(correct_result, 0);
    }

    return;
}

/** generate the next task and show it to the user */
void ExercisePercentage::nextTask()
{
    // change the tooltip of the check button
    m_checkButton->setToolTip(i18n("Click on this button to check your result. The button will not work if you have not entered a result yet."));

    answer_edit->setEnabled(true);
    m_skipButton->setEnabled(true);

    m_resultWidget->setResult(m_result, -1);

    /* clear user input */
    answer_edit->setText("");
    answer_edit->setFocus();

    /* create a new task */
    QApplication::setOverrideCursor(Qt::WaitCursor);  /* show the sand clock */
    createTask();
    QApplication::restoreOverrideCursor(); /* show the normal cursor */

    // update the task widget
    QString tempTask = i18nc("%1 percentage of %2", "%1% of %2 = ", m_numberPercentage, m_numberPercentageOf);
    m_taskLabel->setText(tempTask);

    return;
}

/* ------ private slots ------ */

void ExercisePercentage::slotCheckButtonClicked()
{
    if (m_currentState == _CHECK_TASK) {
        // if nothing has been entered by the user, we don't check the result yet
        if (answer_edit->text().isEmpty() == true)
            return;
        m_currentState = _NEXT_TASK;
        m_checkButton->setText(i18n("N&ext"));
        (void) showResult();
    } else {
        m_currentState = _CHECK_TASK;
        m_checkButton->setText(i18n("&Check"));
        (void) nextTask();
    }

    return;
}

void ExercisePercentage::slotSkipButtonClicked()
{
    forceNewTask();
}

void ExercisePercentage::answerReturnPressed(const QString &)
{
    slotCheckButtonClicked();
}
