
/*
  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 <kapplication.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <klocale.h>
#include <kconfig.h>
#include <kcolordialog.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>

#include <kstdgameaction.h>

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

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

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

#include "version.h"
#include <kaction.h>
#include <kstdaction.h>
#include <kkeydialog.h>

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

Game::Game() :  KMainWindow(0)
{
    setCaption( kapp->caption() );

    setIcon(i18n("Snake Race"));

    conf = kapp->config();
    levels = new Levels();
    score  = new Score;
    menu();
    checkMenuItems();

    View *view = new View(this); //Lots of stuff happens in View::View - namely rattler creation
    rattler = view->rattler;
    rattler->reloadRoomPixmap();
    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)));

    setCentralWidget(view);
}

Game::~Game()
{
    delete score;
    delete levels;
}


void Game::slotConfigureKeys()
{
  KKeyDialog::configure( actionCollection(), this );
}

void Game::menu()
{
    KStdAction::keyBindings( this, SLOT( slotConfigureKeys() ), actionCollection() );
    KStdGameAction::gameNew(this, SLOT(newGame()), actionCollection());
    pause = KStdGameAction::pause(this, SLOT(pauseGame()), actionCollection());
    KStdGameAction::highscores(this, SLOT(showHighScores()), actionCollection());
    KStdGameAction::quit( this, SLOT(quitGame()), actionCollection());

    skills[0] = new KRadioAction(i18n("Beginner"), 0, this, SLOT(skillChecked()),
				 actionCollection(), "opt_beginner");
    skills[1] = new KRadioAction(i18n("Intermediate"), 0, this, SLOT(skillChecked()),
				 actionCollection(), "opt_intermediate");
    skills[2] = new KRadioAction(i18n("Advanced"), 0, this, SLOT(skillChecked()),
				 actionCollection(), "opt_advanced");
    skills[3] = new KRadioAction(i18n("Expert"), 0, this, SLOT(skillChecked()),
				 actionCollection(), "opt_expert");
    for (uint i=0; i<4; i++)
	skills[i]->setExclusiveGroup("skill");

    balls = new KSelectAction(i18n("&Balls"), 0, this, SLOT(ballsChecked()),
			      actionCollection(), "opt_balls");
    QStringList list;
    list.append("0");
    list.append("1");
    list.append("2");
    list.append("3");
    balls->setItems(list);

    ballsAI = new KSelectAction(i18n("Balls AI"), 0, this, SLOT(ballsAIChecked()),
				actionCollection(), "opt_ballsai");
    QStringList bai;
    bai.append(i18n("Default"));
    bai.append(i18n("Dumb"));
    bai.append(i18n("Killer"));
    ballsAI->setItems(bai);

    snakes = new KSelectAction(i18n("&Snakes"), 0, this, SLOT(snakesChecked()),
			       actionCollection(), "opt_snakes");
    snakes->setItems(list);

    snakesAI = new KSelectAction(i18n("Snakes AI"), 0, this, SLOT(snakesAIChecked()),
				 actionCollection(), "opt_snakesai");
    QStringList sai;
    sai.append(i18n("Random"));
    sai.append(i18n("Eater"));
    sai.append(i18n("Killer"));
    snakesAI->setItems(sai);

    new KAction(i18n("Change Keys..."),0, this, SLOT(confKeys()),
		actionCollection(), "opt_change_keys");
    new KAction(i18n("Starting Room..."), 0, this, SLOT(startingRoom()),
		actionCollection(), "opt_startroom");

    new KAction(i18n("Select Background Color..."), 0, this, SLOT(backgroundColor()),
		actionCollection(), "opt_select_background");

    lookupBackgroundPixmaps();

    list.clear();

    if (backgroundPixmaps.count() == 0) {
	list.append(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("_"), " ");
	    list.append(s);
	}
    }

    pix = new KSelectAction(i18n("Select Background Pixmap"), 0, this, SLOT(pixChecked()),
			    actionCollection(), "opt_backgrounds");
    pix->setItems(list);
    createGUI();
}

void Game::ballsChecked()
{
    int x = balls->currentItem();
    conf->writeEntry("Balls", x);
    rattler->setBalls(x);
}

void Game::ballsAIChecked()
{
	int x = ballsAI->currentItem();
	conf->writeEntry("BallsAI", x);
	rattler->setBallsAI(x);
}

void Game::snakesChecked()
{
    int x = snakes->currentItem();
    conf->writeEntry("ComputerSnakes", x);
    rattler->setCompuSnakes(x);
}

void Game::snakesAIChecked()
{
	int x = snakesAI->currentItem();
	conf->writeEntry("SnakesAI", x);
	rattler->setSnakesAI(x);
}

void Game::skillChecked()
{
    for ( int x = 0; x < 4; x++)
	if (skills[x]->isChecked()) {
	    conf->writeEntry("Skill", x);
	    rattler->setSkill(x);
	    return;
	}
}

void Game::pixChecked()
{
    int x = pix->currentItem();
    conf->writeEntry("Background", 2);
    conf->writePathEntry("BackgroundPixmap",
		     *backgroundPixmaps.at(x));

    rattler->reloadRoomPixmap();
}

void Game::checkMenuItems()
{
    conf->setGroup("General");
    balls->setCurrentItem(conf->readNumEntry("Balls", 1));
	ballsAI->setCurrentItem(conf->readNumEntry("BallsAI", 0));
    snakes->setCurrentItem(conf->readNumEntry("ComputerSnakes", 1));
	snakesAI->setCurrentItem(conf->readNumEntry("SnakesAI", 0));
    int skill = conf->readNumEntry("Skill", 1);
    if (skill < 0 || skill > 3)
	skill = 1;
    skills[skill]->setChecked( true );

    pix->setCurrentItem(0);

    QString path = conf->readPathEntry("BackgroundPixmap");
    for ( unsigned int x = 0; x < backgroundPixmaps.count(); x++) {
	if (path == *backgroundPixmaps.at(x)) {
	    pix->setCurrentItem( x );
	    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;
    pause->setEnabled(checked);
}

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

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

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

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

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

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






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





int main( int argc, char **argv )
{
  KAboutData aboutData( "ksnake", I18N_NOOP("KSnakeRace"),
    KSNAKE_VERSION, description, KAboutData::License_GPL,
			I18N_NOOP("(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");
	aboutData.addCredit("André Luiz dos Santos", "AI stuff", "andre@netvision.com.br");
  KCmdLineArgs::init( argc, argv, &aboutData );

  KApplication a;
  KGlobal::locale()->insertCatalogue("libkdegames");

  Game *g = new Game();
  a.setMainWidget( g );
  g->resize(500,575);
  g->show();
  return a.exec();
}

#include "game.moc"
