/***************************************************************************
                          kinsectizid.cpp  -  description
                             -------------------
    begin                : Mon Apr 3 2000
    copyright            : (C) 2000 by Frank von Daak
    email                : frank.fun@kpage.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 "kinsectizid.h"

#define PLAY_TIME 75

#define MAX_LEVELS	16
#define	MUST_HIT 50;

KInsectizid::KInsectizid(QWidget *parent, const char *name, WFlags f) : QWidget(parent, name, f)
{
	gameover = false;
	blocked = false;
	hiShow = false;
	hits = 0;
	miss = 0;
	level = 1;
	points = 0;
	MUST_HITS = MUST_HIT;
	paused = false;
	sound = false;
	timer = new QTimer();

	this->setBackgroundColor(black);

    QFont fnt( "helvetica", 24 );
    QColorGroup grp( darkBlue, black, QColor( 0, 255, 0 ),
	    QColor( 64, 64, 64 ), black, blue, black );
    QPalette pal( grp, grp, grp );

	bulletWidg = new BulletWidg(this);
	bulletWidg->setGeometry(0,0,0,0);

	countWidg = new QWidget(this);
	countWidg->setBackgroundColor(black);
	countWidg->setGeometry(0,550,800,50);

	QLabel *hitLab = new QLabel(i18n("Hits"), countWidg);
	hitLab->setGeometry(20,10,60,30);
	hitLab->setFont(fnt);
	hitLab->setPalette( pal );

	hitLcd = new QLCDNumber(3,countWidg);
	hitLcd->setFrameStyle( QFrame::NoFrame );
	hitLcd->setGeometry(80,5,50,40);
	hitLcd->setPalette(pal);
	hitLcd->display("-");

	QLabel *missLab = new QLabel(i18n("Missed"), countWidg);
	missLab->setGeometry(150,10,90,30);
	missLab->setFont(fnt);
	missLab->setPalette( pal );

	missLcd = new QLCDNumber(3,countWidg);
	missLcd->setGeometry(240,5,50,40);
	missLcd->setFrameStyle( QFrame::NoFrame );
	missLcd->setPalette(pal);
	missLcd->display("-");

	QLabel *pointLab = new QLabel(i18n("Score :"), countWidg);
	pointLab->setGeometry(290,10,80,30);
	pointLab->setFont(fnt);
	pointLab->setPalette( pal );

	pointLcd = new QLCDNumber(6, countWidg);
	pointLcd->setGeometry(370,1,80,48);
	pointLcd->setFrameStyle( QFrame::NoFrame );
	pointLcd->setPalette(pal);
	pointLcd->display("-");

	QLabel *levLab = new QLabel(i18n("Level"), countWidg);
	levLab->setGeometry(450,10,70,30);
	levLab->setFont(fnt);
	levLab->setPalette( pal );
	
	levLcd = new QLCDNumber(2,countWidg);
	levLcd->setGeometry(520,1,80,48);
	levLcd->setFrameStyle( QFrame::NoFrame );
	levLcd->setPalette(pal);
	levLcd->display("-");

// The Timer .....
	gameTimer = new GameTimer(this);
	connect(gameTimer, SIGNAL(timeleft(QString)), this, SLOT(displayTime(QString)));
	connect(gameTimer, SIGNAL(timerExit()), this, SLOT(timeOut()));

	QLabel *timerLab = new QLabel(i18n("Time :"), countWidg);
	timerLab->setGeometry(670,10,60,30);
	timerLab->setFont(fnt);
	timerLab->setPalette( pal );

	timerLcd = new QLCDNumber(4, countWidg);
	timerLcd->setGeometry(730,5,60,40);
	timerLcd->setFrameStyle( QFrame::NoFrame );
	timerLcd->setPalette(pal);
	timerLcd->display("-");

// Needed for the cursor
	this->setMouseTracking(true);

// Initialize the GameField
	initGameField(level);

//	bulletWidg->addBullets(10);
	startGame();
}

KInsectizid::~KInsectizid()
{
}

void KInsectizid::initGameField(int level)
{
// The Gamefield
	gamefield = new GameField(this);
	gamefield->setLevel(level);

	gamefield->setGeometry(0,0,800,550);
	connect(gamefield, SIGNAL(gnatKilled(bool)), this, SLOT(addPoint(bool)));
	connect(gamefield, SIGNAL(magKilled(bool)), this, SLOT(addMagPoint(bool)));
	connect(gamefield, SIGNAL(tuxKilled(bool)), this, SLOT(addTuxPoint(bool)));
	connect(gamefield, SIGNAL(reload()), this, SLOT(reloadGun()));
	gamefield->show();
}

void KInsectizid::removeGameField()
{
	gamefield->hide();
	disconnect(gamefield, SIGNAL(gnatKilled(bool)), this, SLOT(addPoint(bool)));
	disconnect(gamefield, SIGNAL(magKilled(bool)), this, SLOT(addMagPoint(bool)));
	disconnect(gamefield, SIGNAL(reload()), this, SLOT(reloadGun()));
	disconnect(gamefield, SIGNAL(tuxKilled(bool)), this, SLOT(addTuxPoint(bool)));
	delete(gamefield);
}

void KInsectizid::startGame()
{
	gamefield->newGame();
	gamefield->addGnats( 4 );
	QString txt;
	txt.sprintf(i18n("Let's kill them  !!!\n"
				"Press SpaceBar to start the game !\n"
				"You have to kill at least %d insects, now..."), MUST_HITS);
	gamefield->showText( txt, white );
}

void KInsectizid::mouseMoveEvent(QMouseEvent *me)
{
	if ( me->pos().y() <= 550 )
		this->setCursor(crossCursor);
	else
		this->setCursor(arrowCursor);
}

void KInsectizid::addPoint(bool hit)
{
	bulletWidg->startTimer(40);
	if ( hit ) {
		hits++;
		hitLcd->display(hits);
		points = points+(20+(level*5));
	} else {
		miss++;
		missLcd->display(miss);
		if ( points > 0 ) {
			points = points-(20+(level*5));
			if ( points <= 0 )
				points = 0;
		}
	}
	pointLcd->display(points);
}

void KInsectizid::addMagPoint(bool hit)
{
	bulletWidg->startTimer(40);
	if ( hit ) {
		hits++;
		hitLcd->display(hits);
		points = points+50;
	}
	pointLcd->display(points);
}

void KInsectizid::addTuxPoint(bool hit)
{
	bulletWidg->startTimer(40);
	if ( hit ) {
		miss++;
		missLcd->display(miss);
		if ( points > 150 )
			points = points-150;
		else
			points = 0;
	}
	pointLcd->display(points);
}

void KInsectizid::reloadGun()
{
	bulletWidg->addBullets(10);
}

void KInsectizid::displayTime(QString time)
{
	timerLcd->display(time);
	if ( points > 0 ) {
		points = points-5;
		pointLcd->display(points);
	}
}

void KInsectizid::timeOut()
{
	for ( int i=1 ; i <= (10-gamefield->shots); i++) {
		bulletWidg->removeBullets(0);
	}
	
	if ( hits < MUST_HITS ) {
		gamefield->showText( i18n( "\t\tGame Over !!!!" ), yellow );
		gamefield->started=false;
		level = 1;
		blocked = true;
		timer->start(8000);
		connect(timer, SIGNAL(timeout()), this, SLOT(showHiscores()));
		gameover = true;
	// Hiscore reached ?
		kapp->getConfig()->setGroup("Hiscores");
		int svHi;
		QString tmp;
		for ( int i=15; i >= 1 ; i--) {
			tmp.sprintf("Score%d",i);
			svHi = kapp->getConfig()->readNumEntry(tmp,0);
			if ( points > svHi ) {
				blTimer = new QTimer();
				blTimer->start(3000);
				connect(blTimer, SIGNAL(timeout()), this, SLOT(unblockIt()));
				break;
			} else {
				points = 0;
				blocked = false;
			}
		}

	} else {
		if ( level <= 2 ) {
			MUST_HITS = MUST_HITS+10;
		} else if ( level <= 5 ) {
			MUST_HITS = MUST_HITS+5;
		} else {
			MUST_HITS = MUST_HITS+2;
		}
		QString txt;
		txt.sprintf(i18n("\t\tT I M E O U T  !!!\n"
					"Press SpaceBar for the next level !\n"
					"You have to kill at least %d insects, now..."), MUST_HITS);
		gamefield->showText( txt , yellow );
		gamefield->started=false;
		level++;
	}
}

void KInsectizid::keyPressEvent( QKeyEvent *ke)
{
	if ( !gamefield->started && ke->key() == Key_Space && !gameover ) {
		removeGameField();
		initGameField(level);

		gamefield->newGame();
		gamefield->addGnats( 4 );
		gamefield->started = true;
		gamefield->sound=sound;
		gameTimer->maxTime(PLAY_TIME);
		gameTimer->startTimer(1000);

	// Now add some bullets
		bulletWidg->addBullets(10);
	
	// Set the Hits, and miss to 0
		missLcd->display(0);
		hitLcd->display(0);
		levLcd->display(level);
		miss = 0;
		hits = 0;
		timer->stop();
		disconnect(timer, SIGNAL(timeout()), this, SLOT(showHiscores()));
		delete(timer);
		timer = new QTimer();
	} else if ( !gamefield->started && ke->key() == Key_Space && gameover && !hiShow && !blocked ) {
		removeGameField();
		initGameField(level);
		startGame();
		gameover = false;
	// Set the Hits, and miss to 0
		missLcd->display(0);
		hitLcd->display(0);
		levLcd->display(level);
		miss = 0;
		hits = 0;
		timer->stop();
		disconnect(timer, SIGNAL(timeout()), this, SLOT(showHiscores()));
		delete(timer);
		timer = new QTimer();
	} else if ( !gamefield->started && ke->key() == Key_Space && gameover && hiShow && !blocked ) {
		removeGameField();
		killTimers();
		delete(hiField);
		delete(hiView);
		delete(hiscore);
		for ( int i=1; i <= 15; i++ ){
			delete(hiNames[i]);
			delete(hiScores[i]);
		}
		hiShow = false;
		initGameField(level);
		startGame();
		gameover = false;
	// Set the Hits, and miss to 0
		missLcd->display(0);
		hitLcd->display(0);
		levLcd->display(level);
		miss = 0;
		hits = 0;
		timer->stop();
		disconnect(timer, SIGNAL(timeout()), this, SLOT(showHiscores()));
		delete(timer);
		timer = new QTimer();
	} else if ( ke->key() == Key_P && !paused && gamefield->started ) {
		gamefield->killTimers();
		gameTimer->killTimers();
		gamefield->showPause(true);
		gamefield->view->paused=true;
		paused = true;
	} else if ( ke->key() == Key_P && paused && gamefield->started ) {
		gamefield->startTimer(40);
		gameTimer->startTimer(1000);
		gamefield->showPause(false);
		gamefield->view->paused=false;
		paused = false;
	} else if ( ke->key() == Key_Escape && gamefield->started && !paused) {
		gamefield->killTimers();
		gameTimer->killTimers();
		gamefield->view->paused=true;
		paused = true;
		switch (QMessageBox::warning( this, i18n("Exit Game ?"),
				i18n("Do you realy want to exit ?"),
				i18n("Yes"), i18n("No"), 0,0,1) ) {
			case 0:
				exit(0);
				break;
			case 1:
				gamefield->startTimer(40);
				gameTimer->startTimer(1000);
				gamefield->showPause(false);
				gamefield->view->paused=false;
				paused = false;
				break;
			}
	} else if ( ke->key() == Key_Escape && gamefield->started && paused ) {
		switch (QMessageBox::warning( this, i18n("Exit Game ?"),
				i18n("Do you realy want to exit ?"),
				i18n("Yes"), i18n("No"), 0,0,1) ) {
			case 0:
				exit(0);
				break;
			case 1:
				break;
			}
	} else if ( ke->key() == Key_Escape && !gamefield->started ) {
		switch (QMessageBox::warning( this, i18n("Exit Game ?"),
				i18n("Do you realy want to exit ?"),
				i18n("Yes"), i18n("No"), 0,0,1) ) {
			case 0:
				exit(0);
				break;
			case 1:
				break;
			}
	} else if ( ke->key() == Key_C ){
		chiefHide(gamefield->started);
	} else if ( ke->key() == Key_S ) {
		if ( sound ) {
			sound = false;
			gamefield->sound=false;
		} else {
			sound = true;
			gamefield->sound=true;
		}
	}
}

void KInsectizid::chiefHide(bool started)
{
	if ( started ) {
		gamefield->killTimers();
		gameTimer->killTimers();
		gamefield->showPause(true);
		gamefield->view->paused=true;
		paused = true;
		this->setCaption(i18n("KNetwork-Manager"));
		this->iconify();
	} else {
		this->setCaption(i18n("KNetwork-Manager"));
		this->iconify();
	}
}

void KInsectizid::closeEvent(QCloseEvent *ce)
{
	if ( gamefield->started ) {
		gamefield->killTimers();
		gameTimer->killTimers();
		gamefield->view->paused=true;
		paused = true;
		switch (QMessageBox::warning( this, i18n("Exit Game ?"),
				i18n("Do you realy want to exit ?"),
				i18n("Yes"), i18n("No"), 0,0,1) ) {
			case 0:
				exit(0);
				break;
			case 1:
				gamefield->startTimer(40);
				gameTimer->startTimer(1000);
				gamefield->showPause(false);
				gamefield->view->paused=false;
				paused = false;
				break;
			}
	} else {
		switch (QMessageBox::warning( this, i18n("Exit Game ?"),
				i18n("Do you realy want to exit ?"),
				i18n("Yes"), i18n("No"), 0,0,1) ) {
			case 0:
				exit(0);
				break;
			case 1:
				break;
			}
	}
}

void KInsectizid::showHiscores()
{
	if ( !hiShow ) {
		hiShow = true;
		timer->stop();
		timer->start(15000);

		gamefield->hide();
	
		hiY = 600;

		hiField = new QwSpriteField(800, 550, 16, 100);

		hiView = new QwSpriteFieldView(hiField,this,0);
		hiView->setGeometry(0,0,800,550);
		hiView->setBackgroundColor(black);

		hiscore = new QwTextSprite;

		hiscore->setText( i18n("Hiscores ....") );
		hiscore->setFont(QFont("helvetica", 32, QFont::Bold));
		hiscore->setColor( red );
		hiscore->moveTo( (width()-hiscore->boundingRect().width()) / 2, 600 );

	//Time to get the HiScores
		QString hiNTxt, hiSTxt, tmp, tmp2;

		hiNTxt = "";
		hiSTxt = "";
		kapp->getConfig()->setGroup("Hiscores");

		for ( int i=1; i <= 15; i++) {
			tmp.sprintf("Player%d",i);
			tmp = kapp->getConfig()->readEntry(tmp,"Empty");
			tmp2.sprintf("%d. ", i);
			hiNTxt = tmp2;
			hiNTxt += tmp;
			hiNames[i] = new QwTextSprite;
			hiNames[i]->setText( hiNTxt );
			hiNames[i]->setFont(QFont("helvetica", 28, QFont::Bold));
			hiNames[i]->setColor(yellow);
			hiNames[i]->moveTo((width()/2)-(hiNames[i]->boundingRect().width() )-30, hiY+50+(i*30));
			hiNames[i]->show();
		}

		for ( int i=1; i <= 15 ; i++ ) {
			tmp.sprintf("Score%d",i);
			tmp = kapp->getConfig()->readEntry(tmp, "0");
			hiScores[i] = new QwTextSprite;
			hiScores[i]->setText( tmp );
			hiScores[i]->setFont(QFont("helvetica", 28, QFont::Bold));
			hiScores[i]->setColor(yellow);
			hiScores[i]->moveTo( (width()/2)+200, hiY+50+(i*30) );
			hiScores[i]->show();
		}

		hiscore->show();

		startTimer(10);

		hiView->show();
	} else {
		hiShow = false;
		killTimers();
		delete(hiField);
		delete(hiView);
		delete(hiscore);
		for ( int i=1; i <= 15; i++ ){
			delete(hiNames[i]);
			delete(hiScores[i]);
		}
		gamefield->show();
	}
}

void KInsectizid::timerEvent(QTimerEvent *te)
{
	killTimers();
	startTimer(10);
	hiY = hiY-2;
	hiscore->moveTo( (width()-hiscore->boundingRect().width()) / 2, hiY );
	for ( int i=1; i <= 15; i++ ) {
		hiNames[i]->moveTo( (width()/2)-(hiNames[i]->boundingRect().width() )-30, hiY+50+(i*50) );
		hiScores[i]->moveTo( (width()/2)+200, hiY+50+(i*50) );
	}
	
	hiField->update();

	if ( hiY <= -850 )
		hiY = 600;
}

void KInsectizid::newHiScore(int pts)
{
	hiScoreDialog = new HiScoreDialog(this);
	hiScoreDialog->setFixedSize(600,400);
	connect(hiScoreDialog, SIGNAL(newName(QString)), this, SLOT(saveNewHi(QString)));
	hiScoreDialog->show();
}

void KInsectizid::saveNewHi(QString name)
{
	QString tmp, tmp2, tmp3;
	QString on[15];
	int op[15];
	int svHi;

	kapp->getConfig()->setGroup("Hiscores");

	for (int i=1; i <= 15 ; i++) {
		tmp.sprintf("Score%d",i);
		svHi = kapp->getConfig()->readNumEntry(tmp,0);
		if ( points >= svHi ) {
			tmp2.sprintf("Player%d",i);
			// Read the old HiScores to buffer
			for ( int o=i; o <= 15 ; o++) {
				tmp3.sprintf("Score%d",o);
				op[o] = kapp->getConfig()->readNumEntry(tmp3,0);
				tmp3.sprintf("Player%d",o);
				on[o] = kapp->getConfig()->readEntry(tmp3, "Empty");
			}
			// Write current HiScore
			kapp->getConfig()->writeEntry(tmp, points);
			kapp->getConfig()->writeEntry(tmp2, name);
			// Write back HiScores from buffer
			for ( int o=i; o <= 15 ; o++) {
				tmp3.sprintf("Score%d",o+1);
				kapp->getConfig()->writeEntry(tmp3, op[o]);
				tmp3.sprintf("Player%d",o+1);
				kapp->getConfig()->writeEntry(tmp3, on[o]);
			}
			kapp->getConfig()->sync();
			break;
		}
	}

	hiScoreDialog->hide();
	disconnect(hiScoreDialog, SIGNAL(newName(QString)), this, SLOT(saveNewHi(QString)));
	delete(hiScoreDialog);
}

void KInsectizid::unblockIt()
{
	blTimer->stop();
	blocked = false;
	newHiScore(points);
	points = 0;
}