/***************************************************************************
 *   Copyright (C) 2005 by Tavarez Arnaud Bakoula                          *
 *   tbakoula@yahoo.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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "kmastermind.h"

#include "combinaison.h"
#include "notification.h"
// dialogs
#include "datadlg.h"
#include "modedlg.h"
#include "leveldlg.h"
#include "appearancedlg.h"
// sites and ticks
#include "siterow.h"
#include "tickrow.h"

#include "cell.h"
// board
#include "boardwidget.h"
#include "sitemanager.h"
#include "tickmanager.h"

#include "conversion.h"

#include <qlabel.h>
#include <qpushbutton.h>
#include <qinputdialog.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qbuttongroup.h>

#include <kmainwindow.h>
#include <klocale.h>
#include <kapp.h>
#include <kconfig.h>
#include <kdialog.h>
#include <kstatusbar.h>

#include <kstdaccel.h>
#include <kaction.h>
#include <kstdaction.h>
#include <kstandarddirs.h>

#include <qlayout.h>

#include <cstdlib>
#include <ctime>

#include <iostream>

uint icon_res = 32;

KMasterMind::KMasterMind()
    : KMainWindow( 0, "KMasterMind" )
{
    // set the shell's ui resource file
    setXMLFile("kmastermindui.rc");

    setCaption("KMasterMind");

    appKey = "kmastermind";

    initialize();

    setupActions();
    setupMenuBar();
    setupStatusBar();
    setupDialogs();
    setupDefaults();

    createGUI("kmastermindui.rc");
    loadSettings();
    setupBoard();
    setupDatas();

    toolBar()->show();
    statusBar()->show();
    setAutoSaveSettings();

    loadGame();
}

KMasterMind::~KMasterMind()
{
    delete hidden_cmb; hidden_cmb = 0;
    delete propos_cmb; propos_cmb = 0;
    delete notify_ntf; notify_ntf = 0;

    delete dataDlg;       dataDlg  = 0;
    delete modeDlg;       modeDlg  = 0;
    delete levelDlg;      levelDlg = 0;
    delete appearanceDlg; appearanceDlg = 0;
    delete theBoard;      theBoard = 0;

    delete theIconLoader; theIconLoader = 0;
}

void
KMasterMind::saveProperties( KConfig* )
{
}

void
KMasterMind::readProperties( KConfig* )
{
}

void
KMasterMind::initialize()
{
    hidden_cmb  = 0;
    propos_cmb  = 0;
    notify_ntf  = 0;
    absent_ctr    = tries_ctr  = 0;
    misplaced_ctr = placed_ctr = 0;
    suggestion = 0;
    theBoard = 0;
    modeDlg  = 0;
    dataDlg  = 0;
    levelDlg = 0;
    appearanceDlg = 0;
}


/*!
    \fn KMasterMind::loadSettings()
 */
void
KMasterMind::loadSettings()
{
    KConfig* cfg = kapp->config();

    cfg->setGroup( "Game Config" );
      level = (Level) cfg->readNumEntry( "level", (int)NOVICE );
      mode  = (Mode)  cfg->readNumEntry( "mode", (int)Standard );
      nb_pions  = cfg->readNumEntry( "pions", 5 );
      nb_tries  = cfg->readNumEntry( "tries", 10 );
      nb_colors = cfg->readNumEntry( "colors", 6 );

      modeDlg->modeGroup->setButton( (int)mode );
    cfg->setGroup( QString::null );

    cfg->setGroup( "Geometry" );
      int _x = cfg->readNumEntry( "x", 0 );
      int _y = cfg->readNumEntry( "y", 0 );
      cfg->readNumEntry( "width" , 0 );
      cfg->readNumEntry( "height", 0 );

      move(_x, _y);
    cfg->setGroup( QString::null );

    dataDlg->spinTries->setValue( nb_tries );
    dataDlg->spinPions->setValue( nb_pions );
    dataDlg->spinColors->setValue( nb_colors );
    levelDlg->levelGroup->setButton( (int)level );

    cfg->setGroup( "Appearance" );
      site_bg = cfg->readEntry( "sites", "flower" );
      tick_bg = cfg->readEntry( "ticks", "leaf" );
      icon_res = cfg->readNumEntry( "resolution", 32 );
      Cell::setSize( icon_res );

      appearanceDlg->comboSites->setCurrentText( site_bg );
      appearanceDlg->comboTicks->setCurrentText( tick_bg );

      appearanceDlg->comboSize->setCurrentText(
                    QString::number( icon_res )
                    + "x" +
                    QString::number( icon_res ) );
    cfg->setGroup( QString::null );

    for ( int k=0; k<3; k++ )
    {
      cfg->setGroup( "Scores " + levelToString( (Level) k ) );
      for ( int i=0; i<=9; i++ )
      {
        QString scores = cfg->readEntry( "player" + QString::number( i ),"-,-,-,-" );
        QStringList scores_list = QStringList::split( ",", scores, TRUE );
        theScores[ k ][i].name  = scores_list[0];
        theScores[ k ][i].lvl   = scores_list[1];
        theScores[ k ][i].value = scores_list[2];
        theScores[ k ][i].tries = scores_list[3];
      }
      cfg->setGroup( QString::null );
    }

    lblLevel->setText( i18n(" Level : ") + levelToString( level ) + " " );
    lblTries->setText( i18n(" Try : ") + "0/" + QString::number( nb_tries ) + " " );
    lblPions->setText( " " + QString::number( nb_pions ) + i18n(" among ")
                             + QString::number( nb_colors ) + " " );
}

/*!
    \fn KMasterMind::saveSettings()
 */
void KMasterMind::saveSettings()
{
    KConfig* cfg = kapp->config();

    cfg->setGroup( "Game Config" );
      cfg->writeEntry( "level" , (int) level );
      cfg->writeEntry( "mode"  , (int) mode );
      cfg->writeEntry( "pions" , nb_pions );
      cfg->writeEntry( "tries" , nb_tries );
      cfg->writeEntry( "colors", nb_colors );
    cfg->setGroup( QString::null );

    cfg->setGroup( "Geometry" );
      cfg->writeEntry( "x", x() );
      cfg->writeEntry( "y", y() );
      cfg->writeEntry( "width", width() );
      cfg->writeEntry( "height", height() );
    cfg->setGroup( QString::null );

    cfg->setGroup( "Appearance" );
      cfg->writeEntry( "sites", site_bg );
      cfg->writeEntry( "ticks", tick_bg );
      cfg->writeEntry( "resolution", (int)icon_res );
    cfg->setGroup( QString::null );

    for ( int k=0; k<3; k++ )
    {
      cfg->setGroup( "Scores " + levelToString( (Level) k ) );
        for ( int i=0; i<=9; i++ )
        {
          QString scores;
          scores += theScores[ k ][i].name;  scores += ",";
          scores += theScores[ k ][i].lvl;   scores += ",";
          scores += theScores[ k ][i].value; scores += ",";
          scores += theScores[ k ][i].tries;

          cfg->writeEntry( "player" + QString::number( i ), scores );
        }
      cfg->setGroup( QString::null );
    }

}

void
KMasterMind::setupDefaults()
{
    absent_ctr = tries_ctr = misplaced_ctr = placed_ctr = 0;
    hidden_cmb  = 0;
    propos_cmb  = 0;
    notify_ntf  = 0;
    suggestion  = 0;
}

void
KMasterMind::setupActions()
{
    m_actions = actionCollection();

    fileNew = new KAction( i18n("&New"), "filenew", i18n("Ctrl+N"), this,
                           SLOT( slotFileNew() ), m_actions, "new" );
    fileNew->setToolTip( "<b>New</b><br>Start a new game.<br><b>Ctrl+N</b>" );

    fileScore = new KAction( i18n("&Scores..."), i18n("Ctrl+H"), this,
                             SLOT( slotFileScore() ), m_actions, "score" );
    KStdAction::quit( this, SLOT( slotFileQuit() ), m_actions, "exit" );

    m_toolbarAction
        = KStdAction::showToolbar( this, SLOT( slotOptionsShowToolbar() ), m_actions );
    m_statusbarAction
        = KStdAction::showStatusbar( this, SLOT( slotOptionsShowStatusbar() ), m_actions );

    /* options entries */
    optionsData = new KAction( i18n("Configure &datas..."), 0, i18n("Ctrl+D"), this,
                                     SLOT( slotOptionsData() ), m_actions, "datacfg" );
    optionsMode = new KAction( i18n("Define &mode..."), 0, i18n("Ctrl+M"), this,
                                     SLOT( slotOptionsMode() ), m_actions, "modecfg" );
    optionsLevel = new KAction( i18n("Choose &level..."), 0, i18n("Ctrl+L"), this,
                                     SLOT( slotOptionsLevel() ), m_actions, "levelcfg" );
    optionsAppearance = new KAction( i18n("Configure &appearance..."), 0, i18n("Ctrl+A"), this,
                                     SLOT( slotOptionsAppearance() ), m_actions, "appearancecfg" );

    submitAction = new KAction( i18n("&Submit"), "exec", i18n("Ctrl+S"), this,
                                SLOT( submitCombinaison() ), m_actions, "submit" );
    submitAction->setEnabled( FALSE );
    submitAction->setToolTip( "<b>Submit</b><br>Submit the"
                              "current\ncombination.<br><b>Ctrl+S</b>" );

    recordAction =  new KAction( i18n("&Record"), "ok", i18n("Ctrl+R"), this,
                                SLOT( recordNotification() ), m_actions, "record" );
    recordAction->setEnabled( FALSE );
    recordAction->setToolTip( "<b>Record</b><br>Record the"
                              "tickmarks\nstatement.<br><b>Ctrl+R</b>" );

    suggestAction =  new KAction( i18n("Su&ggest"), "help", i18n("Ctrl+G"), this,
                                SLOT(slotSuggest() ), m_actions, "suggest" );
    suggestAction->setEnabled( FALSE );
    suggestAction->setToolTip( "<b>Suggest</b><br>Make a suggestion\n"
                               "about the place of a piece.<br><b>Ctrl+G</b>" );
}


void
KMasterMind::setupMenuBar()
{
//     MenuBar = new KMenuBar( this, "Master menubar" );
}

void
KMasterMind::setupStatusBar()
{
    lblLevel   = new KStatusBarLabel( " Level :     ", 1, statusBar() );
    lblPions   = new KStatusBarLabel( "             ", 2, statusBar() );
    lblTries   = new KStatusBarLabel( " Try :       ", 3, statusBar() );
    lblSuggest = new KStatusBarLabel( " Suggestions : ", 4, statusBar() );
    statusBar()->addWidget( lblLevel, 0, TRUE );
    statusBar()->addWidget( lblPions, 0, TRUE );
    statusBar()->addWidget( lblTries, 0, TRUE );
    statusBar()->addWidget( lblSuggest, 0, TRUE );
}

void
KMasterMind::setupDialogs()
{
    appearanceDlg = new AppearanceDlg( this, "Master Appearance" );
    levelDlg = new LevelDlg( this, "Master Level" );
    modeDlg  = new ModeDlg( this, "Master Mode" );
    dataDlg  = new DataDlg( this, "Master Data" );

    appearanceDlg->comboTheme->setEnabled( FALSE );
}

void KMasterMind::setupBoard()
{
    theBoard = new BoardWidget( nb_tries, nb_pions, nb_colors, this );
    theBoard->theSites->setPaletteBackgroundPixmap( QPixmap( locate("appdata", "pics/" + site_bg + ".png" ) ) );
    theBoard->theTicks->setPaletteBackgroundPixmap( QPixmap( locate("appdata", "pics/" + tick_bg + ".png" ) ) );
    setCentralWidget( theBoard );
}

/*!
 *  This function creates the internal combinations and the notif
 */
void KMasterMind::setupDatas()
{
    hidden_cmb = new Combinaison( nb_pions );
    propos_cmb = new Combinaison( nb_pions );
    notify_ntf = new Notification( nb_pions );
}

/* private slots */
void
KMasterMind::slotFileNew()
{
    if ( !playing )
    {
      loadGame();
      return;
    }

    switch ( QMessageBox::information( this, "Game info",
            i18n("A game is running. Would you really want to give it up ?"),
            QMessageBox::Ok, QMessageBox::Cancel ) )
    {
      case QMessageBox::Ok:
        loadGame();
        return;
      case QMessageBox::Cancel:
        return;
    }
}

void
KMasterMind::slotFileScore()
{
    int j=0;
    QDialog* scr = new QDialog( this, "score widget", TRUE, WType_Dialog | WShowModal );
    scr->setCaption( "Scores" );

    QGridLayout* grid = new QGridLayout( scr, 1, 1, 14, 3 );

    QLabel* bestLabel
      = new QLabel( i18n("<u><b>The best Scores and Scorers</b></u>"), scr );
    bestLabel->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType) 5, (QSizePolicy::SizeType) 5,
                                           0, 0, bestLabel->sizePolicy().hasHeightForWidth() ) );
    bestLabel->setAlignment( int(QLabel::AlignCenter) );

    grid->addMultiCellWidget( bestLabel, 0, 0, 0, 4 );
    j++;

    QLabel* lblRank  = new QLabel( i18n("<b>Rank</b>"), scr, "rank" );
    QLabel* lblName  = new QLabel( i18n("<b>Name</b>"), scr, "name" );
    QLabel* lblScore = new QLabel( i18n("<b>Score</b>"), scr, "score" );
    QLabel* lblLevel = new QLabel( i18n("<b>Level</b>"), scr, "level" );
    QLabel* lblTries = new QLabel( i18n("<b>Tries</b>"), scr, "tries" );
    lblScore->setAlignment( (int) QLabel::AlignRight );
    lblTries->setAlignment( (int) QLabel::AlignRight );

    grid->addWidget( lblRank, j, 0 );
    grid->addWidget( lblName, j, 1 );
    grid->addWidget( lblScore, j, 3 );
    grid->addWidget( lblLevel, j, 2 );
    grid->addWidget( lblTries, j, 4 );
    j++;

    QFrame* line1 = new QFrame( scr, "line1" );
    line1->setFrameShape( QFrame::HLine );
    line1->setFrameShadow( QFrame::Sunken );
    line1->setFrameShape( QFrame::HLine );

    grid->addMultiCellWidget( line1, j, j, 0, 4 );
    j++;

    for ( int i=0; i<=9; i++, j+=i )
    {
      lblRank = new QLabel( scr );
      lblRank->setText( QString::number(i+1) );

      lblName = new QLabel( scr );
      lblName->setText( theScores[ level ][i].name );

      lblScore = new QLabel( scr );
      lblScore->setText( theScores[ level ][i].value );
      lblScore->setAlignment( (int) QLabel::AlignRight );

      lblLevel = new QLabel( scr );
      lblLevel->setText( theScores[ level ][i].lvl );

      lblTries = new QLabel( scr );
      lblTries->setText( theScores[ level ][i].tries );
      lblTries->setAlignment( (int) QLabel::AlignRight );

      grid->addWidget( lblRank, j, 0 );
      grid->addWidget( lblName, j, 1 );
      grid->addWidget( lblScore, j, 3 );
      grid->addWidget( lblLevel, j, 2 );
      grid->addWidget( lblTries, j, 4 );
    }

    QFrame* line2 = new QFrame( scr, "line2" );
    line2->setFrameShape( QFrame::HLine );
    line2->setFrameShadow( QFrame::Sunken );
    line2->setFrameShape( QFrame::HLine );

    grid->addMultiCellWidget( line2, j, j, 0, 4 );
    j++;

    QPushButton* okButton = new QPushButton( i18n("&Close"), scr );
    grid->addWidget( okButton, j, 4 );

    connect( okButton, SIGNAL(clicked()), scr, SLOT(accept()) );
    scr->setFixedSize(scr->minimumSize());
    scr->exec();
    delete scr;
}

void
KMasterMind::slotFileQuit()
{
    saveSettings();
    kapp->quit();
}

void
KMasterMind::slotOptionsData()
{
    dataDlg->spinTries->setValue( nb_tries );
    dataDlg->spinPions->setValue( nb_pions );
    dataDlg->spinColors->setValue( nb_colors );

    if ( dataDlg->exec() )
    {
      int newTries  = dataDlg->spinTries->value();
      int newPions  = dataDlg->spinPions->value();
      int newColors = dataDlg->spinColors->value();

      theBoard->changeCellsBy( newPions - nb_pions );
      changeDataSize( newPions - nb_pions );
      setNbPions( newPions );

      theBoard->changeRowsBy(  newTries - nb_tries );
      setNbTries( newTries );

      lblTries->setText( i18n(" Try : ") + "0/" + QString::number( nb_tries ) + " " );

      theBoard->changeChoicesBy( newColors - nb_colors );
      nb_colors = newColors;


      lblPions->setText( " " + QString::number( nb_pions ) + i18n(" for ")
                             + QString::number( nb_colors ) + " " );
      playing = FALSE;

      // Reset All game's datas
      // Remise à zéro incomplète pour l'instant
      // Doit remettre à zéro la combinaison cachée, la proposée et les status
      // Doit également replacer les élément en mode lecture seule et déconnecter
      // les boutons de tous les signaux.
      theBoard->reset();
    }
}

void
KMasterMind::slotOptionsMode()
{
    modeDlg->modeGroup->setButton( (int) mode );
    if ( modeDlg->exec() )
    {
      int new_mode = modeDlg->modeGroup->selectedId();
      if ( new_mode != mode )
      {
        // configure all the widget in the way corresponding
        // to the mode
        mode = (Mode) new_mode;
        playing = FALSE;
        resetAll();
        theBoard->reset();
      }
    }
}

void
KMasterMind::slotOptionsLevel()
{
    levelDlg->levelGroup->setButton( (int) level );
    if ( levelDlg->exec() )
    {
      int new_level = levelDlg->levelGroup->selectedId();
      if ( new_level != level )
      {
        level = (Level) new_level;
        lblLevel->setText( " Level : " + levelToString(level) + " " );
        playing = FALSE;
        resetAll();
        theBoard->reset();
      }
    }
}

void
KMasterMind::slotOptionsAppearance()
{
    appearanceDlg->comboSites->setCurrentText( site_bg );
    appearanceDlg->comboTicks->setCurrentText( tick_bg );

    appearanceDlg->comboSize->setCurrentText(
                    QString::number( icon_res )
                    + "x" +
                    QString::number( icon_res ) );

    if ( appearanceDlg->exec() )
    {
      site_bg = appearanceDlg->comboSites->currentText();
      theBoard->theSites->setPaletteBackgroundPixmap( QPixmap( locate("appdata", "pics/" + site_bg + ".png" ) ) );

      tick_bg = appearanceDlg->comboTicks->currentText();
      theBoard->theTicks->setPaletteBackgroundPixmap( QPixmap( locate("appdata", "pics/" + tick_bg + ".png" ) ) );

      QString res = appearanceDlg->comboSize->currentText();
      icon_res = res.section( 'x', 0, 0 ).toUInt() ;
      Cell::setSize( icon_res );

      theBoard->updateMe();
    }
}

void
KMasterMind::slotOptionsShowToolbar()
{
    // this is all very cut and paste code for showing/hiding the
    // toolbar
    if (m_toolbarAction->isChecked())
        toolBar()->show();
    else
        toolBar()->hide();

}

void
KMasterMind::slotOptionsShowStatusbar()
{
    // this is all very cut and paste code for showing/hiding the
    // statusbar
    if (m_statusbarAction->isChecked())
        statusBar()->show();
    else
        statusBar()->hide();
}

void
KMasterMind::slotHelpPlay()
{

}

void
KMasterMind::slotSuggest()
{
    if ( !playing )
      return;

    if ( level == NOVICE || !playing )
      return;
    if ( mode != Standard )
      return;

    Color c;
    int p;
    Pion pion = (*hidden_cmb)[std::rand() % nb_pions];
    c = pion.getColor();
    p = pion.getPos();
    QString str = i18n("There's a piece of color ");
    str += colorToString( c );
    str += i18n(" at position ");
    str += QString::number(p+1);

    QMessageBox::information( this, i18n("Suggestion"), str, QMessageBox::Ok );

    suggestion++;
    lblSuggest->setText( i18n(" Suggestions : ")
                         + QString::number( max_suggestion - suggestion) + "/"
                         + QString::number( max_suggestion) + " " );

    if ( suggestion >= max_suggestion )
      suggestAction->setEnabled( FALSE );
}


void
KMasterMind::closeEvent( QCloseEvent* e )
{
    saveSettings();
    e->accept();
}

void
KMasterMind::initParams()
{
    tries_ctr = 0;
    placed_ctr = misplaced_ctr = absent_ctr = 0;
    playing = TRUE;
    suggestion = 0;

    if ( nb_pions == 4 )
      max_suggestion = 2;
    else
      max_suggestion = 4;

    lblTries->setText( tr(" Try : ") + QString::number( tries_ctr )
                               + "/" + QString::number( nb_tries ) + " " );
    lblSuggest->setText( i18n(" Suggestions : ")
                         + QString::number( max_suggestion) + "/"
                         + QString::number( max_suggestion) + " " );

    resetAll();
}

void
KMasterMind::generateHidden()
{
    std::srand( time( 0 ) );

    for ( int i=0; i < nb_pions; i++ )
    {
      (*hidden_cmb)[i].setColor( static_cast<Color>( std::rand() % nb_colors ) );
      (*hidden_cmb)[i].setPos( i );
    }
    hidden_cmb->doCount();
}

void
KMasterMind::changeDataSize( int sz )
{
    if ( sz > 0 )
    {
      hidden_cmb->addPions( sz );
      propos_cmb->addPions( sz );
      notify_ntf->addMarks( sz );
      resetAll();
    }
    else if ( sz < 0 )
    {
      hidden_cmb->removePions( -sz );
      propos_cmb->removePions( -sz );
      notify_ntf->removeMarks( -sz );
      resetAll();
    }
}

bool
KMasterMind::checkComb()
{
    int i;
    int size = hidden_cmb->getDim();

    /* Résolution des états des pions de la combinaison pour
       les absents et les bien placés */
    for ( i=0; i < size; i++ )   // for 1
    {
      int color = static_cast<int>( (*propos_cmb)[i].getColor() );
      if ( hidden_cmb->count[ color ] == 0 )
      {
        (*notify_ntf)[i].setState( ABSENT ); ++absent_ctr;
      }
      else if ( (*propos_cmb)[i] == (*hidden_cmb)[i] )
      {
        (*notify_ntf)[i].setState( PLACED ); ++placed_ctr;
        propos_cmb->count[ color ]++;
      }
    } // end for 1

    /* Résolution des états des pions de la combinaison pour
      les mal placés */
    for ( i=0; i < size; i++ )
    {
      int color = static_cast<int>( (*propos_cmb)[i].getColor() );
      int& a = propos_cmb->count[ color ];
      int  b = hidden_cmb->count[ color ];
      State state = (*notify_ntf)[i].getState();
      if ( state == ABSENT || state == PLACED )
        continue;
      else
      {
        if ( a == b )
        {
          (*notify_ntf)[i].setState( ABSENT ); ++absent_ctr;
        }
        else
        {
          (*notify_ntf)[i].setState( MISPLACED );
          ++a; ++misplaced_ctr;
        }
      }
    }
    if ( *propos_cmb == *hidden_cmb )
      return true;
  return false;
}

void
KMasterMind::computeScore()
{
    double score=0.;
    score += 200. / nb_tries;
    score += 500. / tries_ctr;
    score += (level+1) * nb_pions * 500.;
    score += nb_colors / MAXCOLORS * 1000.;

    if ( int(score) > theScores[ level ][9].value.toInt() )
    {
      int i = 9;
      theScores[ level ][i].value = QString::number( int(score) );
      do {
        if ( theScores[ level ][i].value.toInt() >= theScores[ level ][i-1].value.toInt() )
        {
          theScores[ level ][i].value = theScores[ level ][i-1].value;
          theScores[ level ][i].name  = theScores[ level ][i-1].name;
          theScores[ level ][i].lvl = theScores[ level ][i-1].lvl;
          theScores[ level ][i].tries = theScores[ level ][i-1].tries;
          theScores[ level ][i-1].value = QString::number( int(score) );
          i--;
        }
        else break;
      } while ( i );
      bool ok;
      theScores[ level ][i].tries = QString::number( tries_ctr );
      theScores[ level ][i].lvl = levelToString( level );
      theScores[ level ][i].name = QInputDialog::getText( i18n("Scorer name"),
                        i18n("You've reached a high score, enter your name"),
                        QLineEdit::Normal, QString::null, &ok, this );
      slotFileScore();
    }
}

void
KMasterMind::revealHidden()
{
    combinaisonToSiterow( hidden_cmb, theBoard->answer_row );
    theBoard->theAnswer->hideMe( FALSE );
    theBoard->theAnswer->installActiveRow( theBoard->answer_row );
}

void
KMasterMind::showVictory()
{
    QMessageBox::information( this, "Victory"," You Win :) !!!", QMessageBox::Ok );
}

void
KMasterMind::showDefeat()
{
    QMessageBox::information( this, "Defeat"," You Lose :( !!!", QMessageBox::Ok );
}

void
KMasterMind::loadGame()
{
    initParams();
    theBoard->reset();
    disconnect( submitAction, SIGNAL( activated() ), this, SLOT( submitCombinaison() ) );
    disconnect( submitAction, SIGNAL( activated() ), this, SLOT( recordSolution() ) );

    switch( mode )
    {
       case Standard:
           prepareStandardMode();
         break;
       case Human:
           prepareHumanMode();
         break;
       case Cpu:
           prepareCpuMode();
         break;
    }
}

void
KMasterMind::prepareStandardMode()
{
    generateHidden();
    prepareFirstTry();
}

void
KMasterMind::prepareHumanMode()
{
    // préparation de la solution
    theBoard->theAnswer->setReadMode( FALSE );
    theBoard->theAnswer->hideMe( FALSE );
    theBoard->theAnswer->showReady();
    connect( theBoard->theAnswer, SIGNAL( ready(bool) ), submitAction, SLOT( setEnabled(bool) ) );
    connect( submitAction, SIGNAL( activated() ), this, SLOT( recordSolution() ) );
}

void
KMasterMind::prepareCpuMode()
{
    // Do nothing for the moment
}

void
KMasterMind::recordSolution()
{
    siterowToCombinaison( (SiteRow*)theBoard->theAnswer->getActiveRow(), hidden_cmb );
    theBoard->theAnswer->setReadMode( TRUE );
    hidden_cmb->doCount();
    disconnect( theBoard->theAnswer, SIGNAL( ready(bool) ), submitAction, SLOT( setEnabled(bool) ) );
    disconnect( submitAction, SIGNAL( activated() ), this, SLOT( recordSolution() ) );
    submitAction->setEnabled( FALSE );
    // préparation de la première soumission
    // reconnection des signaux et slots etc.
    prepareFirstTry();
}

/***************************************************************************
 *  This function is in charged of doing the submission of a combination.
 *  For that, it retrieves the active row of the sitemanager and converts
 *  it in a Combination so the comparison will be correctly done in the
 *  checkComb() method.
 *  It also calls updateNotification to give feedback to the player 1.
 */
void
KMasterMind::submitCombinaison()
{
    submitAction->setEnabled( FALSE );
    theBoard->theSites->setReadMode( TRUE );
    siterowToCombinaison( (SiteRow*)theBoard->theSites->getActiveRow(), propos_cmb );
    tries_ctr++;

    lblTries->setText( i18n(" Try : ") + QString::number( tries_ctr )
                               + "/" + QString::number( nb_tries ) + " " );
    updateNotification();
}

/*********************************************************************
 *  This function records the current notification. It must be called
 *  when the player 2 has decided that he has finished to give the
 *  necessary information for the player 1 be able to find the hidden
 *  combination.
 */
void
KMasterMind::recordNotification()
{
    recordAction->setEnabled( FALSE );        // disables the button
    theBoard->theTicks->setReadMode( TRUE );  // no more dnd events for the moment
    isItFinished();                           // sets the playing boolean in the
                                              // appropriate state
    if ( playing )
      prepareNextTry();
}

void
KMasterMind::prepareFirstTry()
{
    theBoard->theAnswer->hideMe( TRUE );
    theBoard->theSites->showReady();
    theBoard->theSites->setReadMode( FALSE );
    connect( theBoard->theSites, SIGNAL( ready(bool) ), submitAction, SLOT( setEnabled(bool) ) );
    connect( submitAction, SIGNAL( activated() ), this, SLOT( submitCombinaison() ) );
    suggestAction->setEnabled( TRUE );
}

void
KMasterMind::prepareNextTry()
{
    theBoard->theSites->nextRow();
    theBoard->theSites->showReady();
    theBoard->theSites->setReadMode( FALSE );
    theBoard->theTicks->nextRow();
    placed_ctr = misplaced_ctr = absent_ctr = 0;
}

/***************************************************************
 *  Updates the notification area depending on the current mode
 *  1 - Standard mode
 *  We must firstly know if the game is finished or not. if it
 *  is the case we reset the notification table and the color
 *  occurences in the submited combination. Then we prepare the
 *  next try.
 *  2 - Human mode
 *  We prepare the notification area to receive the dnd event
 *  from player 2.
 */
void
KMasterMind::updateNotification()
{
    if ( mode == Standard )
    {
      bool res = isItFinished();
      if ( !res )
      {
        notify_ntf->reset();
        propos_cmb->resetCount();
        prepareNextTry();
      }
    }
    else if ( mode == Human )
    {
      prepareNotification();
    }
}

void
KMasterMind::prepareNotification()
{
    recordAction->setEnabled( TRUE );
    theBoard->theTicks->setReadMode( FALSE );
}

/*****************************************************************
 *  This function returns the state of the current party.
 *  Firstly it calls the checkComb() method, secondly it converts
 *  determined notification (in checkComb) in a TickRow that will
 *  be installed in mode Standard to help player 1 to find the
 *  hidden combination. To finish, it determines if the party is
 *  lost or won and disconnect the appropriate signal and slot.
 */
bool
KMasterMind::isItFinished()
{
    bool res = checkComb();
    notificationToTickrow( notify_ntf, theBoard->mark_row );

    if ( mode == Standard )
    {
      switch( level )
      {
        case NOVICE:
          theBoard->theTicks->installActiveRow( theBoard->mark_row );
          break;
        case MEDIUM:
          theBoard->theTicks->installActiveRow( placed_ctr, misplaced_ctr );
          break;
        case EXPERT:
          theBoard->theTicks->installActiveRow( placed_ctr, misplaced_ctr, TRUE );
          break;
      }
    }

    if ( res )                            // we guessed the right
    {
      playing = FALSE;                    // end of the game
      showVictory();
      suggestAction->setEnabled( FALSE );
      if ( mode == Standard )
        computeScore();
      revealHidden();
      disconnect( submitAction, SIGNAL( activated() ), this, SLOT( submitCombinaison() ) );
      return TRUE;
    }
    else if ( (int)tries_ctr == nb_tries )
    {
      playing = FALSE;                  // end of the game
      showDefeat();
      revealHidden();
      suggestAction->setEnabled( FALSE );
      disconnect( submitAction, SIGNAL( activated() ), this, SLOT( submitCombinaison() ) );
      return TRUE;
    }
    return FALSE;
}

void
KMasterMind::resetAll()
{
    hidden_cmb->reset();
    propos_cmb->reset();
    notify_ntf->reset();

    suggestAction->setEnabled( FALSE );
    submitAction->setEnabled( FALSE );
    recordAction->setEnabled( FALSE );
}

#include "kmastermind.moc"
