
/*
  note: the code to lookup and insert the pixmaps
  into the Options menu was copied and adapted
  from KReversi.
  thanks.
  */
#include <qdir.h>
#include <qregexp.h>

#include <qlcdnumber.h>
#include <qkeycode.h>
#include <qcolor.h>
#include <qpopupmenu.h>

#include <kapp.h>
#include <kglobal.h>
#include <kstddirs.h>
#include <kmenubar.h>
#include <klocale.h>
#include <kconfig.h>
#include <kcolordlg.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>

#include "rattler.h"
#include "score.h"
#include "game.h"
#include "startroom.h"
#include "levels.h"

#include "trys.h"
#include "lcdrange.h"
#include "progress.h"

#include "view.h"
#include "keys.h"

#include "version.h"


static const char *description = I18N_NOOP("KDE Game");

Game::Game() :  KTMainWindow()
{
    setCaption( kapp->caption() );

    setIcon(i18n("Snake Race"));

    conf = kapp->config();
    if(conf == NULL) {
	printf("KConfig error?\n");
	kapp->quit();
    }

    levels = new Levels();
    score  = new Score;
    menu();
    checkMenuItems();

    View *view = new View(this);
    rattler = view->rattler;
    rattler->setFocus();

    connect(rattler, SIGNAL(setPoints(int)), view->lcd, SLOT(display(int)));
    connect(rattler, SIGNAL(setTrys(int)), view->trys, SLOT(set(int)));
    connect(rattler, SIGNAL(rewind()), view->pg, SLOT(rewind()));
    connect(rattler, SIGNAL(advance()), view->pg, SLOT(advance()));
    connect(view->pg, SIGNAL(restart()), rattler, SLOT(restartTimer()));

    connect(rattler, SIGNAL(togglePaused()), this, SLOT(togglePaused()));
    connect(rattler, SIGNAL(setScore(int)), score, SLOT(setScore(int)));

    menubar->show();
    view->show();
    setView(view);
}


void Game::menu()
{

    game = new QPopupMenu();
    CHECK_PTR( game );
    game->insertItem( i18n("New"), this, SLOT(newGame()),Key_F2);
    pauseID = game->insertItem( i18n("Pause"), this , SLOT(pauseGame()), Key_F3);
    game->insertItem( i18n("High Scores..."), this, SLOT(showHighScores()));
    game->insertSeparator();
    game->insertItem( i18n("&Quit"),  this, SLOT(quitGame()), CTRL+Key_Q );
    game->setCheckable( TRUE );

    balls = new QPopupMenu;
    CHECK_PTR( balls );
    ballsID[0] = balls->insertItem( i18n("0"));
    ballsID[1] = balls->insertItem( i18n("1"));
    ballsID[2] = balls->insertItem( i18n("2"));
    ballsID[3] = balls->insertItem( i18n("3"));
    balls->setCheckable( TRUE );
    connect(balls, SIGNAL(activated(int)), this, SLOT ( ballsChecked(int) ));

    snakes = new QPopupMenu;
    CHECK_PTR( snakes );
    snakesID[0] = snakes->insertItem( i18n("0"));
    snakesID[1] = snakes->insertItem( i18n("1"));
    snakesID[2] = snakes->insertItem( i18n("2"));
    snakesID[3] = snakes->insertItem( i18n("3"));
    snakes->setCheckable( TRUE );
    connect(snakes, SIGNAL(activated(int)), this,
	    SLOT ( snakesChecked(int) ));


    pix = new QPopupMenu;
    lookupBackgroundPixmaps();
    pixID.resize(backgroundPixmaps.count());

    if(backgroundPixmaps.count() == 0) {
	pix->insertItem(i18n("none"));
    } else {
        QStringList::ConstIterator it = backgroundPixmaps.begin();
        for(unsigned i = 0; it != backgroundPixmaps.end(); i++, it++) {
	    // since the filename may contain underscore, they
	    // are replaced with spaces in the menu entry
            QString s = QFileInfo( *it ).baseName();
	    s = s.replace(QRegExp("_"), " ");
	    pixID[i] = pix->insertItem(s, i);
	}
    }
    pix->setCheckable( TRUE );
    connect(pix, SIGNAL(activated(int)), this,
	    SLOT ( pixChecked(int) ));

    options = new QPopupMenu();
    CHECK_PTR( options );
    skillID[0] = options->insertItem( i18n("Beginner"));
    skillID[1] = options->insertItem( i18n("Intermediate"));
    skillID[2] = options->insertItem( i18n("Advanced"));
    skillID[3] = options->insertItem( i18n("Expert"));
    options->insertSeparator();
    options->insertItem(i18n("Balls"), balls);
    options->insertItem(i18n("Computer Snakes"), snakes);
    options->insertSeparator();
    options->insertItem(i18n("Select background color..."), this, SLOT(backgroundColor()));
    options->insertItem(i18n("Select background pixmap"), pix);
    options->insertSeparator();
    options->insertItem(i18n("Change keys..."),this, SLOT(confKeys()));
    options->insertSeparator();
    options->insertItem(i18n("Starting Room..."), this, SLOT(startingRoom()));

    options->setCheckable( TRUE );
    connect(options, SIGNAL(activated(int)), this, SLOT ( skillChecked(int) ));

    QPopupMenu *help = helpMenu(i18n("Snake Race")
                                      + " " + KSNAKE_VERSION
                                      + i18n("\n\nby Michel Filippi"
                                             " (mfilippi@sade.rhein-main.de)")
                                      + i18n("\n\nWith new hacks by\n Andrew Chant (achant@home.com)"));
    menubar = menuBar(); // auto-managed.
    CHECK_PTR( menubar );
    menubar->insertItem( i18n("&Game"), game );
    menubar->insertItem( i18n("&Options"), options );
    menubar->insertSeparator();
    menubar->insertItem( i18n("&Help"), help);
}

void Game::ballsChecked(int id)
{
    for ( int x = 0; x < 4; x++)
	if (ballsID[x] != id)
	    balls->setItemChecked( ballsID[x], FALSE );
	else { balls->setItemChecked( ballsID[x], TRUE );
	conf->writeEntry("Balls", x);
	rattler->setBalls(x);
	}
}

void Game::snakesChecked(int id)
{
    for ( int x = 0; x < 4; x++)
	if (snakesID[x] != id)
	    snakes->setItemChecked( snakesID[x], FALSE );
	else { snakes->setItemChecked( snakesID[x], TRUE );
	conf->writeEntry("ComputerSnakes", x);
	rattler->setCompuSnakes(x);
	}
}

void Game::skillChecked(int id)
{
    if (options->indexOf(id) > 3)
	return;

    for ( int x = 0; x < 4; x++)
	if (skillID[x] != id)
	    options->setItemChecked( skillID[x], FALSE );
	else { options->setItemChecked( skillID[x], TRUE );
	conf->writeEntry("Skill", x);
	rattler->setSkill(x);
	}
}

void Game::pixChecked(int id)
{
    for ( unsigned int x = 0; x < backgroundPixmaps.count(); x++)
	pix->setItemChecked( pixID[x] , pixID[x] == id );

	conf->writeEntry("Background", 2);
	conf->writeEntry("BackgroundPixmap",
				*backgroundPixmaps.at(id));

	rattler->reloadRoomPixmap();
}

void Game::checkMenuItems()
{
    balls->setItemChecked( ballsID[conf->readNumEntry("Balls", 1)], TRUE );
    snakes->setItemChecked( snakesID[conf->readNumEntry("ComputerSnakes", 1)], TRUE );
    options->setItemChecked( skillID[conf->readNumEntry("Skill", 1)], TRUE );

    QString path = conf->readEntry("BackgroundPixmap");
    for ( unsigned int x = 0; x < backgroundPixmaps.count(); x++) {
	if (path == *backgroundPixmaps.at(x)) {
	    pix->setItemChecked( x , TRUE );
	    break;
	}
    }
}

void Game::quitGame()
{
    kapp->quit();
}

void Game::showHighScores()
{
    score->display(-1);  // Magic number because bug in moc doesn't let us
                         // default 2 parameters.
}

void Game::newGame()
{
    rattler->restart();
}

void Game::pauseGame()
{
    rattler->pause();
}

void Game::togglePaused()
{
    static bool checked = FALSE;
    checked = !checked;
    game->setItemChecked( pauseID, checked );
}

void Game::startingRoom()
{
    int r = 0;
    StartRoom *sr = new StartRoom(conf->readNumEntry("StartingRoom", 1), &r);
    sr->exec();
    delete sr;

    if (r != 0) {
	conf->writeEntry("StartingRoom", r);
	rattler->setRoom(r);
    }
}

void Game::confKeys()
{
    Keys *keys = new Keys();
    if (keys->exec() == QDialog::Accepted)
	rattler->initKeys();
    delete keys;
}

//taken from KReversi
void Game::backgroundColor()
{
    QString s;
    QColor c;
      if(KColorDialog::getColor(c)) {
	conf->writeEntry("Background", 1);
	conf->writeEntry("BackgroundColor", c);
	rattler->reloadRoomPixmap();
      }
}

void Game::lookupBackgroundPixmaps()
{
    backgroundPixmaps = KGlobal::dirs()->
	findAllResources("appdata", "backgrounds/*.xpm");
}






/************************** main ******************************/





int main( int argc, char **argv )
{
  KAboutData aboutData( "ksnake", I18N_NOOP("KSnakeRace"), 
    KSNAKE_VERSION, description, KAboutData::License_GPL, 
    "(c) 1997-2000, Your Friendly KSnake Developers");
  aboutData.addAuthor("Michel Filippi",0, "mfilippi@sade.rhein-main.de");
  aboutData.addAuthor("Robert Williams");
  aboutData.addAuthor("Andrew Chant",0, "achant@home.com");
  KCmdLineArgs::init( argc, argv, &aboutData );

  KApplication a;

  Game g;
  a.setMainWidget( &g );
  g.resize(500,575);
  g.show();
  return a.exec();
}
