/***************************************************************************
 *   Copyright (C) 2005-2006 by Anne-Marie Mahfouf   *
 *   annemarie.mahfouf@free.fr   *
 *                                                                         *
 *   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 "kalculview.h"
#include "settings.h"

#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QLabel>
#include <QPushButton>
#include <QTimer>
#include <QValidator>
#include <QTextStream>

#include <klineedit.h>
#include <klocale.h>
#include <kurl.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include <kclock.h>
#include <kdebug.h>

KalculView::KalculView(QWidget *parent)
    : QWidget(parent)
{
    setAttribute(Qt::WA_StaticContents);
    ui_kalculview.setupUi(this);
    mode = Settings::operation();
    paused = false;
    total = 0;
    correct = 0;
    firstNum = 0;
    secondNum = 0;
    //ui_kalculview.kProgress1->setFormat("%v");
    //ui_kalculview.kProgress2->setFormat("%v");
    ui_kalculview.kProgress1->setMaximum(Settings::numOp());
    ui_kalculview.kProgress2->setMaximum(Settings::numOp());
    clock = new KClock(ui_kalculview.clockFrame);
    ui_kalculview.resultLabel->setText( i18n("Click on the Start button") );
    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else
        clock->setTimeLeft(0);
    //TODO: make sure the upper limit is appropriate for the maximum possible value.
    //If you use multiply and limits of e.g. 50 and 50, it could be higher than 999
    intValidator = new QIntValidator(0, 999, this);
    ui_kalculview.answerLine->setValidator(intValidator);

    connect(ui_kalculview.startButton, SIGNAL(clicked()), this, SLOT(slotStart()));
    connect(ui_kalculview.answerLine, SIGNAL(returnPressed()), this, SLOT(slotCheck()));
    connect(ui_kalculview.pauseButton, SIGNAL(clicked()), this, SLOT(slotPause()));
    connect(clock, SIGNAL(signalTimeout()), this, SLOT(timerDone()));
}

KalculView::~KalculView()
{

}

void KalculView::setLevel(const QString& level)
{
    mode = Level;
    levelQuestionsList.clear();

    int tmpCurrent = 0;
    int tmpPosition;
    QStringList tmpList = level.split("\n");
    for (QStringList::Iterator it = tmpList.begin(); it != tmpList.end();
         ++it, ++tmpCurrent) {
        tmpPosition = (*it).indexOf("=");
        levelQuestionsList.append((*it).left(tmpPosition));
        correctAnswer[tmpCurrent] = (*it).mid(tmpPosition + 2).toInt();
    }
    levelNumberOfQuestions = tmpCurrent;
    
    reset();
}

void KalculView::setPracticeMode(int practiceMode)
{
    mode = practiceMode;
    reset();
}

void KalculView::settingsChanged()
{
    mode = Settings::operation();
    reset();

    //update user name
    emit signalChangeStatusbar(i18n("User: %1", Settings::nameLine()), 100); 
}

void KalculView::displayOperation()
{
    //TODO: Optimize calculation(replace the clumsy while loops)
    ui_kalculview.answerLine->setEnabled(true);
    ui_kalculview.answerLine->setFocus();
    //make sure the numbers are >0 for division
    if (mode == Practice_Division) {
        firstNum = random.getLong(Settings::maxFirst() - 1) + 1;
        secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
    }
    else {
        firstNum = random.getLong(Settings::maxFirst());
        secondNum = random.getLong(Settings::maxSecond());
    }

    // + operation
    if (mode == Practice_Addition ) {
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum + secondNum;
            kDebug() << correctAnswer[total] << endl;
            kDebug() << Settings::max() << endl;
            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst());
                secondNum = random.getLong(Settings::maxSecond()); 
                correctAnswer[total] = firstNum + secondNum;        
            }
        }
        else
            correctAnswer[total] = firstNum + secondNum;
    }
    
    // - operation
    else if (mode == Practice_Subtraction) {
        //make sure the first number is bigger than the second one
        while (firstNum < secondNum)
        {
            firstNum = random.getLong(Settings::maxFirst());
            secondNum = random.getLong(Settings::maxSecond());
        }
        correctAnswer[total] = firstNum - secondNum;
    }

    // * operation
    else if (mode == Practice_Multiplication) {
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum * secondNum;
            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst());
                secondNum = random.getLong(Settings::maxSecond());
                correctAnswer[total] = firstNum * secondNum;
            }
        }
        else
            correctAnswer[total] = firstNum * secondNum;
    }

    // / operation
    else if (mode == Practice_Division ) {
        // make sure the first number is bigger than the second one
        // operations like 4 / 9 might be a little too hard except for preset levels
        while (firstNum < secondNum || (firstNum % secondNum) != 0)
        {
            firstNum = random.getLong(Settings::maxFirst() - 1) + 1;
            secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
        }
           
        if (Settings::max() > 0) {
            correctAnswer[total] = firstNum / secondNum;

            while (correctAnswer[total] > Settings::max())
            {
                firstNum = random.getLong(Settings::maxFirst() - 1 ) + 1;
                secondNum = random.getLong(Settings::maxSecond() - 1) + 1;
                correctAnswer[total] = firstNum / secondNum;
            }
        }
        else
            correctAnswer[total] = firstNum / secondNum;
    } 
                
    if (mode == Practice_Addition) //case?
        questionString[total] = i18n("%1 + %2", QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Subtraction)
        questionString[total] = i18n("%1 - %2", QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Multiplication)
        questionString[total] = i18n("%1 * %2", QString::number(firstNum), QString::number(secondNum));
    else if (mode == Practice_Division)
        questionString[total] = i18n("%1 / %2", QString::number(firstNum), QString::number(secondNum));
    else if (mode == Level) 
        questionString[total] = i18n("%1", levelQuestionsList[total]);

    ui_kalculview.questionLabel->setText(questionString[total]);
}

void KalculView::slotCheck()
{
    if (ui_kalculview.answerLine->text().isEmpty())
        return;
    answerNum[total] = ui_kalculview.answerLine->text().toInt();
    if (correctAnswer[total] != answerNum[total]) 
    {   //TODO: save in config
        QString text = "<qt>";
        text += "<font color=\"red\">" + i18n("Wrong answer.") + "</font><br>";
        text += i18n("Correct Answer:");
        text += "<br>";
        text += questionString[total] + " = " + QString::number(correctAnswer[total]);
        text += "</qt>";
        ui_kalculview.resultLabel->setText(text);
    }
    else
    {
        correct++;
        ui_kalculview.kProgress2->setValue(correct);
        ui_kalculview.resultLabel->setText(i18n("Correct!"));
    }
    total++;
    
    emit signalChangeStatusbar(i18n("User: %1", Settings::nameLine()) + ",  " +
                               i18n("Correct: %1", QString::number(correct)) +
                               i18n(" Total: %1", QString::number(total)), 100);
                               
    ui_kalculview.kProgress1->setValue(total);

    int complete;
    (mode == Level) ? complete = levelNumberOfQuestions : complete = Settings::numOp();
    
    if (total == complete) // if correct == number of questions set
    {
        clock->stop();
        // write statistics in config
        saveResults();
        
        // display result dialog
        displayResultDialog();
        
        // reset everything
        reset();
        emit signalChangeStatusbar(i18n("User: %1", Settings::nameLine()), 100); 
        return;
    }
    
    ui_kalculview.answerLine->clear();
    //wait a bit before next operation
    ui_kalculview.answerLine->setEnabled(false);
    ui_kalculview.questionLabel->clear();
    QTimer::singleShot(1500, this, SLOT(displayOperation()));
}

void KalculView::timerDone()
{
    displayResultDialog();
    reset();
}

void KalculView::slotStart()
{
    ui_kalculview.pauseButton->setEnabled(true);
    ui_kalculview.answerLine->setEnabled(true);
    ui_kalculview.answerLine->setFocus();
    ui_kalculview.questionLabel->setEnabled(true);
    ui_kalculview.startButton->setText(i18n("Stop"));
    ui_kalculview.resultLabel->setText(i18n("Ready"));
    disconnect( ui_kalculview.startButton, SIGNAL( clicked() ), this, SLOT( slotStart() ) );
    connect( ui_kalculview.startButton, SIGNAL( clicked() ), this, SLOT( slotStop() ) );
    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else
        clock->setTimeLeft(0);
    clock->start();
    displayOperation();
    update();
}

void KalculView::slotPause()
{
    if (paused) {
        ui_kalculview.pauseButton->setText(i18n("Pause"));
        clock->setPaused(false);
        ui_kalculview.answerLine->setEnabled(true);
        ui_kalculview.answerLine->setFocus();
        paused = false;
    } else {
        ui_kalculview.pauseButton->setText(i18n("Continue"));
        clock->setPaused(true);
        ui_kalculview.answerLine->setEnabled(false);
        paused = true;
    }
}

void KalculView::saveResults()
{
    KUrl url;
    //save data in .kde/share/kalcul/userName.txt
    QString myString=QString("kalcul/%1.txt").arg(Settings::nameLine());
    QFile myFile;
    myFile.setFileName(KStandardDirs::locateLocal("data", myString));
    if (myFile.open(QIODevice::WriteOnly | QIODevice::Append))  {
        QTextStream textStream(&myFile);
        textStream << Settings::nameLine()<<",";
        //save date and time of the day
        textStream << QDate::currentDate().toString() << ",";
        textStream << QTime::currentTime().toString() << endl;
        //save test time, correct answers, total answers
        if (Settings::timerBool())  {
            int trueTime = Settings::time()*60-clock->timeLeft();
            textStream << trueTime << ","; 
        }
        else
            textStream << clock->timeLeft() << ","; //test duration in seconds
        textStream << correct << "," << total << endl;
        for (int i=0; i<Settings::numOp(); i++)
        {
            textStream<<questionString[i]<<",";
            textStream<< QString::number(correctAnswer[i])<<",";
            textStream<< QString::number(answerNum[i])<<endl;
        }
    myFile.close();
    }
}

void KalculView::slotStop()
{
    //stop the test
    reset();
    disconnect(ui_kalculview.startButton, SIGNAL(clicked()), this, SLOT(slotStop()));
}

void KalculView::reset()
{
    clock->stop();

    if (Settings::timerBool())
        clock->setTimeLeft(Settings::time() * 60);
    else 
        clock->setTimeLeft(0);
    total = 0;
    if (mode == Level) {
        ui_kalculview.kProgress1->setMaximum(levelNumberOfQuestions);
        ui_kalculview.kProgress2->setMaximum(levelNumberOfQuestions);
    } else {
        ui_kalculview.kProgress1->setMaximum(Settings::numOp());
        ui_kalculview.kProgress2->setMaximum(Settings::numOp());
    }
    ui_kalculview.kProgress1->setValue(total);
    ui_kalculview.kProgress2->setValue(total);
    correct = 0;
    ui_kalculview.questionLabel->setText(QString::null);
    ui_kalculview.resultLabel->setText(QString::null);
    ui_kalculview.startButton->setText(i18n("Start"));
    connect(ui_kalculview.startButton, SIGNAL(clicked()), this, SLOT(slotStart()));
    ui_kalculview.pauseButton->setEnabled(false);
    ui_kalculview.answerLine->clear();
    ui_kalculview.answerLine->setEnabled(false);
    emit signalChangeStatusbar(i18n("User: %1", Settings::nameLine()) + ",  " +
                               i18n("Correct: %1", QString::number(correct)) +
                               i18n(" Total: %1", QString::number(total)), 100);
}

void KalculView::displayResultDialog()
{
    //TODO result dialog - SUCKS BIG TIME -  should be replaced with kdeedu own result dialog
    QDialog *resultsDlg = new QDialog;
    ui_results.setupUi(resultsDlg);
    ui_results.resultsLabel->setText(i18n("You have %1 answers right out of %2", correct, total));
    for (int i=0; i < total; i++) {
        ui_results.questionLabel->setText(ui_results.questionLabel->text() + questionString[i] + " =  \n");
        ui_results.correctAnswerLabel->setText(ui_results.correctAnswerLabel->text() + QString::number(correctAnswer[i]) + "\n");
        ui_results.yourAnswerLabel->setText(ui_results.yourAnswerLabel->text() + i18n("Your answer: ") + QString::number(answerNum[i]) + "\n");
    }
    resultsDlg->adjustSize();
    resultsDlg->show();
}

#include "kalculview.moc"

