/***************************************************************************
                          mainwindow.cpp  -  description
                             -------------------
    begin                : Sun Oct 21 2001
    copyright            : (C) 2001 by Primoz Anzur (zer0Kode)
    email                : zerokode@yahoo.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "mainwindow.h"
#include "mainwindow.moc"
#include <kglobal.h>
#include <qfile.h>
#include <kdebug.h>

#include "kwritewords.h"
#include "scores.h"
#include "mwconfig.h"
#include "answer.h"
#include <pwd.h>
#include <kprocess.h>


MainWindow::MainWindow(QWidget *parent, const char *name) : FrontEnd(parent, name)
{
	guesses=0L;
	tGuesses=0L;
	messups=0L;
	solvedWords=0L;

	//config
	config = kapp->config();

	//popup menu
	mainMenu = new KPopupMenu(this);
	loadPopupMenu();
	btnConfig->setPopup(mainMenu);

	//Help Menu
	helpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData(), true);
	btnHelp->setPopup(helpMenu->menu());

	setIcon(QPixmap(locate("icon","locolor/16x16/apps/kmessedwords.png")));
	kMessedDataDir=locate("data","kmessedwords/");

	setLocalDictionary=locateLocal("data","kmesswords/");
	QFile f(setLocalDictionary+"easy.txt");
	if (! f.exists()) {
		setLocalDictionary=locate("data","kmessedwords/");
	}
	
	setCaption(i18n ("KMessedWords %1").arg(LOCAL_VERSION));
	guesses = 0;
	btnMess->setFocus();	//focus on "Messup" button

	first_run(); //makes the config file and all...
	check_update();
	winRefresh();

	cfg= new Config();
	connect(cfg,SIGNAL(sig_reload()), this, SLOT(winRefresh()) );

	mainScreen->setAutoMask(true);
	//setBackgroundOrigin(QWidget::ParentOrigin);
	//mainScreen->setBackgroundOrigin(QLabel::ParentOrigin); //FIXME!!! I donno, how to make transparent QLabel
}

MainWindow::~MainWindow(){}

void MainWindow::slot_close(){
	close();
}

void MainWindow::randomizer(int level)
{
	reloadStructure();
	if(level==0){
		lines=configInputData.easyDict->numLines();
		cleanWord=configInputData.easyDict->textLine(random.getLong(lines)).stripWhiteSpace();
	}
	if(level==1){
		lines=configInputData.mediumDict->numLines();
		cleanWord=configInputData.mediumDict->textLine(random.getLong(lines)).stripWhiteSpace();
	}
	if(level==2){
		lines=configInputData.hardDict->numLines();
		cleanWord=configInputData.hardDict->textLine(random.getLong(lines)).stripWhiteSpace();
	}

}

void MainWindow::confuse_words() {
	QPtrList <QChar> messList;
	messList.setAutoDelete(true);

	// Put all letters of the word in the list
	for(unsigned int i = 0; i < cleanWord.length(); i++) {
		messList.append(new QChar(cleanWord[i]));
	}

	// Shuffle the list
	random.randomize(&messList);

	// Give the messed up string the right length.
	messedWord.fill(' ', cleanWord.length());

	// Copy all letters to the messed u-p string.
	for(unsigned int i = 0; i < cleanWord.length(); i++) {
		messedWord[i] = *(messList.at(i));
	}
}


void MainWindow::slot_messup() {
	// enable Buttons on first button click
	if (!guessedText->isEnabled()) {
		guessedText->setEnabled(true);
		txtGuess->setEnabled(true);
		btnTry->setEnabled(true);
		btnMess->setDefault(false);
	}
	randomizer(leveler->currentItem());
	confuse_words();

	//prevents clean words to be displayed...
	if (cleanWord.stripWhiteSpace()==messedWord.stripWhiteSpace()) 	{
		slot_messup();
	//messups ++;  //this is for nothing more than monitoring the completenumbers of messed and clean words...
	} else 	{
		messups++;
		mainScreen->setText(messedWord.stripWhiteSpace());
		guessedText->setFocus();
	}

}

void MainWindow::slot_try() {
	if(guessedText->text() != "") {
		guesses++;
		tGuesses++;
		kdDebug() << "try " << guessedText->text()  << endl;
		kdDebug() << "answare " << cleanWord << endl;
		
		config->setGroup("Environment");
		bool gfxStyle=config->readBoolEntry("UseGfxStyle",true);
		config->sync();
		
		if (gfxStyle){
			if(QString::compare(guessedText->text().stripWhiteSpace(),cleanWord.stripWhiteSpace())==0) { //when you are right in graphic environment...
				
				Answer *answer = new Answer();
				emit answer->doAnswer(true);
				connect(answer, SIGNAL(gameExit()), this, SLOT(theEnd()) );
				connect(answer, SIGNAL(gameReplay()), this, SLOT(theReply()) );
				answer->show();
								
			} else {
				Answer *answer = new Answer();
				emit answer->doAnswer(false);
				answer->show();
				
				guessedText->setText("");
			}
		} else {
			if(QString::compare(guessedText->text().stripWhiteSpace(),cleanWord.stripWhiteSpace())==0) {
				kdDebug() << "correct" << endl;
				if (KMessageBox::questionYesNo(this,i18n("Congratulations! You got the right answer after ") + guessedString.sprintf("%i", guesses) + i18n(" attempt.\nDo you want to play again?"), "KMessedWords") ==4) {  //this kills the app, if you don't wanna play anymore...
					//scoring final calc thingy goes here :)
					config->setGroup("Environment");
					shareLoginName=config->readEntry("GamerName", "");
					config->sync();	

					solvedWords++;
					write_scores();
					justtext=i18n("Name: ") +  shareLoginName + "\n"+ i18n("Solved:") + justtext.sprintf("%i\n",  solvedWords)+ i18n ("Rounds:") + justtext.sprintf("%i\n" , messups);
					KMessageBox::information(this,justtext);
					close();
				} else	{ //here goes on...
					//scoring calc thingy goes here :)
					solvedWords++;
					guesses=0;
					guessedText->setText("");
					slot_messup();
				}
			
			} else 	{ //if you are wrong...
				kdDebug() << "wrong" << endl;
				KMessageBox::information(this,i18n("You missed! Try again :o)"), "MainWindow"); //this should be replaced by a graphical box [?]
				guessedText->setText("");
			}
		} //end dialog
			
	}//end graphic style...
}

void MainWindow::slot_textAccel(){
	if(guessedText->text() != "") {
		slot_try();
	}
}

void MainWindow::slot_openBook(){
	showConfig.show();
}

void MainWindow::reloadStructure(){
	//this too is a-must-have for the paths and fie checkings and stuff...
	setLocalDictionary=locateLocal("data","kmesswords/"); //<-this NEEDS to be there due to the info, that is in the Locate path [graphics and files]
	QFile f(setLocalDictionary+"easy.txt");
	if (! f.exists()){
		setLocalDictionary=locate("data","kmessedwords/");
	}

	//this is just a patch.. It reloads the files into the dictionary buffer...
	QFile openEasyFile(setLocalDictionary+"easy.txt");
	openEasyFile.open(IO_ReadOnly);
	QTextStream readEasyStr(&openEasyFile);
	configInputData.easyDict->setText(readEasyStr.read().stripWhiteSpace());
	openEasyFile.close();

	QFile openMediumFile(setLocalDictionary+"medium.txt");
	openMediumFile.open(IO_ReadOnly);
	QTextStream readMediumStr(&openMediumFile);
	configInputData.mediumDict->setText(readMediumStr.read().stripWhiteSpace());
	openMediumFile.close();

	QFile openHardFile(setLocalDictionary+"hard.txt");
	openHardFile.open(IO_ReadOnly);
	QTextStream readHardStr(&openHardFile);
	configInputData.hardDict->setText(readHardStr.read().stripWhiteSpace());
	openHardFile.close();
}

void MainWindow::slot_scores(){
	showScores.show(); //much better solution... It shows only one instance of the window...
}

void MainWindow::read_scores(){
	for (int i=0; i<=9; i++){
		HighScores showScores;
		config->setGroup("Easy_scores");
		readName[i]=config->readEntry(varnames.sprintf("name%i",i),0);
		readSolved[i]=config->readNumEntry(varsolved.sprintf("solved%i",i),0);
		readRounds[i]=config->readNumEntry(varrounds.sprintf("rounds%i",i),0);
		config->sync();
	}
}

void MainWindow::write_scores(){
	config->setGroup("Environment");
	shareLoginName=config->readEntry("GamerName", "");
	config->sync();

	//this is for the levels...
	if (leveler->currentItem()==0){
		for (int i=0; i<=9; i++){ //we load everything in cache
			config->setGroup("Easy_scores");
			readName[i]=config->readEntry(varnames.sprintf("name%i",i),"");
			readSolved[i]=config->readNumEntry(varsolved.sprintf("solved%i",i),0);
			readRounds[i]=config->readNumEntry(varrounds.sprintf("rounds%i",i),0);
			readGuesses[i]=config->readNumEntry(varguesses.sprintf("guesses%i",i),0);
			config->sync();
		}

		int a;
		for (int i=9; i>=0; i--) {//...and now we check each score from lowest to highest
			if ((readSolved[i]<=solvedWords) && (readSolved[i-1]>solvedWords)) {
				config->writeEntry(varnames.sprintf("name%i",i), shareLoginName);
				config->writeEntry(varsolved.sprintf("solved%i",i),solvedWords);
				config->writeEntry(varrounds.sprintf("rounds%i",i),messups);
				config->writeEntry(varguesses.sprintf("guesses%i",i),tGuesses);
				a=i;
				config->sync();
			}
		}

		for (int x=a;  x<=9; x++) {//this will write the scores for a level lower...
			config->writeEntry(varnames.sprintf("name%i",x+1), readName[x]);
			config->writeEntry(varsolved.sprintf("solved%i",x+1),readSolved[x]);
			config->writeEntry(varrounds.sprintf("rounds%i",x+1),readRounds[x]);
			config->writeEntry(varguesses.sprintf("guesses%i",x+1),readGuesses[x]);
			config->sync();
		}
	} else if (leveler->currentItem()==1) {
		for (int i=0; i<=9; i++) {//we load everything in cache
			config->setGroup("Medium_scores");
			readName[i]=config->readEntry(varnames.sprintf("name%i",i),"");
			readSolved[i]=config->readNumEntry(varsolved.sprintf("solved%i",i),0);
			readRounds[i]=config->readNumEntry(varrounds.sprintf("rounds%i",i),0);
			readGuesses[i]=config->readNumEntry(varguesses.sprintf("guesses%i",i),0);
			config->sync();
		}

		int a;
		for (int i=9; i>=0; i--) { //...and now we check each score from lowest to highest
			if ((readSolved[i]<=solvedWords) && (readSolved[i-1]>solvedWords)) {
				config->writeEntry(varnames.sprintf("name%i",i), shareLoginName);
				config->writeEntry(varsolved.sprintf("solved%i",i),solvedWords);
				config->writeEntry(varrounds.sprintf("rounds%i",i),messups);
				config->writeEntry(varguesses.sprintf("guesses%i",i),tGuesses);
				a=i;
				config->sync();
			}
		}

		for (int x=a;  x<=9; x++) {//this will write the scores for a level lower...
			config->writeEntry(varnames.sprintf("name%i",x+1), readName[x]);
			config->writeEntry(varsolved.sprintf("solved%i",x+1),readSolved[x]);
			config->writeEntry(varrounds.sprintf("rounds%i",x+1),readRounds[x]);
			config->writeEntry(varguesses.sprintf("guesses%i",x+1),readGuesses[x]);
			config->sync();
		}
	} else if (leveler->currentItem()==2) {
		for (int i=0; i<=9; i++) {//we load everything in cache
			config->setGroup("Hard_scores");
			readName[i]=config->readEntry(varnames.sprintf("name%i",i),"");
			readSolved[i]=config->readNumEntry(varsolved.sprintf("solved%i",i),0);
			readRounds[i]=config->readNumEntry(varrounds.sprintf("rounds%i",i),0);
			readGuesses[i]=config->readNumEntry(varguesses.sprintf("guesses%i",i),0);
			config->sync();
		}

		int a;
		for (int i=9; i>=0; i--) {//...and now we check each score from lowest to highest
			if ((readSolved[i]<=solvedWords) && (readSolved[i-1]>solvedWords)) {
				config->writeEntry(varnames.sprintf("name%i",i), shareLoginName);
				config->writeEntry(varsolved.sprintf("solved%i",i),solvedWords);
				config->writeEntry(varrounds.sprintf("rounds%i",i),messups);
				config->writeEntry(varguesses.sprintf("guesses%i",i),tGuesses);
				a=i;
				config->sync();
			}
		}

		for (int x=a;  x<=9; x++) {//this will write the scores for a level lower...
			config->writeEntry(varnames.sprintf("name%i",x+1), readName[x]);
			config->writeEntry(varsolved.sprintf("solved%i",x+1),readSolved[x]);
			config->writeEntry(varrounds.sprintf("rounds%i",x+1),readRounds[x]);
			config->writeEntry(varguesses.sprintf("guesses%i",x+1),readGuesses[x]);
			config->sync();
		}
	}

}

void MainWindow::first_run() {
	config->setGroup("First_run");
	if (config->readBoolEntry("Run",true)==true) {
		config->sync();
		//KMessageBox::information(this,i18n("The player name has been set to that of the user account. The player name can be changed in Configure, Configuration."));
		for (int i=0; i<=9; i++) 	{
			config->setGroup("Easy_scores");
			config->writeEntry(varnames.sprintf("name%i",i),"Anonymous");
			config->writeEntry(varsolved.sprintf("solved%i",i),"0");
			config->writeEntry(varrounds.sprintf("rounds%i",i),"0");
			config->writeEntry(varguesses.sprintf("guesses%i",i),"0");
			config->sync();

			config->setGroup("Medium_scores");
			config->writeEntry(varnames.sprintf("name%i",i),"Anonymous");
			config->writeEntry(varsolved.sprintf("solved%i",i),"0");
			config->writeEntry(varrounds.sprintf("rounds%i",i),"0");
			config->writeEntry(varguesses.sprintf("guesses%i",i),"0");
			config->sync();

			config->setGroup("Hard_scores");
			config->writeEntry(varnames.sprintf("name%i",i),"Anonymous");
			config->writeEntry(varsolved.sprintf("solved%i",i),"0");
			config->writeEntry(varrounds.sprintf("rounds%i",i),"0");
			config->writeEntry(varguesses.sprintf("guesses%i",i),"0");
			config->sync();
		}
		config->setGroup("First_run");
		config->writeEntry("Run","false");
		config->sync();
	}

	struct passwd* pw;

	config->setGroup("Environment");
	shareLoginName=config->readEntry("GamerName","");
	config->sync();
	
	if (shareLoginName.isEmpty()) {
		pw = getpwuid(getuid());
		if (pw) {
			shareLoginName = pw->pw_gecos;
			int i = shareLoginName.find(',');
			if (i>0)
				shareLoginName.truncate(i);
		}
		config->setGroup("Environment");
		config->writeEntry("GamerName",shareLoginName);
		config->sync();
	} else 	{
		kdDebug() << "Name set to user, that has been read from configuration file..." << endl;
	}



	kdDebug() << "Name found: " << shareLoginName << endl;
}

void MainWindow::slot_changeLevel() {
	//a complete reset for other levels... [docs?]
	KMessageBox::information(this,i18n("Now playing another level"));
	messups=0;
	solvedWords=0;
	guesses=0;
	tGuesses=0;
	guessedText->setText("");

	//we have to lock it up for the other level...
	guessedText->setEnabled(false);
	txtGuess->setEnabled(false);
	btnTry->setEnabled(false);
	btnMess->setDefault(true);
}

void MainWindow::check_update() {
	config->setGroup("Version");
	if (config->readEntry("version","") !="1.0.0") {
		config->sync();
		for (int i=0; i<=9; i++) 	{
			config->setGroup("Easy_scores");
			config->writeEntry(varnames.sprintf("guesses%i",i),"0");
			config->sync();
	
			config->setGroup("Medium_scores");
			config->writeEntry(varnames.sprintf("guesses%i",i),"0");
			config->sync();

			config->setGroup("Hard_scores");
			config->writeEntry(varnames.sprintf("guesses%i",i),"0");
			config->sync();
		}
		config->setGroup("Version");
		config->writeEntry("version","1.0.0");
		config->sync();
	}
}

void MainWindow::loadPopupMenu() {
	mainMenu->insertItem(QPixmap(locate("data","kmessedwords/wrench_small.png")),i18n("&Configuration"), this, SLOT(showAppConfig()));
	mainMenu->insertItem(QPixmap(locate("data","kmessedwords/dict.png")),i18n("&Dictionary"), this, SLOT(slot_openBook()));
}

void MainWindow::showAppConfig() {
	cfg->show();
}

void MainWindow::closeEvent(QCloseEvent *){
	exit(0);
}

void MainWindow::winRefresh(){
	QPixmap bgPix;
	config->setGroup("Theme");
	themeName=config->readEntry("Name","default");
	if(config->readBoolEntry("Background",true)){
		bgPix=QPixmap(locate("data","kmessedwords/themes/"+themeName+"/kmessedbg.png"));
		setBackgroundPixmap(bgPix);
		mainScreen->setBackgroundOrigin( QLabel::ParentOrigin );
		mainScreen->setBackgroundPixmap(bgPix);
	} else 	{
		setBackgroundColor("#DCDCDC");
	}
	config->sync();

	config->setGroup("Theme");
	isThemeBtn=config->readBoolEntry("Buttons",false);
	config->sync();
	
	if(isThemeBtn) 	{
		btnClose->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btnbye.png")));
		btnHelp->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btnhelp.png")));
		btnConfig->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btnconf.png")));
		btnScore->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btnscore.png")));
		btnMess->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btnmess.png")));
		btnTry->setPixmap(QPixmap(locate("data","kmessedwords/themes/"+themeName+"/btntry.png")));
	} else 	{
		btnClose->setText(i18n("&Quit"));
		btnHelp->setText(i18n("&Help"));
		btnConfig->setText(i18n("Co&nfigure"));
		btnScore->setText(i18n("&Scores"));
		btnMess->setText(i18n("&Randomize"));
		btnTry->setText(i18n("&Try"));
	}
}

void MainWindow::theEnd(){
	config->setGroup("Environment");
	shareLoginName=config->readEntry("GamerName", "");
	config->sync();	

	solvedWords++;
	write_scores();
	justtext=i18n("Name: ") +  shareLoginName + "\n"+ i18n("Solved:") + justtext.sprintf("%i\n",  solvedWords)+ i18n ("Rounds:") + justtext.sprintf("%i\n" , messups);
	KMessageBox::information(this,justtext);
	close();
}

void MainWindow::theReply(){
	solvedWords++;
	guesses=0;
	guessedText->setText("");
	slot_messup();
}
