/***************************************************************************
 *   Copyright (C) 2004 by Kraschinski Arnold                              *
 *   arnold.kra67@gmx.de                                                   *
 *                                                                         *
 *   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 Steet, Fifth Floor, Boston, MA 02110-1301, USA.           *
 ***************************************************************************/
#include "qlearning.h"

// Standard C++ header files
#include <stdlib.h>

// Qt headera files
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QScrollArea>
#include <QLabel>
#include <QImage>
#include <QPixmap>
#include <QRect>
#include <QPainter>
#include <QDesktopWidget>
#include <QList>
#include <QKeyEvent>

// KDE header files
#include <klocale.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>

// project header files
#include "kverbos.h"
#include "kverbossettings.h"
#include "verbdata.h"
#include "charbuttonsh.h"
#include "verbviewtrainer.h"
#include "formstrainer.h"
#include "gaptrainer.h"
#include "qtimerview.h"
#include "qcounterview.h"
#include "jigsaw.h"
#include "jigsawshow.h"
#include "controlline.h"



QLearning::QLearning( QWidget* parent )
: QWidget ( parent ), m_activeTrainer( 0 )
{
    m_parent = (Kverbos*)parent;
    
    // Prepare the GUI for the application.
    // The horizontal layout will have two columns: the feedback, the trainer
    QHBoxLayout* layout = new QHBoxLayout;
    layout->setContentsMargins( 0, 0, 0, 0 );

    // The column for all the feedback widgets
    QVBoxLayout* vBoxLeft = new QVBoxLayout();
    vBoxLeft->setContentsMargins( 0, 0, 0, 0 );

    m_scrollArea = new QScrollArea(this);
    m_jigsaw = new Jigsaw (m_scrollArea, KStandardDirs::locate("appdata", "images/rose.jpg"), 12, 8, m_scrollArea );
    prepareJigsaw();
    m_scrollArea->setAlignment( Qt::AlignCenter );
    m_jigsaw->scaleImage( true );
    m_scrollArea->setBackgroundRole(QPalette::Dark);
    m_scrollArea->setWidgetResizable( true );
    m_scrollArea->setWidget(m_jigsaw);
    m_scrollArea->setMaximumWidth( 300 );
    vBoxLeft->addWidget(m_scrollArea);
    connect ( m_jigsaw, SIGNAL( signalJigsawSolved() ), this, SLOT( slotJigsawSolved() ) );

    QHBoxLayout* hBox = new QHBoxLayout();
    hBox->setContentsMargins( 0, 0, 0, 0 );

    m_timer = new QTimerView(this);
    hBox->addWidget( m_timer );
    connect ( m_timer, SIGNAL( signalTimeout() ), m_parent, SLOT( slotTimerExpired() ) );
    connect ( m_parent, SIGNAL ( signalStopTimer() ), m_timer, SLOT ( slotStopTimer() ) );
    connect ( m_parent, SIGNAL ( signalStartTimer() ), m_timer, SLOT ( slotStartTimer() ) );
    m_counter = new QCounterView(this);
    hBox->addWidget( m_counter );
    vBoxLeft->addLayout( hBox );

    layout->addLayout( vBoxLeft );

    // The column with the trainers
    QVBoxLayout* vBoxRight = new QVBoxLayout();
    vBoxRight->setContentsMargins( 0, 0, 0, 0 );
    
    m_stackedLayout = new QStackedLayout();
    m_verbViewTrainer = new VerbViewTrainer(this);
    m_stackedLayout->addWidget(m_verbViewTrainer);
    m_formsTrainer = new FormsTrainer(this);
    m_stackedLayout->addWidget(m_formsTrainer);
    m_gapTrainer = new GapTrainer(this);
    m_stackedLayout->addWidget(m_gapTrainer);
    vBoxRight->addLayout( m_stackedLayout );
    
    m_charButtons = new CharButtonsH(this);
    vBoxRight->addWidget(m_charButtons);
    
    m_charButtons->connectButtons(m_verbViewTrainer);
    m_charButtons->connectButtons(m_formsTrainer);
    connect(m_counter, SIGNAL( someCorrectAnswers(int) ), m_jigsaw, SLOT( slotUncover(int) ) );
    connect(m_verbViewTrainer, SIGNAL(someExerciseSolved(int, int) ), m_counter, SLOT(slotAdd(int, int) ) );
    connect(m_formsTrainer, SIGNAL( someExerciseSolved(int, int) ), m_counter, SLOT( slotAdd(int, int) ) );
    connect(m_gapTrainer, SIGNAL( someExerciseSolved(int, int) ), m_counter, SLOT( slotAdd(int, int) ) );
    connect(m_formsTrainer, SIGNAL( allExercisesAreDone() ), this, SLOT( slotAllExercisesAreDone() ) );
    connect(m_gapTrainer, SIGNAL( allExercisesAreDone() ), this, SLOT( slotAllExercisesAreDone() ) );

    layout->addLayout( vBoxRight );
    
    setLayout(layout);

    // Consider the settings
    applySettings();
}

QLearning::~QLearning() 
{
}

void QLearning::applySettings()
{
    m_charButtons->setVisible( KVerbosSettings::showCharButtons() );
    m_scrollArea->setVisible( KVerbosSettings::showJigsaw() );
}

void QLearning::connectTrainerControlline(ControlLine* controlline)
{
    connect (this, SIGNAL( signalSetNextText(QString) ), controlline, SLOT( slotSetNextText(QString) ) );
    connect (m_formsTrainer, SIGNAL( signalSetNextText(QString) ), controlline, SLOT( slotSetNextText(QString) ) );
    connect (m_gapTrainer, SIGNAL( signalSetNextText(QString) ), controlline, SLOT( slotSetNextText(QString) ) );
}

bool QLearning::startExercise(QString trainer, QString exercise) 
{
    m_activeTrainer = 0;
    // VerbViewTrainer -->
    if ( trainer == "VerbViewTrainer" ) {
        m_stackedLayout->setCurrentWidget( m_verbViewTrainer );
        m_activeTrainer = m_verbViewTrainer;

    // FormsTrainer -->
    } else if ( trainer == "FormsTrainer" ) {
        m_stackedLayout->setCurrentWidget( m_formsTrainer );
        m_activeTrainer = m_formsTrainer;
        // prepare the verbselection
        bool select = ( exercise == "user selection" ) ? true : KVerbosSettings::useSelection();
        QList<Verb*> v = Verbdata::verbPointers( select );
        if ( exercise != "user selection" ) {
            // now delete verbs that don't match the exercise
            int group = -1;
            for (int i = 0; i < Verbdata::GROUPS; i++) {
                if ( Verbdata::GROUPNAMES[i] == exercise )
                    group = i;
            }
            if (group == -1) {
                kDebug() << "Couldn't find the group! " << exercise << endl;
                m_activeTrainer = 0;
            } else {
                QList<Verb*>::iterator it = v.begin();
                while ( it != v.end() ) {
                    if ( Verbdata::GROUPMATCH[ (*it)->family() ] == group ) {
                        it++;
                    } else {
                        it = v.erase( it );
                    }
                }
            }
        }
        
        if ( v.empty() ) {
            KMessageBox::information( this, i18n("You have not yet selected a verb that matches the exercise ""%1"". Go to the settings dialog and select some matching verbs there.", exercise ) );
            m_activeTrainer = 0;
        } else {
            if ( m_activeTrainer != 0 ) {
                QList<Verb*> b;
                QList<Verb*>::iterator it = v.begin();
                while ( it != v.end() ) {
                    if ( (*it)->blocked() ) {
                        b << *it;
                        it = v.erase( it );
                    } else {
                        it++;
                    }
                }
                kDebug() << "ungelernte Verben: " << v.size() << " geblockte Verben: " << b.size();
                if ( v.size() < KVerbosSettings::minimalNumberOfVerbs() ) {
                    // Put the two lists together to get more verbs to learn
                    v << b;
                    b.clear();
                }
                m_formsTrainer->setVerbLists( v, b );
            }
            if ( !m_formsTrainer->prepareTenseList() ) {
                KMessageBox::information( this, i18n("You did not select a tense. Go to the settings dialog and select some tenses." ) );
                m_activeTrainer = 0;
            } else
                m_activeTrainer = ( m_formsTrainer->setExercise() ) ? m_activeTrainer : 0;
        }
        
    // The GapTrainer a HTML-Document is the exercise form elements are the gaps
    } else  if ( trainer == "GapTrainer" ) {
        m_charButtons->setVisible( false );
        m_stackedLayout->setCurrentWidget( m_gapTrainer );
        m_activeTrainer = m_gapTrainer;
        m_gapTrainer->setExercise( exercise );

    // Couldn't find a matching trainer class. This shouldn't happen.
    } else {
        //kDebug() << "A trainer class with the name " << trainer << " doesn't exist." << endl;
        m_activeTrainer = 0;
    }

    if ( m_activeTrainer != 0 ) {
        //if (m_activeTrainer != m_gapTrainer) {
        //    m_jigsaw->coverAll();
        //}
        m_jigsaw->setChanged();
        m_timer->startExercise( KVerbosSettings::clock(), (KVerbosSettings::clock()) ? 0 : KVerbosSettings::minutes() * 60 );
    }
    return ( m_activeTrainer != 0 );
}

void QLearning::stopExercise()
{
    m_timer->slotStopTimer();
    
    // write the information about selected verbs into the config file so that
    // the levels and lastDays are adopted.
    Verbdata::writeSettings();
    m_activeTrainer = 0;
    // For the GapTrainer the buttons are hidden by default. Show them again at the
    // end of the training if wished.
    m_charButtons->setVisible( KVerbosSettings::showCharButtons() );
    
    // reset the text on the next button
    emit signalSetNextText( i18n("Go On") );
}

void QLearning::prepareJigsaw()
{
    QStringList images = KVerbosSettings::imageList();
    int n = images.size();
    QString image = KStandardDirs::locate("appdata", "images/rose.jpg");
    if ( n != 0) {
        image = images[ rand() % n ];
    }
    m_jigsaw->load( image, KVerbosSettings::horizontalParts(), KVerbosSettings::verticalParts() );
}

void QLearning::slotJigsawSolved()
{
    bool startTimer(false);
    if ( m_timer->isRunning() ) {
        m_timer->slotStopTimer();
        startTimer = true;
    }

    QDesktopWidget qdw;
    QRect qr = qdw.screenGeometry(this);

    QPixmap picture = QPixmap::fromImage( m_jigsaw->getImage()->scaled ( QSize( 640, 400 ), Qt::KeepAspectRatio) );

    QPixmap clientArea(640, 400);
    clientArea.fill(QColor(0x696969));
    QPainter bildPaint(&clientArea);

    QRect rect(0, 0, 640, 400);
    QSize sw(clientArea.size());
    double rw = (double)sw.width() / (double)sw.height();
    QSize sp( picture.size() );
    double rp = (double)sp.width() / (double)sp.height();
    if (rw < rp) {
        rect.setWidth(sw.width());
        rect.setHeight( (int)(sw.width() / rp) );
        rect.moveTop((sw.height() - rect.height()) / 2);
    } else {
        rect.setWidth( (int)(sw.height() * rp) );
        rect.setHeight(sw.height());
        rect.moveLeft((sw.width() - rect.width()) / 2);
    }
    bildPaint.drawPixmap( rect, picture );

    JigsawShow* js = new JigsawShow(this);
    js->setMaximumSize( qr.width() * 9 / 10, qr.height() * 9 / 10 );
    js->getLabel()->setPixmap(clientArea);
    //std::cout << "pixmap: " << js->pixmapLabel->size().width() << " " << js->pixmapLabel->size().height() << std::endl;
    js->exec();

    if (startTimer) {
        m_timer->slotStartTimer();
    }
    prepareJigsaw();
}

void QLearning::slotNext()
{
    if ( m_activeTrainer != 0)
        m_activeTrainer->next();
}

void QLearning::slotAllExercisesAreDone()
{
    KMessageBox::information( this, i18n("You solved all tasks in this exercise. You will be brought back to the menu.") );
    emit stopLearning();
}



#include "qlearning.moc"
