/***************************************************************************
                          keducaview.cpp  -  description
                             -------------------
    begin                : Thu May 24 2001
    copyright            : (C) 2001 by Javier Campos
    email                : javi@asyris.org
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "keducaview.h"
#include "keducaview.moc"
#include "settings.h"
#include "../libkeduca/fileread.h"
#include "kquestion.h"
#include "kgroupeduca.h"

#include <stdlib.h>

#include <tdelocale.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include <kpushbutton.h>
#include <kdebug.h>
#include <tdeio/netaccess.h>

#include <tqtimer.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqtextedit.h>

KEducaView::KEducaView( TQWidget *parent, const char *name )
    : TQWidgetStack( parent, name ), _keducaFile( 0 ), _timeoutTimer( 0 )
{
    init();
}

KEducaView::~KEducaView()
{
    delete _questionText;
    delete _buttonGroup;
    delete _split;
    delete _buttonNext;
    delete _buttonSave;
    delete _viewResults;
    delete _keducaFile;
}

/** Init graphical interface */
void KEducaView::init()
{
    // Intro Screen
    _introWidget = new TQLabel( this, "introScreen" );
    _introWidget->setBackgroundColor( TQt::white );
    _introWidget->setAlignment( AlignCenter );
    _introWidget->setPixmap( TQPixmap( locate("data","keduca/pics/keduca_init.png") ) );
    addWidget( _introWidget, 0 );

    // Info Widget
    _infoWidget = new TQVBox( this, "infoWidget" );
    _viewInfo = new TQTextEdit( _infoWidget );
    _viewInfo->setReadOnly( true );
    _buttonStartTest = new KPushButton( i18n( "&Start Test" ), _infoWidget );
    connect( _buttonStartTest, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) );
    addWidget( _infoWidget, 1 );

    // Question Widget
    _questionWidget = new TQVBox( this, "questionWidget" );
    _split  = new TQSplitter( Qt::Vertical, _questionWidget );
    _questionText = new KQuestion( _split, "kquestion" );
    _buttonGroup = new KGroupEduca( _split, "ButtonGroup" );
    _buttonGroup->setRadioButtonExclusive( true );
    _buttonNext = new KPushButton( i18n( "&Next >>" ), _questionWidget, "ButtonNext" );
    connect( _buttonNext, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) );
    addWidget( _questionWidget, 2 );

    // Results Widget
    _resultsWidget = new TQVBox( this, "resultsWidget" );
    _viewResults = new TQTextEdit( _resultsWidget );
    _viewResults->setReadOnly( true );
    _buttonSave = new KPushButton( i18n( "&Save Results..." ), _resultsWidget );
    connect( _buttonSave, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonSave() ) );
    /* FIXME: This is a hack
     * The results widget can be shown only in the end of the test (when you should be shown the
     * option to save the results) or at the middle of the test, after each question (when there should
     * be a "Next" button).
     */
    _buttonResultsNext = new KPushButton( i18n( "&Next >>" ), _resultsWidget );
    connect( _buttonResultsNext, TQT_SIGNAL( clicked() ), TQT_SLOT( slotButtonNext() ) );
    _buttonResultsNext->hide();
    addWidget( _resultsWidget, 3 );

    raiseWidget( _introWidget );

    // Restore splitter size
    _split->setSizes( Settings::splitter_size() );
}

void KEducaView::slotButtonStartTest()
{
    raiseWidget( _questionWidget );
    showRecord();
}

/** Button Next action */
void KEducaView::slotButtonNext()
{
    // stop the timer
    if (_timeoutTimer)
    {
      _currentTime += _questionText->getCurrentTime();
      _timeoutTimer->stop();
      _questionText->countdown(0);
    }

    if( ( visibleWidget() == _questionWidget ) && !_isInitStatus )
      setResults();

    _buttonGroup->clearAnswers();

    if( ( Settings::resultFinish()== Settings::EnumResultFinish::afterEachQuestion ) 
        && _questionText->isVisible() )
    {
        showResults( _currentResults + "<HR>" + currentStatusPoints() );
    }
    else
    {
        if( questionNext() )
          showRecord();
        else
          {
          configWrite();
          showResults( setFinalResult() + currentStatusPoints() + "<HR><P>" + _results + "</HTML>"
);
          }
    }
}

/** Button Save action */
void KEducaView::slotButtonSave()
{
    KFileDialog *dialog=new KFileDialog(TQString(), TQString(), this, "file dialog", true);
    dialog->setCaption( i18n("Save Results As") );
    dialog->setKeepLocation( true );
    dialog->setOperationMode( KFileDialog::Saving );
    TQStringList mimeFilter( "text/html");
    dialog->setMimeFilter( mimeFilter );
    KURL newURL;
    TQString outputFormat ("text/html");

    bool bOk;
    do {
        bOk=true;
        if(dialog->exec()==TQDialog::Accepted) {
            newURL=dialog->selectedURL();
            outputFormat=dialog->currentMimeFilter();
        }
        else
        {
            bOk = false;
            break;
        }
        kdDebug()<<"Requested saving to file "<<newURL.prettyURL() <<endl;

        if ( TQFileInfo( newURL.path() ).extension().isEmpty() ) {
            // No more extensions in filters. We need to get it from the mimetype.
            TQString extension = ".html";
            newURL.setPath( newURL.path() + extension );
        }

        if ( TDEIO::NetAccess::exists( newURL, false, this ) ) { // this file exists => ask for confirmation
            bOk = KMessageBox::warningContinueCancel( this,
                                              i18n("A document with this name already exists.\n"\
                                                   "Do you want to overwrite it?"),
                                              i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue;
        }
    } while ( !bOk );

    delete dialog;  
    if( bOk ) {
        if (!_keducaFile->saveResults( newURL, _viewResults->text() ))
          {
          kdDebug()<< "saving of file failed" <<endl;
          KMessageBox::sorry( this, i18n("Save failed.") ); 
          }
        }else {
        kdDebug()<< "KControlDoc: no valid filename selected" <<endl;
    }
}

/** Show record, returns false if there is no record to show. */
void KEducaView::showRecord()
{
    TQString questionTextTemp = "";
    
    raiseWidget( _questionWidget );
    
    _keducaFileIndex++;
    bool MultiAnswer = _keducaFile->isMultiAnswer();

    // SHOW QUESTION *******************************************************************
    _questionText->setPixmap( _keducaFile->getPicturePixmap() );
    questionTextTemp =  "<table width=100%><tr><td><b>"
                        + i18n("Question %1").arg(_keducaFileIndex) + "</b>";

    if( _keducaFile->getTotalPoints() > 0 )
      questionTextTemp  += "</td><td align=center bgColor=#336699><font color=#ffffff><b>"
                        + _keducaFile->getQuestion( FileRead::TQF_POINTS )
                        + " " + i18n("Points")
                        + "</b></font>";
                       
    questionTextTemp    += "</tr></td></table><hr/><table><tr><td>"
                        + _keducaFile->getQuestion( FileRead::TQF_TEXT )
                        + "</td></tr></table>";

    _questionText->setText( questionTextTemp );
                            
    // SHOW ANSWERS ********************************************************************
    if( MultiAnswer )
        _buttonGroup->setType( KGroupEduca::Check );
    else
        _buttonGroup->setType( KGroupEduca::Radio );


    if( Settings::randomAnswers() )
      {
      _randomAnswers.clear();
      TQValueList<unsigned int> tmpRandom;
      unsigned int index;
      for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ )
        { tmpRandom.append( index ); }
      for( index = 0 ; index < _keducaFile->recordAnswerCount() ; index ++ )
        {
        unsigned int random = rand() % tmpRandom.count();
        TQValueList<unsigned int>::iterator itTmpRandom = tmpRandom.begin();
        for( unsigned int i = 0; i < random; i++) { ++itTmpRandom; }
        _keducaFile->recordAnswerAt( (*itTmpRandom) );
        _randomAnswers.append( (*itTmpRandom) );
        _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) );
        tmpRandom.remove( itTmpRandom );
        }
      }
    else
      {
        _keducaFile->recordAnswerFirst();
        while( !_keducaFile->recordAnswerEOF() )
        {
            if( !_keducaFile->getAnswer(FileRead::AF_TEXT).isEmpty() )
                _buttonGroup->insertAnswer( _keducaFile->getAnswer(FileRead::AF_TEXT) );
            _keducaFile->recordAnswerNext();
        };
      }

    
    // START THE TIMER *****************************************************************
    if( _keducaFile->getQuestionInt(FileRead::TQF_TIME) > 0 )
    {
        KMessageBox::information( this,
                                  i18n( "You have %1 seconds to complete this question.\n\n"
                                        "Press OK when you are ready." )
                                  .arg( _keducaFile->getQuestion(FileRead::TQF_TIME) ) );
     }

    int timeout = _keducaFile->getQuestionInt(FileRead::TQF_TIME);
    if (timeout > 0)
    {
      if (!_timeoutTimer)
      {
        _timeoutTimer = new TQTimer(this);
        connect(_timeoutTimer, TQT_SIGNAL(timeout()),
                this, TQT_SLOT(questionTimedOut()));
      }
      _timeoutTimer->start(1000*timeout);
      _questionText->countdown(timeout);
      _questionText->countdownVisible(true);
    }
    else
    {
      _questionText->countdownVisible(false);
    }
}

void KEducaView::questionTimedOut()
{
  _currentTime += _keducaFile->getQuestionInt(FileRead::TQF_TIME);
  slotButtonNext();
}

/** Show results */
void KEducaView::showResults( const TQString &text )
{
    _viewResults->setText( text );
   
    if ( _keducaFile->recordEOF() )
    {
        _buttonSave->show();
	   _buttonResultsNext->hide();
    }
    else
    {
        _buttonSave->hide();
	   _buttonResultsNext->show();
    }
    
    raiseWidget( _resultsWidget );
}

/** Set results */
void KEducaView::setResults()
{
    bool isCorrect = true;
    TQString yourAnswer = "";
    TQString correctAnswer = "";
    TQValueList<uint>::iterator itRandom = _randomAnswers.begin();
    
    Settings::randomAnswers() ? _keducaFile->recordAnswerAt(*itRandom) : _keducaFile->recordAnswerFirst();

    for( unsigned index = 0 ; index < _keducaFile->recordAnswerCount() ; index++ )
    {
        TQString answertext = _keducaFile->getAnswer( FileRead::AF_TEXT );
        if( !answertext.isEmpty() )
        {
            if(_buttonGroup->isChecked(index) != _keducaFile->getAnswerValue())
            {
                isCorrect=false;
                if(_buttonGroup->isChecked(index)) yourAnswer += "<BR><FONT COLOR=#b84747><B>" + answertext + "</B></FONT>";
                if(_keducaFile->getAnswerValue()) correctAnswer += "<BR><FONT COLOR=#006b6b><B>" + answertext + "</B></FONT>";
            }
            else
            {
                if(_buttonGroup->isChecked(index)) yourAnswer += "<BR><B>" + answertext + "</B>";
                if(_keducaFile->getAnswerValue()) correctAnswer += "<BR><FONT COLOR=#006b6b><B>" + answertext + "</B></FONT>";
            }
        }
        if( Settings::randomAnswers() )
          {
          ++itRandom;
          _keducaFile->recordAnswerAt(*itRandom);
          }
        else
          _keducaFile->recordAnswerNext();
    }

    if( isCorrect)
      {
      _correctAnswer++;
      if( _keducaFile->getTotalPoints() > 0 )
        _correctPoints += _keducaFile->getQuestionInt(FileRead::TQF_POINTS);
      }
    else
      {
      _incorrectAnswer++;
      if( _keducaFile->getTotalPoints() > 0 )
        _incorrectPoints += _keducaFile->getQuestionInt(FileRead::TQF_POINTS);
      }
    
  _results += getTableQuestion( isCorrect, correctAnswer, yourAnswer );
}

/** Set results */
TQString KEducaView::setFinalResult()
{
  TQString finalResult = "";
  
  if( !_keducaFile->isResult() ) return "";

  finalResult = "<TABLE WIDTH=100% BORDER=0 BGCOLOR=#EEEEDD CELLSPACING=0><TR><TD BGCOLOR=#DDDDCC COLSPAN=2 ALIGN=CENTER><FONT COLOR=#222211><B>"
              + i18n("Result")
              + "</B></FONT></TD></TR>";
  
  _keducaFile->recordResultFirst();
  while( !_keducaFile->recordResultEOF() )
    {
        if( _correctPoints >= _keducaFile->getResultInt(FileRead::RS_MIN) &&
            _correctPoints <= _keducaFile->getResultInt(FileRead::RS_MAX) )
          {
             if( _keducaFile->getResult(FileRead::RS_PICTURE).isEmpty() )
               finalResult += "<TR><TD COLSPAN=2 ALIGN=CENTER>";
               else
               finalResult += "<TR><TD><IMG SRC=" + _keducaFile->getResult(FileRead::RS_PICTURE) + " : </TD><TD>";
               
             finalResult += _keducaFile->getResult(FileRead::RS_TEXT) + "</TD><TR>";
          }
        _keducaFile->recordResultNext();
    }

  finalResult += "</TABLE>";

  return finalResult;
}

/** Open url */
bool KEducaView::openURL( const KURL &url)
{
    _keducaFile = new FileRead();
    if ( !_keducaFile->openFile( url ) )
        return false;

    _isInitStatus = true;
    _results = "<HTML>";
    _correctAnswer = 0;
    _correctPoints = 0;
    _currentTime = 0;
    _incorrectAnswer = 0;
    _incorrectPoints = 0;
    _keducaFileIndex = 0;

    if( Settings::randomQuestions() )
      {
      unsigned int index;
      for( index = 0 ; index < _keducaFile->getTotalQuestions() ; index ++ )
            {   _randomQuestions.append( index ); }
      }

    _keducaFile->recordFirst();
    _keducaFile->recordAnswerFirst();
    
    _viewInfo->setText( getInformation() );
    raiseWidget( _infoWidget );
    
    return true;
}

/** Write settings */
void KEducaView::configWrite()
{
    Settings::setSplitter_size( _split->sizes() );
    Settings::writeConfig();
}

/** current Status Points */
TQString KEducaView::currentStatusPoints()
{
  TQString tempStatus;
 
  tempStatus = insertTable()
              + insertRow( i18n("Statistics"), true, 4)
              + insertRow( i18n("Correct questions"),
                           TQString().setNum( _correctAnswer ),
                           i18n("Incorrect questions"),
                           TQString().setNum( _incorrectAnswer ), true);

  if( _keducaFile->getTotalPoints() > 0 )
    tempStatus += insertRow( i18n("Total points"), true, 4 )
                + insertRow( i18n("Correct points"),
                             TQString().setNum( _correctPoints ),
                             i18n("Incorrect points"),
                             TQString().setNum( _incorrectPoints ), true );

  if( _keducaFile->getTotalTime() > 0 )
    tempStatus += insertRow( i18n("Time"), true, 4 )
                + insertRow( i18n("Total time"),
                             TQString().setNum( _keducaFile->getTotalTime() ),
                             i18n("Time in tests"),
                             TQString().setNum( _currentTime ), true );
  tempStatus += insertTableClose();
  return tempStatus;
}

/** Set HTML table view with correct and incorrect answers */
TQString KEducaView::getTableQuestion( bool isCorrect, const TQString &correct, const TQString &incorrect)
{
  _currentResults = "<TABLE WIDTH=100% BORDER=0><TR><TD VALIGN=TOP WIDTH=70><IMG WIDTH=64 HEIGHT=64 SRC=";                     
  if( isCorrect )
    _currentResults += locate("data","keduca/pics/keduca_correct_64.png");
    else
    _currentResults += locate("data","keduca/pics/keduca_incorrect_64.png");

  _currentResults += "></TD><TD VALIGN=TOP>";

  _currentResults += "<B><FONT COLOR=#336699>" + _keducaFile->getQuestion( FileRead::TQF_TEXT ) + "</FONT></B>";

  if( _keducaFile->getQuestionInt(FileRead::TQF_POINTS) > 0 )
    _currentResults += "<SMALL> ( " + _keducaFile->getQuestion(FileRead::TQF_POINTS) + " " + i18n("Points") + " )</SMALL>";
    
  _currentResults += "<HR><SMALL>";

  if( isCorrect )
    _currentResults += i18n( "The answer is: ");
    else
    _currentResults += i18n( "The correct answer is: ");

  _currentResults += correct + "<BR>";

  if( !isCorrect )
    {
        _currentResults += i18n( "Your answer was: ");
        _currentResults += incorrect;
    }
 
  _currentResults += "</SMALL></TD></TR></TABLE><P>";
  return _currentResults;
}

/** Define the next questions (random, secuencial) */
bool KEducaView::questionNext()
{
  if( !Settings::randomQuestions() && !_isInitStatus )
    {
    _keducaFile->recordNext();
    return _keducaFile->recordEOF() ? false : true;
    }

  if( _isInitStatus )
    {
    _isInitStatus = false;
    if( !Settings::randomQuestions() ) return true;
    }
 
  if( _randomQuestions.count() > 0 )
    { 
    unsigned int randomQuestion = rand() % _randomQuestions.count();
    TQValueList<uint>::iterator itRandom = _randomQuestions.begin();
    for( unsigned int i = 0; i < randomQuestion; ++i)
      { ++itRandom; }
    _keducaFile->recordAt( (*itRandom) );
    _randomQuestions.remove( itRandom );
    return true;
    }
    else
    return false;
}

/** Get document information */
TQString KEducaView::getInformation()
{

  TQString tmp = "";
  
  if ( _keducaFile )
  {
    if( !(_keducaFile->getHeader("startupinfo")).isEmpty() )
    {
      tmp += insertTable( "<img src=" + locate("data","keduca/pics/alert.png") + ">", 2 )
//          + insertRow( i18n("Additional Information")+"<br>", true, 2 )
          + insertRow( _keducaFile->getHeader("startupinfo") + "<br>", false )
          + insertTableClose();
    }

    tmp += insertTable( "<img src=" + locate("data","keduca/pics/info.png") + ">", 2 );
    tmp += insertRow( i18n("Information")+"<br>", true, 2);
    tmp += insertRow( i18n("Title"), _keducaFile->getHeader("title"), true );
    tmp += insertRow( i18n("Category"), _keducaFile->getHeader("category"), true );
    tmp += insertRow( i18n("Type"), _keducaFile->getHeader("type"), true );
    tmp += insertRow( i18n("Language"), _keducaFile->getHeader("language"), true );
    tmp += insertTableClose();
  }
  else
  {
    tmp += "<html><body>";
    tmp += "<img src=" + locate("data","keduca/pics/keduca_init.png") + "/>";
    tmp += "</body></html>";
  }

  return tmp;
}

/** Init table with title and colspan */
TQString KEducaView::insertTable( const TQString &title, unsigned int col){
  TQString tmp;

  tmp = "<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 BGCOLOR=#EEEEDD>";

  if( !title.isEmpty() ) {
    tmp += "<TR><TD ";

    if( col > 0 ) tmp += "COLSPAN=" + TQString().setNum( col ) + " ";

    tmp += "ALIGN=CENTER><FONT COLOR=#222211><B>"
        + title
        + "</B></FONT></TD></TR>";
    }
  return tmp;
}

/** Insert row */
TQString KEducaView::insertRow( const TQString &text, bool title, unsigned colSpan ){
  TQString tmp;
  tmp = "<TR><TD";
  if( colSpan>0 ) tmp+= " COLSPAN=" + TQString().setNum(colSpan);
  if( title ) tmp += " ALIGN=CENTER";
  tmp += ">";
  if( title ) tmp += "<B>";
  tmp += text;
  if( title ) tmp += "</B>";
  tmp += "</TD></TR>";
  return tmp;
}

/** Insert row */
TQString KEducaView::insertRow( const TQString &label, const TQString &field, bool formBased ){
  TQString tmp;
  tmp = "<TR><TD";
  if( formBased ) tmp += " ALIGN=RIGHT";
  tmp += ">" + label;
  if( formBased ) tmp += ": ";
  tmp += "</TD><TD>" + field + "</TD></TR>";
  return tmp;
}

TQString KEducaView::insertRow( const TQString &label1, const TQString &field1, const TQString &label2, const TQString &field2, bool formBased ){
  TQString tmp;
  tmp = "<TR><TD";
  if( formBased ) tmp += " ALIGN=RIGHT";
  tmp += ">" + label1;
  if( formBased ) tmp += ": ";
  tmp += "</TD><TD>" + field1 + "</TD>";
  tmp += "<TD";
  if( formBased ) tmp += " ALIGN=RIGHT";
  tmp += ">" + label2;
  if( formBased ) tmp += ": ";
  tmp += "</TD><TD>" + field2 + "</TD></TR>";
  return tmp;
}


/** Close current table */
TQString KEducaView::insertTableClose(){
  return "</TABLE>";
}

