/***************************************************************************
                       kanswer.cpp  -  description
                          -------------------
 begin                : Fri Nov 30 2001
 copyright            : (C) 2001 by Matthias Messmer <bmlmessmer@web.de> &
                                     Carsten Niehaus <cniehaus@gmx.de> &
                                     Robert Gogolok <mail@robert-gogolok.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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "kanswer.h"

// C/C++ includes
#include <stdlib.h>
#include <assert.h>

// Qt includes
#include <QFile>
#include <QLabel>
#include <QBoxLayout>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QScrollBar>
#include <QTextStream>
#include <QTimer>
#include <QPixmap>
#include <QVBoxLayout>
#include <QAbstractEventDispatcher>

// KDE includes
#include <KDebug>
#include <KIcon>
#include <KLocale>
#include <KPushButton>
#include <KStandardDirs>
#include <KStandardGuiItem>

// local includes
#include "kanimation.h"

KAnswer::KAnswer( QWidget *parent ): KDialog( parent )
{
    setButtons(0);
    setFont( parent->font() );
    // fix size for the background pixmap
    setFixedSize( QSize( 430, 190 ) );

    // load background pixmap
    QPixmap bgp( KStandardDirs::locate( "data", "kpercentage/pics/kanswer_bg.png" ) );

    QPalette palette;
    palette.setBrush( backgroundRole(), QBrush(bgp) );
    setPalette( palette );

    setupSprite();

    ButtonOK = new KPushButton( KStandardGuiItem::ok(), this );
    // for the bottons edges
    ButtonOK->setIcon( KIcon("dialog-ok") );
    // ButtonOK->hide();

    TextLabelAnswer = new QLabel( this );
    // make the label transparent
    TextLabelAnswer->setPalette( palette );

    m_graphicsScene->setBackgroundBrush( bgp );
    m_graphicsView->setBackgroundBrush( bgp );

    ///////
    // begin layouting
    ///////
    delete layout();
    mainLayout = new QHBoxLayout( this );
    mainLayout->setMargin( 0 );
    mainLayout->setDirection(QBoxLayout::LeftToRight);

    // mainLayout->addSpacing( 20 );

    QVBoxLayout *leftLayout = new QVBoxLayout(  );
    mainLayout->addItem( leftLayout );
    leftLayout->setObjectName( "main" );
    leftLayout->setSpacing( -1 );
    // leftLayout->addSpacing( 20 );
    leftLayout->addWidget( m_graphicsView );
    leftLayout->addSpacing( 20 );
    leftLayout->addStretch();

    mainLayout->addSpacing( 60 );

    QVBoxLayout *rightLayout = new QVBoxLayout(  );
    mainLayout->addItem( rightLayout );
    rightLayout->setObjectName( "right" );
    rightLayout->setSpacing( -1 );

    rightLayout->addStretch( 2 );

    QHBoxLayout *topLayout = new QHBoxLayout(  );
    rightLayout->addItem( topLayout );
    topLayout->setObjectName( "top" );
    topLayout->setSpacing( -1 );
    topLayout->setDirection(QBoxLayout::LeftToRight);
    topLayout->addStretch();
    topLayout->addWidget( TextLabelAnswer );
    topLayout->addStretch();

    rightLayout->addStretch( 2 );

    QHBoxLayout *bottomLayout = new QHBoxLayout(  );
    rightLayout->addItem( bottomLayout );
    bottomLayout->setObjectName( "bottom" );
    bottomLayout->setSpacing( -1 );
    bottomLayout->setDirection(QBoxLayout::LeftToRight);
    bottomLayout->addStretch();
    bottomLayout->addWidget( ButtonOK );
    bottomLayout->addSpacing( 20 );

    rightLayout->addSpacing( 20 );
    ///////
    // end layouting
    ///////

    connect( ButtonOK, SIGNAL( clicked() ), this, SLOT( accept() ) );
    loadAnswers();
}

void KAnswer::loadAnswers()
{
    // helping to manage the IO
    QString s;
    QFile f;
    QTextStream t;

    //reading proper answers from file
    f.setFileName( KStandardDirs::locate( "data", "kpercentage/right.txt" ) );
    if ( f.open( QIODevice::ReadOnly ) )        // file opened successfully
    {
        QTextStream t( &f );        // use a text stream
        while ( !t.atEnd() )            // until end of file...
        {
            s = t.readLine();       // line of text excluding '\n'
            rightAnswerList.append( s );
        }
    }
    f.close();

    // reading proper answers from file
    f.setFileName( KStandardDirs::locate( "data", "kpercentage/wrong.txt" ) );
    if ( f.open( QIODevice::ReadOnly ) )        // file opened successfully
    {
        QTextStream t( &f );        // use a text stream
        while ( !t.atEnd() )            // until end of file...
        {
            s = t.readLine();       // line of text excluding '\n'
            wrongAnswerList.append( s );
        }
    }
    f.close();
}

void KAnswer::setAnswer( int modus )
{
    bool correct;
    switch ( modus )
    {
    case 1:
        setCaption( i18n( "Congratulations!" ) );
        TextLabelAnswer->setText( getRightAnswer() );
        correct = true;
        break;
    case 2:
        setCaption( i18n( "Error!" ) );
        TextLabelAnswer->setText( getWrongAnswer() );
        correct = false;
        break;
    case 3:
        setCaption( i18n( "Oops!" ) );
        TextLabelAnswer->setText( i18n( "Mistyped!" ) );
        correct = false;
        break;
    case 4:
        setCaption( i18n( "Congratulations!" ) );
        TextLabelAnswer->setText( i18n( "Great!\nYou managed all\nthe exercises!" ) );
        correct = true;
        break;
    default:
        assert(false);
        correct = false;
    }

    if (correct)
    {
        wrong_animation->hide();
        right_animation->show();
    }
    else
    {
        wrong_animation->show();
        right_animation->hide();
    }

    wrong_animation->setToStart();
    right_animation->setToStart();

    m_sceneAdvanceTimer->start( advPer );

    // this seems to be needed for proper showing TextLabelAnswer :-(
    resize( width(), height() );

    m_graphicsView->resetMatrix();
}

// reads one answer out of the list by chance
QString KAnswer::getRightAnswer()
{
    return i18n( rightAnswerList[ random() % rightAnswerList.count() ].toUtf8() );
}

// reads one answer out of the list by chance
QString KAnswer::getWrongAnswer()
{
    return i18n( wrongAnswerList[ random() % wrongAnswerList.count() ].toUtf8() );
}


// Animation stuff

void KAnswer::setupSprite()
{
    advPer = 80;

    m_graphicsScene = new QGraphicsScene( this );

    /// HACK: the -4 here is to work around the silly margins that QGraphicsView uses
    /// TODO: Fix it, or remove this line if it is fixed in QGraphicsView
    m_graphicsScene->setSceneRect( QRect( 4, 4, width()+4, height()+4 ) );

    QString pics = KStandardDirs::locate( "data", "kpercentage/pics/" )+"smily%1.png";
    right_animation = new KAnimation( KStandardDirs::locate( "data", "kpercentage/story/right.story" ), pics, m_graphicsScene );
    wrong_animation = new KAnimation( KStandardDirs::locate( "data", "kpercentage/story/wrong.story" ), pics, m_graphicsScene );

    m_graphicsView = new QGraphicsView( m_graphicsScene, this );
    m_graphicsView->resize( size() );
    m_graphicsView->resetMatrix();
    m_graphicsView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
    m_graphicsView->horizontalScrollBar()->setValue( 0 );
    m_graphicsView->verticalScrollBar()->setValue( 0 );
    m_graphicsView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
    m_graphicsView->setFrameStyle( QGraphicsView::NoFrame );

    m_sceneAdvanceTimer = new QTimer( this );
    connect( m_sceneAdvanceTimer, SIGNAL(timeout()), m_graphicsScene, SLOT(advance()) );
}


void KAnswer::timerEvent( QTimerEvent *event )
{
    Q_UNUSED( event );
    accept();
}

int KAnswer::exec()
{
    QAbstractEventDispatcher::instance()->unregisterTimers(this);
    startTimer( 3000 ); // 5 seconds
    return KDialog::exec();
}

void KAnswer::accept()
{
    m_sceneAdvanceTimer->stop(); // stop all animation
    KDialog::accept();
}

#include "kanswer.moc"
