/***************************************************************************
                         kfrmain.cpp  -  description
                            -------------------
   begin                : Mon Dec  3 13:47:14 CET 2001
   copyright            : (C) 2001 by Christian Hubinger
   email                : e9806056@student.tuwien.ac.at
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
//QT Includes
#include <qpainter.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qbitmap.h>
#include <qrect.h>
#include <qwmatrix.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qhbox.h>
#include <qlcdnumber.h>
#include <qfont.h>
#include <qfontmetrics.h>
#include <qdrawutil.h>
#include <qlabel.h>
#include <qcheckbox.h>

//KDE Includes
#include <kfiledialog.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <kpushbutton.h>
#include <kpixmapeffect.h>
#include <kpixmap.h>
#include <kaboutapplication.h>
#include <kaboutkde.h>
#include <khelpmenu.h>
#include <kpopupmenu.h>
#include <kinputdialog.h>

//C++ Standard Includes
#include <stdlib.h>

//My Includes
#include "kfreerings.h"
#include "kfrmain.h"
#include "kfconfiguration.h"
#include "kfdialog.h"

KFRMain::KFRMain( QWidget *parent, const char *name ) : QWidget( parent, name ) {
	m_animationStep = -1;
	m_isCrushig = false;
	m_inGame = false;
	m_wasInGame = false;
	m_inTrainigGame = false;
	m_timer = new QTimer( this );
	m_game = KFGame();
	m_currLevel = 1;
	m_gameOver = false;
	m_highScore = new KFHighscore( this );
	QFont f( "Helvetica", 10, QFont::Bold );
	setFont( f );

	KStandardDirs stddir;
	bg_filename = stddir.findResource("data", "kfreerings/pics/" + Config().m_Image );
	kdDebug() << "Found Background at: " << bg_filename << endl;

	tri_mask_filename = stddir.findResource("data", "kfreerings/required_pics/tri_mask.png");
	tri_mask_180_filename = stddir.findResource("data", "kfreerings/required_pics/tri_mask_180.png");
	qu_mask_filename = stddir.findResource("data", "kfreerings/required_pics/qu_mask.png");
	qu_mask_60_filename = stddir.findResource("data", "kfreerings/required_pics/qu_mask_60.png");
	qu_mask_120_filename = stddir.findResource("data", "kfreerings/required_pics/qu_mask_120.png");
	mask_ring1_filename = stddir.findResource("data", "kfreerings/required_pics/mask_ring1.png");
	mask_ring2_filename = stddir.findResource("data", "kfreerings/required_pics/mask_ring2.png");
	mask_ring3_filename = stddir.findResource("data", "kfreerings/required_pics/mask_ring3.png");
	QBitmap reg1( mask_ring1_filename, "PNG" );
	m_regionRing1 = QRegion( reg1 );
	QBitmap reg2( mask_ring2_filename, "PNG" );
	m_regionRing2 = QRegion( reg2 );
	QBitmap reg3( mask_ring3_filename, "PNG" );
	m_regionRing3 = QRegion( reg3 );

	m_neededMoves = 0;
	bg.load( bg_filename );
	setBackgroundPixmap( bg );

	r1kfl = new KFButton( this, "kf" );
	r1kfl->setButtonStyle( KFButton::LEFT );
	r1kfl->setAngel( 0 );
	r1kfl->setGeometry( 210, 365, 70, 70 );
	connect( r1kfl, SIGNAL( clicked() ), this, SLOT( r1moveLeft() ) );

	r1kfr = new KFButton( this, "kf" );
	r1kfr->setButtonStyle( KFButton::RIGHT );
	r1kfr->setAngel( 0 );
	r1kfr->setGeometry( 280, 365, 70, 70 );
	connect( r1kfr, SIGNAL( clicked() ), this, SLOT( r1moveRight() ) );

	r2kfl = new KFButton( this, "kf" );
	r2kfl->setButtonStyle( KFButton::LEFT );
	r2kfl->setAngel( 0 );
	r2kfl->setGeometry( 450, 365, 70, 70 );

	connect( r2kfl, SIGNAL( clicked() ), this, SLOT( r2moveLeft() ) );

	r2kfr = new KFButton( this, "kf" );
	r2kfr->setButtonStyle( KFButton::RIGHT );
	r2kfr->setAngel( 0 );
	r2kfr->setGeometry( 520, 365, 70, 70 );

	connect( r2kfr, SIGNAL( clicked() ), this, SLOT( r2moveRight() ) );

	r3kfl = new KFButton( this, "kf" );
	r3kfl->setButtonStyle( KFButton::LEFT );
	r3kfl->setAngel( 0 );
	r3kfl->setGeometry( 330, 155, 70, 70 );

	connect( r3kfl, SIGNAL( clicked() ), this, SLOT( r3moveLeft() ) );

	r3kfr = new KFButton( this, "kf" );
	r3kfr->setButtonStyle( KFButton::RIGHT );
	r3kfr->setAngel( 0 );
	r3kfr->setGeometry( 400, 155, 70, 70 );
	connect( r3kfr, SIGNAL( clicked() ), this, SLOT( r3moveRight() ) );

// 	count = new QLCDNumber( 4, this, "lcd" );

// 	count->setGeometry( 690, 540, 100, 50 );

	connect( this, SIGNAL( reset() ), this, SLOT( resetCounter() ) );
	m_newGame = new KFButton( this, "m_newGame" );
	m_newGame->setButtonStyle( KFButton::TEXT );
	m_newGame->setFixedHeight( 30 );
	m_newGame->setText( i18n("Game") );
	m_newGame->setGeometry( 4, 4,fontMetrics().width( i18n("Game") ) + 10, 30 );
	m_newGame->repaint();

	m_settings = new KFButton( this,"m_settings");
	m_settings->setButtonStyle( KFButton::TEXT );
	m_settings->setFixedHeight( 30 );
	m_settings->setText( i18n("Settings") );
	m_settings->setGeometry( m_newGame->x() + m_newGame->width() , 4,fontMetrics().width( i18n("Settings") ) + 10, 30 );

	m_help = new KFButton( this,"m_help" );
	m_help->setButtonStyle( KFButton::TEXT );
	m_help->setFixedHeight( 30 );
	m_help->setText( i18n("Help") );
	m_help->setGeometry( m_settings->x() + m_settings->width(), 4,fontMetrics().width( i18n("Help") ) + 10, 30 );

	m_quitGame = new KFButton( this,"m_quitGame" );
	m_quitGame->setButtonStyle( KFButton::TEXT );
	m_quitGame->setFixedSize(fontMetrics().width( i18n("Quit") ) + 10, 30 );
	m_quitGame->setText( i18n("Quit") );
	m_quitGame->setGeometry( 800 - m_quitGame->width() - 4, 4,fontMetrics().width( i18n("Quit") ) + 10, 30 );

	m_helpMenu = new KHelpMenu( this, kapp->aboutData(), false );

	m_fileMenu = new KPopupMenu(0, "m_fileMenu");
	m_fileMenu->insertItem( KGlobal::iconLoader()->loadIcon("roll", KIcon::Small ) , i18n("&New Game"), this , SLOT( slotNewGame() ) );
	m_fileMenu-> insertSeparator();
	
	m_fileMenu->insertItem( KGlobal::iconLoader()->loadIcon("roll", KIcon::Small ) , i18n("&Start Training Game"), this , SLOT( slotNewTrainingGame() ) );
	m_fileMenu-> insertSeparator();
	
	m_fileMenu->insertItem( KGlobal::iconLoader()->loadIcon("wizard", KIcon::Small ), i18n("&Solve Game"), this , SLOT( slotSolveGame() ) );
	m_fileMenu-> insertSeparator();
	
	m_fileMenu->insertItem( KGlobal::iconLoader()->loadIcon("exit", KIcon::Small ), i18n("&Quit"), this , SLOT( slotQuitGame() ) );
	m_fileMenu->setFont( font() );
	m_fileMenu-> setPaletteForegroundColor( QColor( "darkGray") );

	m_settingsMenu  = new KPopupMenu(0, "m_settingsMenu");
	m_settingsMenu->insertItem( KGlobal::iconLoader()->loadIcon("thumbnail", KIcon::Small ) , i18n("&Change Image"), this , SLOT( slotSetImage() ) );
	m_settingsMenu-> insertSeparator();
	m_settingsMenu->insertItem( KGlobal::iconLoader()->loadIcon("apply", KIcon::Small ), i18n("&Set your Skill"), this , SLOT( slotSetLevel() ) );
	m_settingsMenu->insertItem( KGlobal::iconLoader()->loadIcon("apply", KIcon::Small ), i18n("Set &Training Level"), this , SLOT( slotSetTrainingsLevel() ) );
	
	m_settingsMenu->insertItem( i18n("Show/Hide &Highscores"), this , SLOT( slotToggleShowHighscores() ) );
	
	m_settingsMenu->setFont( font() );
	m_settingsMenu-> setPaletteForegroundColor( QColor( "darkGray") );
	
	
	m_highscoreLabel = new QLabel( this );
	m_highscoreLabel->setFixedWidth( 300 );
	m_highscoreLabel->setFixedHeight( 400 );
	m_highscoreLabel->move( 250, 100 );
	m_highscoreLabel->setFont( font() );
	m_highscoreLabel-> setPaletteForegroundColor( QColor( "lightGray") );
	m_highscoreLabel->setAlignment( AlignBottom | AlignCenter );
	m_highscoreLabel->show();
	
	connect( m_newGame, SIGNAL( clicked() ), this, SLOT( slotShowFileMenu() ) );
	connect( m_settings, SIGNAL( clicked() ), this, SLOT( slotShowSettingsMenu() ) );
	connect( m_help, SIGNAL( clicked() ), this, SLOT( slotShowHelpMenu() ) );
	connect( m_quitGame, SIGNAL( clicked() ), this, SLOT( slotQuitGame() ) );
	slotRefreshHighscroes();
	setImage( bg_filename );
	startUp = true;
}

KFRMain::~KFRMain() {
	delete m_helpMenu;
	delete m_fileMenu;
	delete m_settingsMenu;
}

void KFRMain::slotSetImage() {
	if ( m_inGame  || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::YESNO , i18n("<qt><center>Changing the image while playing a game will cancel the game!<br>Are you sure you want to change the image?</center></qt>") );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( setImage() ) );
		dialog->show();
	} else {
		setImage();
	}
}

void KFRMain::slotNewGame() {
	if ( m_inGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::YESNO , i18n("<qt><center>Are you sure you want to start a new Game?<br>The current game will be canceled!</center></qt>") );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotStartNewGame() ) );
		dialog->show();
	} else {
		slotStartNewGame();
	}
}

void KFRMain::slotNewTrainingGame() {
	if ( m_inTrainigGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::YESNO , i18n("<qt><center>Are you sure you want to start a new Game?<br>The current game will be canceled!</center></qt>") );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotStartTrainingGame() ) );
		dialog->show();
	} else {
		slotStartTrainingGame();
	}
}

void KFRMain::slotStartTrainingGame() {
	KFLevel* currLevel = m_game.getLevel();
	currLevel = 0;
	slotHideHighscores();
	slotFixImage();
	m_inTrainigGame=true;
	crushImage();
	m_inGame=false;
	m_gameOver = false;
	repaint();
}

void KFRMain::slotStartNewGame() {
	slotFixImage();
	m_currLevel = 1;
	m_game.startGame( Config().m_GameLevel );
	m_game.startLevel( m_currLevel, m_currLevel );
	m_gameOver = false;
	slotHideHighscores();
	crushImage();
	fadeRings( true );
	m_inGame=true;
	repaint();
}


void KFRMain::slotNextLevel() {
	m_currLevel++;
	m_game.startLevel( m_currLevel, m_currLevel );
	slotFixImage();
	crushImage();
	fadeRings( true );
	m_inGame=true;
	repaint();
}

void KFRMain::slotGameOver() {
	m_inGame=false;
	m_gameOver = true;
	slotFixImage();
	repaint();
	m_game.endGame();
	QPtrList<KFLevel>& levels = m_game.levelList();
	QPtrListIterator<KFLevel> it (levels);
	QString levelResult = "";
	while ( it.current() && ! it.atLast() ) {
		KFLevel* currLevel =  it.current();
		++it;
		levelResult += i18n("Level: %1 Score: %2<br>").arg( currLevel->getLevel() ).arg( currLevel->getScore() );
		
	}
	
	KFDialog *dialog = showKFDialog( KFDialog::INFORMATION , i18n("<qt><center><h2>Game Over!</h2>%1<h3>Your score: %2</h3></center></qt>").arg(levelResult).arg( m_game.gameScore() ) );
	slotRefreshHighscroes();
	connect( dialog, SIGNAL( sigAccepted() ), this, SLOT ( slotShowHighscores() ) );
	
	connect( dialog, SIGNAL( sigAccepted() ), this, SLOT ( checkForHighscore() ) );
	dialog->show();
}

void KFRMain::slotShowHighscores() {
	refreshHighscores();
	m_highscoreLabel->show();
	refreshHighscores();
}

void KFRMain::slotHideHighscores() {
	m_highscoreLabel->hide();
}

void KFRMain::slotToggleShowHighscores(){
	if ( m_inGame || m_inTrainigGame )
		return;
	
	if ( m_highscoreLabel->isShown() ) {
		m_highscoreLabel->hide();
	} else {
		m_highscoreLabel->show();
	}
}

void KFRMain::slotRefreshHighscroes() {
	refreshHighscores();
}

void KFRMain::refreshHighscores() {
	kdDebug() << "KFRMain::refreshHighscores()" << endl;
	m_highscoreLabel->clear();
	QString skill;
	switch ( Config().m_GameLevel ) {
		case 0:
		skill =  "Child";
		break;
		case 1:
		skill =  "Beginner";
		break;
		case 2:
		skill =  "Advanced";
		break;
		case 3:
		skill =  "Expert";
		break;
	}	
	
	QString text = QString("<qt><center><h2>Highscores %1</h2>").arg(skill);
	text += "<table width=\"250\" border=\"0\">";
	text += "<tr><th>Player</th><th>Level</th><th>Score</th></tr>";
	
	QPtrList<QStringList>* highscores = m_highScore->getScores();
	int numScores = highscores->count();
	kdDebug() << "Found Num Highscores: " << numScores << endl;
	QPtrListIterator<QStringList> it ( *highscores );
	while ( it.current() ) {
		QStringList *list = *it;
		++it;
		text += "<tr><td>"+ *list->at(0) +"</td><td>"+ *list->at(1)+"</td><td align=\"right\">" +*list->at(2)+ "</td></tr>";
	}
	if ( numScores < 10 ) {
		for ( int i = 10 - ( 10 - numScores ) ; i  < 11; i++ ) {
			text += "<tr><td align=\"center\">-</td><td align=\"center\">-</td><td align=\"center\">-</td></tr>";
		}
	
	} 
	text += "</table>";
	text += "</center></qt>";
	m_highscoreLabel->setText( text );
}

void KFRMain::slotSolveGame() {
	if ( m_inGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::YESNO , i18n("<qt><center>Are you sure you want to cancel the current game and sort the image?</center></qt>") );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotFixImage() ) );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotShowHighscores() ) );
		dialog->show();
	} else {
		slotFixImage();
	}
}

void KFRMain::slotHelp() {
	kapp->invokeHelp();
}

void KFRMain::slotAbout() {
	KAboutApplication *a = new KAboutApplication( this, "a", true );
	a->exec();
}

void KFRMain::slotAboutKDE() {
	KAboutKDE *a = new KAboutKDE( this, "a", true );
	a->exec();
}

void KFRMain::slotShowHelpMenu() {
	KPopupMenu * men = m_helpMenu->menu();
	men->move( parentWidget()->x() +m_help->x() , parentWidget()->y() + 34 );
	men->show();
}

void KFRMain::slotShowFileMenu() {
	m_fileMenu->move( parentWidget()->x() +m_newGame->x() , parentWidget()->y() + 34 );
	m_fileMenu->show();
}

void KFRMain::slotShowSettingsMenu() {
	m_settingsMenu->move( parentWidget()->x() +m_settings->x() , parentWidget()->y() + 34 );
	m_settingsMenu->show();
}


void KFRMain::slotQuitGame() {
	if ( m_inGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::YESNO , i18n("<qt><center>Are you sure you want to quit?</center></qt>") );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotQuit() ) );
		dialog->show();
	} else {
		slotQuit();
	}
	
}

void KFRMain::slotQuit() {
	kapp->quit();
}

void KFRMain::slotSetTrainingsLevel() {
	if ( m_inGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::INFORMATION , i18n("<qt><center>Sorry, You can not change the level while plaing a game!</center></qt>") );
		dialog->show();
	} else {
		slotHideHighscores();
		KFDialog *dialog = showKFDialog( KFDialog::SETTRAININGSLEVEL , i18n("<qt><center>Set the numer of moves used to scrabble the image.</center></qt>") );
		dialog->show();
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotShowHighscores() ) );
		connect( dialog, SIGNAL( sigRejected() ) , this, SLOT( slotShowHighscores() ) );
	}
}

void KFRMain::slotSetLevel(){ 
	if ( m_inGame || m_inTrainigGame ) {
		KFDialog *dialog = showKFDialog( KFDialog::INFORMATION , i18n("<qt><center>Sorry, You can not change the level while plaing a game!</center></qt>") );
		dialog->show();
	} else {
		slotHideHighscores();
		KFDialog *dialog = showKFDialog( KFDialog::SETLEVEL , i18n("<qt><center>Choose your skill</center></qt>") );
		dialog->show();
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotShowHighscores() ) );
		connect( dialog, SIGNAL( sigRejected() ) , this, SLOT( slotShowHighscores() ) );
	}
}


void KFRMain::finished() {
	if ( m_inGame ) {
		KFLevel* currLevel = m_game.endLevel( m_neededMoves );
		KFDialog *dialog = showKFDialog( KFDialog::INFORMATION , i18n("<qt><center>Congratulations you have done it!<br> You needed %1 moves for fixing the picture scrabbled with %2 moves.<br>Max. Points: %3<br>Points: %4<br>Bonus: %5<br>Sum: %6</center></qt>").arg( m_neededMoves ).arg( currLevel->getMoves() ).arg( currLevel->getMaxPoints() ).arg( currLevel->getPoints() ).arg( currLevel->getBonus() ).arg( currLevel->getScore() ) );
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotNextLevel() ) );
		m_inGame = false;
		m_inTrainigGame = false;
		dialog->show();
	} else {
		KFDialog *dialog = showKFDialog( KFDialog::INFORMATION , i18n("<qt><center>Congratulations you have done it!<br> You needed %1 moves.</center></qt>").arg(m_neededMoves) );
		
		connect( dialog, SIGNAL( sigAccepted() ) , this, SLOT( slotShowHighscores() ) );
		dialog->show();
		m_inGame = false;
		m_inTrainigGame = false;
	}
	emit reset();
	repaint();
}

KFDialog* KFRMain::showKFDialog( int dialogType, const QString& msg ) {
	KFDialog *dialog = new KFDialog( this, "diag", dialogType, msg );
	dialog->move( this->x() +  this->width()/2 - dialog->width()/2 , this->y() +  this->height()/2 - dialog->height()/2 );
	
	dialog->move( parentWidget()->x() + ( width()/2 - dialog->width()/2 ), parentWidget()->y() + ( height()/2 - dialog->height()/2 ));
	
	QImage base ( 800, 600, 32 );
	base = bg.convertToImage();
	
	QImage header( base.copy(  this->x() +  this->width()/2 - dialog->width()/2 , this->y() +  this->height()/2 - dialog->height()/2, dialog->width(), dialog->height() ) );
	
	QPixmap pix;
	pix.convertFromImage( header, AutoColor );
	KPixmap p = KPixmap( pix );
	pix = KPixmapEffect::intensity( p , -0.7f );
	dialog->show();
	dialog->setPaletteBackgroundPixmap( pix );
	dialog->setFont( font() );
	dialog->setPaletteForegroundColor( QColor( "lightGray") );
	
	//dialog->move( parentWidget()->x() + ( width()/2 - dialog->width()/2 ), parentWidget()->y() + ( height()/2 - dialog->height()/2 ));
	
	return dialog;
}

void KFRMain::setImage( QString file /* = QString::null */ ) {
	m_inGame = false;
	KStandardDirs stddir;
	QString defaultImage = "kfreerings/pics/" + Config().m_Image;
	const QString dir  = stddir.findResource("data", defaultImage );
	const QString filter = "*.jpg";
	if ( file.isNull() ) {
		KURL url = KFileDialog::getOpenURL(  dir, "*.jpg *.png | PNG & JPEG Pictures ", this );
		file = url.path();
		kdDebug() << "File Name: " << url.path() << endl;
		if ( ! url.path().isEmpty() ) {
			Config().m_Image = url.fileName();
			Config().write();
		}
	}
	if ( ! file.isNull() ) {
		bg_filename = file;
		QImage img( bg_filename );
		img = img.smoothScale( 800,600 );
		bg.convertFromImage( img,AutoColor );
		QImage base ( 800, 600, 32 );
		QPixmap pix;
		base = bg.convertToImage();
		QImage header( base.copy(  0, 0, bg.width(), 100 ) );
		pix.convertFromImage( header, AutoColor );
		KPixmap kp_header =  KPixmap( pix );
		const QColor& fadeto = QColor("black");
		kp_header = KPixmapEffect::blend( kp_header, 0.0 , fadeto,  KPixmapEffect::VerticalGradient, true );
		QPainter p( &bg );
		p.drawPixmap(0,0, kp_header );
		QImage leftCorner( base.copy(  0, 500, bg.width(), 100 ) );
		QPixmap pix2;
		pix2.convertFromImage( leftCorner, AutoColor );
		KPixmap kp_leftCorner =  KPixmap( pix2 );
		kp_leftCorner = KPixmapEffect::blend( kp_leftCorner, 0.0 , fadeto,  KPixmapEffect::VerticalGradient, false );
		p.drawPixmap(0,500, kp_leftCorner );





		const QColorGroup& cg =QColorGroup( colorGroup() );
		qDrawShadeRect( &p,0,0,bg.width(), bg.height(), cg , false, 1,2,0 );
		bg_unchanged = bg;
		this->setBackgroundPixmap( bg );

		slotFixImage();

		// Set LCD Background
// 		QImage m( base.copy(  count->x(), count->y() ,
// 		                      count->width(), count->height() ) );

// 		pix.convertFromImage( m, AutoColor );
// 		count->setPaletteBackgroundPixmap( pix );

		// set Menu
		m_newGame->setBackground( &bg_unchanged, m_newGame->x(), m_newGame->y() );
		m_settings->setBackground( &bg_unchanged, m_settings->x(), m_settings->y() );
		m_quitGame->setBackground( &bg_unchanged, m_quitGame->x(), m_quitGame->y() );
		m_help->setBackground( &bg_unchanged, m_help->x(), m_help->y() );

		// set Button Background
		r1kfl->setBackground( &bg_unchanged, r1kfl->x(), r1kfl->y() );
		r1kfr->setBackground( &bg_unchanged, r1kfr->x(), r1kfr->y() );
		r2kfl->setBackground( &bg_unchanged, r2kfl->x(), r2kfl->y() );
		r2kfr->setBackground( &bg_unchanged, r2kfr->x(), r2kfr->y() );
		r3kfl->setBackground( &bg_unchanged, r3kfl->x(), r3kfl->y() );
		r3kfr->setBackground( &bg_unchanged, r3kfr->x(), r3kfr->y() );
		
		base = bg.convertToImage();
		QImage n( base.copy(  m_highscoreLabel->x(), m_highscoreLabel->y() ,
		                      m_highscoreLabel->width(), m_highscoreLabel->height() ) );
		QPixmap pix3;
		pix3.convertFromImage( n, AutoColor );
		KPixmap kp_hs =  KPixmap( pix3 );
		kp_hs = KPixmapEffect::intensity( kp_hs , -0.7f );
		m_highscoreLabel->setPaletteBackgroundPixmap( kp_hs );
	}
}

void KFRMain::incrementCount() {
	if ( m_isCrushig )
		return;
	m_neededMoves++;
	repaint( QRegion( 660, 560, 800, 600  ) );

// 	count->display( m_neededMoves );
}

void KFRMain::resetCounter() {
	m_neededMoves = 0;
// 	count->display( 0 );
}

void KFRMain::r1moveLeft() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 1 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 1 ];

	for ( int i = 0; i < 10; i++ ) {
		int j = i + 2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang [ i ] = ( ang[ j ] - 60 );

	}

	pix[ 10 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang [ 10 ] = ( tang1 - 60 );
	//******************************
	pix[ 11 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang [ 11 ] = ( tang2 - 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing1 );
	}
	if ( testFinished() ) {
		finished();
	}
}

void KFRMain::r1moveRight() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 11 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 11 ];
	//******************************
	pix[ 0 ] = pix[ 10 ];
	if ( ang[ 10 ] == 360 || ang[ 10 ] == -360 )
		ang[ 10 ] = 0;
	ang [ 0 ] = ( ang[ 10 ] + 60 );

	for ( int i = 11; i > 2; i-- ) {
		int j = i -2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang[ i ] = ( ang[ j ] + 60 );
	}

	pix[ 2 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang[ 2 ] = ( tang1 + 60 );
	//******************************
	pix[ 1 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang[ 1 ] = ( tang2 + 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing1 );
	}
	if ( testFinished() ) {
		finished();
	}
}

void KFRMain::r2moveLeft() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 20 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 20 ];
	//******************************
	pix[ 0 ] = pix[ 19 ];
	if ( ang[ 19 ] == 360 || ang[ 19 ] == -360 )
		ang[ 19 ] = 0;
	ang[ 0 ] = ( ang[ 19 ] - 60 );
	//******************************
	pix[ 20 ] = pix[ 21 ];
	if ( ang[ 21 ] == 360 || ang[ 21 ] == -360 )
		ang[ 21 ] = 0;
	ang[ 20 ] = ( ang[ 21 ] - 60 );
	//******************************
	pix[ 19 ] = pix[ 22 ];
	if ( ang[ 22 ] == 360 || ang[ 22 ] == -360 )
		ang[ 22 ] = 0;
	ang[ 19 ] = ( ang[ 22 ] - 60 );
	//******************************

	for ( int i = 21; i < 26; i++ ) {
		int j = i +2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang[ i ] = ( ang[ j ] - 60 );
	}

	//******************************
	pix[ 26 ] = pix[ 2 ];
	if ( ang[ 2 ] == 360 || ang[ 2 ] == -360 )
		ang[ 2 ] = 0;
	ang[ 26 ] = ( ang[ 2 ] - 60 );
	//******************************
	pix[ 27 ] = pix[ 1 ];
	if ( ang[ 1 ] == 360 || ang[ 1 ] == -360 )
		ang[ 1 ] = 0;
	ang[ 27 ] = ( ang[ 1 ] - 60 );
	//******************************
	pix[ 2 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang[ 2 ] = ( tang1 - 60 );
	//******************************
	pix[ 1 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang[ 1 ] = ( tang2 - 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing2 );
	}
	if ( testFinished() ) {
		finished();
	}
}

void KFRMain::r2moveRight() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 1 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 1 ];
	//******************************
	pix[ 0 ] = pix[ 2 ];
	if ( ang[ 2 ] == 360 || ang[ 2 ] == -360 )
		ang[ 2 ] = 0;
	ang [ 0 ] = ( ang[ 2 ] + 60 );
	//******************************
	pix[ 1 ] = pix[ 27 ];
	if ( ang[ 27 ] == 360 || ang[ 27 ] == -360 )
		ang[ 27 ] = 0;
	ang [ 1 ] = ( ang[ 27 ] + 60 );
	//******************************
	pix[ 2 ] = pix[ 26 ];
	if ( ang[ 26 ] == 360 || ang[ 26 ] == -360 )
		ang[ 26 ] = 0;
	ang [ 2 ] = ( ang[ 26 ] + 60 );

	for ( int i = 27; i > 22; i-- ) {
		int j = i -2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang[ i ] = ( ang[ j ] + 60 );
	}

	//******************************
	pix[ 22 ] = pix[ 19 ];
	if ( ang[ 19 ] == 360 || ang[ 19 ] == -360 )
		ang[ 19 ] = 0;
	ang [ 22 ] = ( ang[ 19 ] + 60 );
	//******************************
	pix[ 21 ] = pix[ 20 ];
	if ( ang[ 20 ] == 360 || ang[ 20 ] == -360 )
		ang[ 20 ] = 0;
	ang [ 21 ] = ( ang[ 20 ] + 60 );
	//******************************
	pix[ 19 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang [ 19 ] = ( tang1 + 60 );
	//******************************
	pix[ 20 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang [ 20 ] = ( tang2 + 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing2 );
	}
	if ( testFinished() ) {
		finished();
	}
}

void KFRMain::r3moveLeft() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 11 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 11 ];

	//******************************
	pix[ 0 ] = pix[ 10 ];
	if ( ang[ 10 ] == 360 || ang[ 10 ] == -360 )
		ang[ 10 ] = 0;
	ang [ 0 ] = ( ang[ 10 ] - 60 );
	//******************************
	pix[ 11 ] = pix[ 12 ];
	if ( ang[ 12 ] == 360 || ang[ 12 ] == -360 )
		ang[ 12 ] = 0;
	ang [ 11 ] = ( ang[ 12 ] - 60 );
	//******************************
	pix[ 10 ] = pix[ 13 ];
	if ( ang[ 13 ] == 360 || ang[ 13 ] == -360 )
		ang[ 13 ] = 0;
	ang [ 10 ] = ( ang[ 13 ] - 60 );

	for ( int i = 12; i < 19; i++ ) {
		int j = i +2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang[ i ] = ( ang[ j ] - 60 );
	}


	//******************************
	pix[ 19 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang [ 19 ] = ( tang1 - 60 );
	//******************************
	pix[ 20 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang [ 20 ] = ( tang2 - 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing3 );
	}
	if ( testFinished() ) {
		finished();
	}

}

void KFRMain::r3moveRight() {
	incrementCount();
	QPixmap * tpic1;
	QPixmap* tpic2;
	int tang1, tang2;
	tpic1 = pix[ 0 ];
	tpic2 = pix[ 20 ];
	tang1 = ang[ 0 ];
	tang2 = ang[ 20 ];

	//******************************
	pix[ 0 ] = pix[ 19 ];
	if ( ang[ 19 ] == 360 || ang[ 19 ] == -360 )
		ang[ 19 ] = 0;
	ang [ 0 ] = ( ang[ 19 ] + 60 );

	for ( int i = 20; i > 13; i-- ) {
		int j = i -2;
		pix[ i ] = pix[ j ];
		if ( ang[ j ] == 360 || ang[ j ] == -360 )
			ang[ j ] = 0;
		ang[ i ] = ( ang[ j ] + 60 );
	}

	//******************************
	pix[ 13 ] = pix[ 10 ];
	if ( ang[ 10 ] == 360 || ang[ 10 ] == -360 )
		ang[ 10 ] = 0;
	ang [ 13 ] = ( ang[ 10 ] + 60 );
	//******************************
	pix[ 12 ] = pix[ 11 ];
	if ( ang[ 11 ] == 360 || ang[ 11 ] == -360 )
		ang[ 11 ] = 0;
	ang [ 12 ] = ( ang[ 11 ] + 60 );
	//******************************
	pix[ 10 ] = tpic1;
	if ( tang1 == 360 || tang1 == -360 )
		tang1 = 0;
	ang [ 10 ] = ( tang1 + 60 );
	//******************************
	pix[ 11 ] = tpic2;
	if ( tang2 == 360 || tang2 == -360 )
		tang2 = 0;
	ang [ 11 ] = ( tang2 + 60 );
	//******************************
	if ( Repaint ) {
		repaint( m_regionRing3 );
	}
	if ( testFinished() ) {
		finished();
	}
}

void KFRMain::slotFixImage() {
	m_inGame = false;
	m_inTrainigGame = false;
	Repaint = false;
	QImage base ( 800,600,32 );
	base = bg_unchanged.convertToImage();

	//load bitmap-masks for the pieces of the puzzle
	QBitmap tri_mask ( tri_mask_filename, "PNG" );
	QBitmap tri_mask_180 ( tri_mask_180_filename, "PNG" );
	QBitmap qu_mask ( qu_mask_filename, "PNG" );
	QBitmap qu_mask_60 ( qu_mask_60_filename, "PNG" );
	QBitmap qu_mask_120 ( qu_mask_120_filename, "PNG" );
	//**********************************************
	//settup puzzle pieces from
	QImage m( base.copy( 362, 294, 76, 90 ) );
	//	m.invertPixels(false);
	mid.convertFromImage( m, AutoColor );
	mid.setMask( tri_mask );
	//*************************************
	QImage mu( base.copy( 340, 354, 120, 113 ) );
	// 	mu.invertPixels(false);
	midu.convertFromImage( mu, AutoColor );
	midu.setMask( qu_mask );
	//*************************************
	QImage ml( base.copy( 280, 250, 120, 113 ) );
	//	ml.invertPixels(false);
	midl.convertFromImage( ml, AutoColor );
	midl.setMask( qu_mask_120 );
	//*************************************
	QImage mr( base.copy( 400, 250, 120, 113 ) );
	//  mr.invertPixels(false);
	midr.convertFromImage( mr, AutoColor );
	midr.setMask( qu_mask_60 );
	//*************************************
	QImage r1t1( base.copy( 363, 435, 76, 90 ) );
	//	r1t1.invertPixels(false);
	r1tr1.convertFromImage( r1t1, AutoColor );
	r1tr1.setMask( tri_mask_180 );
	//*************************************
	QImage r1q1( base.copy( 280, 457, 120, 113 ) );
	// 	r1q1.invertPixels(false);
	r1qu1.convertFromImage( r1q1, AutoColor );
	r1qu1.setMask( qu_mask_60 );
	//*************************************
	QImage r1t2( base.copy( 243, 502, 76, 90 ) );
	// 	r1t2.invertPixels(false);
	r1tr2.convertFromImage( r1t2, AutoColor );
	r1tr2.setMask( tri_mask );
	//*************************************
	QImage r1q2( base.copy( 160, 457, 120, 113 ) );
	// 	r1q2.invertPixels(false);
	r1qu2.convertFromImage( r1q2, AutoColor );
	r1qu2.setMask( qu_mask_120 );
	//*************************************
	QImage r1t3( base.copy( 123, 435, 76, 90 ) );
	//	r1t3.invertPixels(false);
	r1tr3.convertFromImage( r1t3, AutoColor );
	r1tr3.setMask( tri_mask_180 );
	//*************************************
	QImage r1q3( base.copy( 100, 354, 120, 113 ) );
	// 	r1q3.invertPixels(false);
	r1qu3.convertFromImage( r1q3, AutoColor );
	r1qu3.setMask( qu_mask );
	//*************************************
	QImage r1t4( base.copy( 124, 294, 76, 90 ) );
	//	r1t4.invertPixels(false);
	r1tr4.convertFromImage( r1t4, AutoColor );
	r1tr4.setMask( tri_mask );
	//*************************************
	QImage r1q4( base.copy( 160, 250, 120, 113 ) );
	// 	r1q4.invertPixels(false);
	r1qu4.convertFromImage( r1q4, AutoColor );
	r1qu4.setMask( qu_mask_60 );
	//*************************************
	QImage r2t1( base.copy( 483, 227, 76, 90 ) );
	// 	r2t1.invertPixels(false);
	r2tr1.convertFromImage( r2t1, AutoColor );
	r2tr1.setMask( tri_mask_180 );
	//*************************************
	QImage r2q1( base.copy( 520, 250, 120, 113 ) );
	//	r2q1.invertPixels(false);
	r2qu1.convertFromImage( r2q1, AutoColor );
	r2qu1.setMask( qu_mask_120 );
	//*************************************
	QImage r2t2( base.copy( 602, 295, 76, 90 ) );
	// 	r2t2.invertPixels(false);
	r2tr2.convertFromImage( r2t2, AutoColor );
	r2tr2.setMask( tri_mask );
	//*************************************
	QImage r2q2( base.copy( 580, 354, 120, 113 ) );
	// 	r2q2.invertPixels(false);
	r2qu2.convertFromImage( r2q2, AutoColor );
	r2qu2.setMask( qu_mask );
	//*************************************
	QImage r2t3( base.copy( 602, 431, 76, 90 ) );
	// 	r2t3.invertPixels(false);
	r2tr3.convertFromImage( r2t3, AutoColor );
	r2tr3.setMask( tri_mask_180 );
	//*************************************
	QImage r2q3( base.copy( 520, 457, 120, 113 ) );
	// 	r2q3.invertPixels(false);
	r2qu3.convertFromImage( r2q3, AutoColor );
	r2qu3.setMask( qu_mask_60 );
	//*************************************
	QImage r2t4( base.copy( 483, 502, 76, 90 ) );
	// 	r2t4.invertPixels(false);
	r2tr4.convertFromImage( r2t4, AutoColor );
	r2tr4.setMask( tri_mask );
	//*************************************
	QImage r2q4( base.copy( 400, 457, 120, 113 ) );
	// 	r2q4.invertPixels(false);
	r2qu4.convertFromImage( r2q4, AutoColor );
	r2qu4.setMask( qu_mask_120 );
	//*************************************
	QImage r3t1( base.copy( 242, 227, 76, 90 ) );
	//	r3t1.invertPixels(false);
	r3tr1.convertFromImage( r3t1, AutoColor );
	r3tr1.setMask( tri_mask_180 );
	//*************************************
	QImage r3q1( base.copy( 220, 147, 120, 113 ) );
	// 	r3q1.invertPixels(false);
	r3qu1.convertFromImage( r3q1, AutoColor );
	r3qu1.setMask( qu_mask );
	//*************************************
	QImage r3t2( base.copy( 242, 87, 76, 90 ) );
	// 	r3t2.invertPixels(false);
	r3tr2.convertFromImage( r3t2, AutoColor );
	r3tr2.setMask( tri_mask );
	//*************************************
	QImage r3q2( base.copy( 280, 42, 120, 113 ) );
	// 	r3q2.invertPixels(false);
	r3qu2.convertFromImage( r3q2, AutoColor );
	r3qu2.setMask( qu_mask_60 );
	//*************************************
	QImage r3t3( base.copy( 363, 20, 76, 90 ) );
	// 	r3t3.invertPixels(false);
	r3tr3.convertFromImage( r3t3, AutoColor );
	r3tr3.setMask( tri_mask_180 );
	//*************************************
	QImage r3q3( base.copy( 400, 42, 120, 113 ) );
	// 	r3q3.invertPixels(false);
	r3qu3.convertFromImage( r3q3, AutoColor );
	r3qu3.setMask( qu_mask_120 );
	//*************************************
	QImage r3t4( base.copy( 483, 87, 76, 90 ) );
	// 	r3t4.invertPixels(false);
	r3tr4.convertFromImage( r3t4, AutoColor );
	r3tr4.setMask( tri_mask );
	//*************************************
	QImage r3q4( base.copy( 460, 147, 120, 113 ) );
	// 	r3q4.invertPixels(false);
	r3qu4.convertFromImage( r3q4, AutoColor );
	r3qu4.setMask( qu_mask );
	//*************************************
	
	//Setting middlepoints of fields
	pm_t.setX( 400 );
	pm_t.setY( 339 );
	//**************
	pm_qu.setX( 400 );
	pm_qu.setY( 410 );
	//**************
	pm_ql.setX( 340 );
	pm_ql.setY( 306 );
	//**************
	pm_qr.setX( 460 );
	pm_qr.setY( 306 );
	//ring-left
	pr1_t1.setX( 401 );
	pr1_t1.setY( 480 );
	//**************
	pr1_q1.setX( 340 );
	pr1_q1.setY( 513 );
	//**************
	pr1_t2.setX( 280 );
	pr1_t2.setY( 547 );
	//**************
	pr1_q2.setX( 220 );
	pr1_q2.setY( 513 );
	//**************
	pr1_t3.setX( 160 );
	pr1_t3.setY( 480 );
	//**************
	pr1_q3.setX( 160 );
	pr1_q3.setY( 410 );
	//**************
	pr1_t4.setX( 162 );
	pr1_t4.setY( 339 );
	//**************
	pr1_q4.setX( 220 );
	pr1_q4.setY( 306 );

	//ring right
	pr2_t1.setX( 521 );
	pr2_t1.setY( 272 );
	//**************
	pr2_q1.setX( 580 );
	pr2_q1.setY( 306 );
	//**************
	pr2_t2.setX( 640 );
	pr2_t2.setY( 340 );
	//**************
	pr2_q2.setX( 640 );
	pr2_q2.setY( 410 );
	//**************
	pr2_t3.setX( 640 );
	pr2_t3.setY( 476 );
	//**************
	pr2_q3.setX( 580 );
	pr2_q3.setY( 513 );
	//**************
	pr2_t4.setX( 521 );
	pr2_t4.setY( 547 );
	//**************
	pr2_q4.setX( 460 );
	pr2_q4.setY( 513 );
	//**************


	//ring top
	pr3_t1.setX( 280 );
	pr3_t1.setY( 272 );
	//**************
	pr3_q1.setX( 280 );
	pr3_q1.setY( 203 );
	//**************
	pr3_t2.setX( 280 );
	pr3_t2.setY( 132 );
	//**************
	pr3_q2.setX( 340 );
	pr3_q2.setY( 98 );
	//**************
	pr3_t3.setX( 400 );
	pr3_t3.setY( 65 );
	//**************
	pr3_q3.setX( 460 );
	pr3_q3.setY( 98 );
	//**************
	pr3_t4.setX( 521 );
	pr3_t4.setY( 132 );
	//**************
	pr3_q4.setX( 520 );
	pr3_q4.setY( 203 );
	//**************


	//pos QPoint[] stores the possible possisions
	pos[ 0 ] = &pm_t;
	pos[ 1 ] = &pm_qu;
	pos[ 2 ] = &pr1_t1;
	pos[ 3 ] = &pr1_q1;
	pos[ 4 ] = &pr1_t2;
	pos[ 5 ] = &pr1_q2;
	pos[ 6 ] = &pr1_t3;
	pos[ 7 ] = &pr1_q3;
	pos[ 8 ] = &pr1_t4;
	pos[ 9 ] = &pr1_q4;
	pos[ 10 ] = &pr3_t1;
	pos[ 11 ] = &pm_ql;
	pos[ 12 ] = &pr3_q1;
	pos[ 13 ] = &pr3_t2;
	pos[ 14 ] = &pr3_q2;
	pos[ 15 ] = &pr3_t3;
	pos[ 16 ] = &pr3_q3;
	pos[ 17 ] = &pr3_t4;
	pos[ 18 ] = &pr3_q4;
	pos[ 19 ] = &pr2_t1;
	pos[ 20 ] = &pm_qr;
	pos[ 21 ] = &pr2_q1;
	pos[ 22 ] = &pr2_t2;
	pos[ 23 ] = &pr2_q2;
	pos[ 24 ] = &pr2_t3;
	pos[ 25 ] = &pr2_q3;
	pos[ 26 ] = &pr2_t4;
	pos[ 27 ] = &pr2_q4;

	// stre for finished check
	pos_orig[ 0 ] = &pm_t;
	pos_orig[ 1 ] = &pm_qu;
	pos_orig[ 2 ] = &pr1_t1;
	pos_orig[ 3 ] = &pr1_q1;
	pos_orig[ 4 ] = &pr1_t2;
	pos_orig[ 5 ] = &pr1_q2;
	pos_orig[ 6 ] = &pr1_t3;
	pos_orig[ 7 ] = &pr1_q3;
	pos_orig[ 8 ] = &pr1_t4;
	pos_orig[ 9 ] = &pr1_q4;
	pos_orig[ 10 ] = &pr3_t1;
	pos_orig[ 11 ] = &pm_ql;
	pos_orig[ 12 ] = &pr3_q1;
	pos_orig[ 13 ] = &pr3_t2;
	pos_orig[ 14 ] = &pr3_q2;
	pos_orig[ 15 ] = &pr3_t3;
	pos_orig[ 16 ] = &pr3_q3;
	pos_orig[ 17 ] = &pr3_t4;
	pos_orig[ 18 ] = &pr3_q4;
	pos_orig[ 19 ] = &pr2_t1;
	pos_orig[ 20 ] = &pm_qr;
	pos_orig[ 21 ] = &pr2_q1;
	pos_orig[ 22 ] = &pr2_t2;
	pos_orig[ 23 ] = &pr2_q2;
	pos_orig[ 24 ] = &pr2_t3;
	pos_orig[ 25 ] = &pr2_q3;
	pos_orig[ 26 ] = &pr2_t4;
	pos_orig[ 27 ] = &pr2_q4;




	//QPixmap* [] pix stores the pix in startorder
	pix[ 0 ] = &mid;
	pix[ 1 ] = &midu;
	pix[ 2 ] = &r1tr1;
	pix[ 3 ] = &r1qu1;
	pix[ 4 ] = &r1tr2;
	pix[ 5 ] = &r1qu2;
	pix[ 6 ] = &r1tr3;
	pix[ 7 ] = &r1qu3;
	pix[ 8 ] = &r1tr4;
	pix[ 9 ] = &r1qu4;
	pix[ 10 ] = &r3tr1;
	pix[ 11 ] = &midl;
	pix[ 12 ] = &r3qu1;
	pix[ 13 ] = &r3tr2;
	pix[ 14 ] = &r3qu2;
	pix[ 15 ] = &r3tr3;
	pix[ 16 ] = &r3qu3;
	pix[ 17 ] = &r3tr4;
	pix[ 18 ] = &r3qu4;
	pix[ 19 ] = &r2tr1;
	pix[ 20 ] = &midr;
	pix[ 21 ] = &r2qu1;
	pix[ 22 ] = &r2tr2;
	pix[ 23 ] = &r2qu2;
	pix[ 24 ] = &r2tr3;
	pix[ 25 ] = &r2qu3;
	pix[ 26 ] = &r2tr4;
	pix[ 27 ] = &r2qu4;

	//QPixmap* [] pix stores the pix for finshed check
	pix_orig[ 0 ] = &mid;
	pix_orig[ 1 ] = &midu;
	pix_orig[ 2 ] = &r1tr1;
	pix_orig[ 3 ] = &r1qu1;
	pix_orig[ 4 ] = &r1tr2;
	pix_orig[ 5 ] = &r1qu2;
	pix_orig[ 6 ] = &r1tr3;
	pix_orig[ 7 ] = &r1qu3;
	pix_orig[ 8 ] = &r1tr4;
	pix_orig[ 9 ] = &r1qu4;
	pix_orig[ 10 ] = &r3tr1;
	pix_orig[ 11 ] = &midl;
	pix_orig[ 12 ] = &r3qu1;
	pix_orig[ 13 ] = &r3tr2;
	pix_orig[ 14 ] = &r3qu2;
	pix_orig[ 15 ] = &r3tr3;
	pix_orig[ 16 ] = &r3qu3;
	pix_orig[ 17 ] = &r3tr4;
	pix_orig[ 18 ] = &r3qu4;
	pix_orig[ 19 ] = &r2tr1;
	pix_orig[ 20 ] = &midr;
	pix_orig[ 21 ] = &r2qu1;
	pix_orig[ 22 ] = &r2tr2;
	pix_orig[ 23 ] = &r2qu2;
	pix_orig[ 24 ] = &r2tr3;
	pix_orig[ 25 ] = &r2qu3;
	pix_orig[ 26 ] = &r2tr4;
	pix_orig[ 27 ] = &r2qu4;
	/*for each pixmap we define an angel
	possible values +-60 +-120 +-180 +-240*/
	for ( int i = 0; i < 28 ; i++ ) {
		ang[ i ] = 0;
		ang_orig[i] = 0;
	}

	//reset counter
	// 	if ( !startUp ) {
	emit reset();
	// 	}
	Repaint = true;
	repaint();
}

bool KFRMain::testFinished() {
	if ( m_isCrushig )
		return false;
	
	bool finished = true;
	for ( int i = 0; i < 28; i++ ) {
		if ( pix[i] != pix_orig[i] ) {
			finished = false;
		}
	}

	for ( int i = 0; i < 28; i++ ) {
		// 		kdDebug() << "Found angle: " << ang[i] << endl;
		if ( ang[i] != 0 && ang[i] != 360  && ang[i] != - 360) {
			finished = false;
		}
	}
	
	if ( finished ) {
		return finished;
	}
	
	if ( m_inGame ) {
		kdDebug() << "Check if Game over" << endl;
		KFLevel* currLevel = m_game.endLevel( m_neededMoves );
		if ( currLevel->getMaxAllowedMoves() < m_neededMoves ) {
			slotGameOver();
		}
	}
	return finished;
}


/** function for drawing a rect with the centerPoint at (x,y)
and the size (w,h)*/
QRect KFRMain::cycleRect( int x, int y, int w, int h ) const {
	QRect r( ( x - w / 2 ), ( y - h / 2 ), w, h );
	return r;
}

void KFRMain::showCycles( QPainter *p ) {
	QPainter painter( &bg );
	int r = 332;
	painter.setPen( QPen( QColor("white" ), 2 ) );
	p->drawPixmap( 0, 0, bg, 0, 0, -1, -1 );

	for ( int i = 0; i < 3; i++ ) {
		// Draw balck

		// TOP Rings
		drawCyclePie( 520, -6, r ,  3140,  1400,  p, i );  // top right
		drawCyclePie( 280, -6, r , 4110, 1390 , p, i ); // top left


		// R1
		drawCycle( 280, 410, r ,p, i ); // MAIN Cycle
		drawCyclePie( 40, 410, r , 700,  -1400 , p, i ); // left


		// R2
		drawCycle( 520, 410, r , p, i );  // MAIN Cycle
		drawCyclePie( 760, 410, r , 3580,  -1400, p, i ); // right

		// R3
		drawCycle( 400, 202, r , p, i ); // MAIN Cycle
		drawCyclePie( 160, 202, r , 700, -2350, p, i ); // left
		drawCyclePie( 640, 202, r , 2180, 2350, p, i ); // right

		// BOTTOM Rings
		drawCyclePie( 160, 618, r , 265, 1400 , p, i ); // bottom left
		drawCyclePie( 400, 618, r  , 265, 2350 , p, i ); // bottom center
		drawCyclePie( 640, 618, r, 2620,  -1400 , p, i ); // bottom right
	}
	
}




void KFRMain::fadeRings( bool inout ) {
	/*	QPainter p( this );
		int r = 332;*/
	/*	for ( int brush = 7; brush > 0; brush-- ) {
			if ( brush == 8)
				p.setBrush( QBrush( QColor("black") , Dense7Pattern ) );
			if ( brush == 7)
				p.setBrush( QBrush( QColor("black") , Dense6Pattern ) );
			if ( brush == 6 )
				p.setBrush( QBrush( QColor("black") , Dense5Pattern ) );
			if ( brush == 5 )
				p.setBrush( QBrush( QColor("black") , Dense4Pattern ) );
			if ( brush == 4 )
				p.setBrush( QBrush( QColor("black") , Dense3Pattern ) );
			if ( brush == 3 )
				p.setBrush( QBrush( QColor("black") , Dense2Pattern ) );
			if ( brush == 2 )
				p.setBrush( QBrush( QColor("black") , Dense1Pattern ) );
			if ( brush == 2 )
				p.setBrush( QBrush( QColor("black") , SolidPattern ) );
	 
			for ( int i = 0; i < 3; i++ ) {
				// Draw balck
				// R1
				drawCycle( 280, 410, r , &p, i ); // MAIN Cycle
	 
				drawCyclePie( 280, -6, r , 4110, 1390 , &p, i ); // top left
				drawCyclePie( 40, 410, r , 700,  -1400 , &p, i ); // left
	 
	 
				// R2
				drawCycle( 520, 410, r , &p, i );  // MAIN Cycle
	 
				drawCyclePie( 520, -6, r ,  3140,  1400,  &p, i );  // top right
				drawCyclePie( 760, 410, r , 3580,  -1400, &p, i ); // right
	 
	 
				// R3
				drawCycle( 400, 202, r , &p, i ); // MAIN Cycle
	 
				drawCyclePie( 160, 202, r , 700, -2350, &p, i ); // left
				drawCyclePie( 640, 202, r , 2180, 2350, &p, i ); // right
	 
				drawCyclePie( 160, 618, r , 265, 1400 , &p, i ); // bottom left
				drawCyclePie( 400, 618, r  , 265, 2350 , &p, i ); // bottom center
				drawCyclePie( 640, 618, r, 2620,  -1400 , &p, i ); // bottom right
			}
		}*/
}

void  KFRMain::drawCycle( int m_x, int m_y, int r, QPainter *p, int color ) {
	int real_x = m_x - r/2;
	int real_y = m_y - r/2;

	switch( color ) {

	case 2:
		p->setPen( QPen( QColor("grey" ).light(), 1 ) );
		p->drawEllipse( real_x , real_y , r , r );
		break;

	case 1:
		p->setPen( QPen( QColor( "grey" ), 1 ) );
		p->drawEllipse( real_x + 1  , real_y + 1  , r - 2  , r - 2 );
		p->drawEllipse( real_x - 1  , real_y - 1  , r + 2  , r + 2 );
		break;

	case 0:
		p->setPen( QPen( QColor( "black" ), 1 ) );
		p->drawEllipse( real_x + 2  , real_y + 2  , r - 4  , r - 4 );
		p->drawEllipse( real_x - 2  , real_y - 2  , r + 4  , r + 4 );
		break;

	}
}

void  KFRMain::drawCyclePie( int m_x, int m_y, int r, int angle, int length, QPainter *p, int color ) {
	int real_x = m_x - r/2;
	int real_y = m_y - r/2;

	switch( color ) {
	case 2:
		p->setPen( QPen( QColor(" grey" ).light(), 1 ) );
		p->drawArc ( real_x , real_y , r , r, angle, length );
		break;
	case 1:
		p->setPen( QPen( QColor( "grey" ), 1 ) );
		p->drawArc ( real_x + 1  , real_y + 1  , r - 2  , r - 2, angle, length );
		p->drawArc ( real_x - 1  , real_y - 1  , r + 2  , r + 2,  angle, length );
		break;
	case 0:
		p->setPen( QPen( QColor( "black" ), 1 ) );
		p->drawArc ( real_x + 2  , real_y + 2  , r - 4  , r - 4,  angle, length );
		p->drawArc ( real_x - 2  , real_y - 2  , r + 4  , r + 4,  angle, length );
		break;
	}
}


void KFRMain::paintPieces ( QPainter *p, int  ) {
	//middle
	Repaint = false;
	for ( int i = 0; i < 28; i++ ) {
		paintPiece( pix[ i ], pos[ i ], ang[ i ], p );
	}
	Repaint = true;
}

void KFRMain::paintPiece ( QPixmap *pix, QPoint *middle, int deg, QPainter * ) {
	QWMatrix rot;
	rot.translate( -pix->width() / 2, -pix->height() / 2 );
	rot.rotate( deg );
	QPixmap out = pix->xForm( rot );

	int x = middle->x() - ( out.width() / 2 );
	int y = middle->y() - ( out.height() / 2 );

	QPoint dest( x, y );
	QPainter painter ( &bg );
	painter.drawPixmap( dest, out );
}

void KFRMain::crushImage() {
	Repaint = false;
	m_isCrushig = true;
	int last_ring = -1;
	int direction = -1;
	KFLevel* currLevel = m_game.getLevel();
	int m_neededMoves = 0;
	
	if ( m_inTrainigGame ) {
		kdDebug() << "Set Training Crush" << endl;
		m_neededMoves = Config().m_Level;
	} else if ( currLevel ) {
		kdDebug() << "Set Level Crush" << endl;
		m_neededMoves = currLevel->getMoves();
	} else {
		kdDebug() << "Not in any Game this is a bug!" << endl;
	}
	
	kdDebug() << "Crushig with: " << m_neededMoves << " moves." << endl;
	for ( int i = 0; i < m_neededMoves; i++ ) {
		int hour = i;
		int minute = i;
		int second = i;

		if ( hour >= 24 ) {
			hour = hour %24;
		}
		if ( minute >= 60 ) {
			minute = minute %60;
		}
		if ( second >= 60 ) {
			second = second %60;
		}

		QTime midnight1( hour, minute, second );
		srand( midnight1.secsTo( QTime::currentTime() ) );
		int which_ring = 1 + ( int ) ( 200.0 * rand() / ( RAND_MAX + 1.0 ) );

		int ring = which_ring % 3;
		if ( last_ring == -1 ) {
			kdDebug() << "First time Setting last ring to: " << ring << endl;
			last_ring = ring; 
		} else if ( ring == last_ring ) {
			ring = (ring + 1) % 2;
			kdDebug() << "Setting last ring to: " << ring << endl;
			last_ring = ring;
		} else {
			kdDebug() << "Setting last ring to: " << ring << endl;
			last_ring = ring;
		}
		if ( direction == -1 ) {
			QTime midnight2( hour, minute, second );
			srand( midnight2.secsTo( QTime::currentTime() ) );
			int which_direction = 1 + ( int ) ( 200.0 * rand() / ( RAND_MAX + 1.0 ) );
			direction = which_direction % 2;
			kdDebug() << "New Direction: " << direction << endl;
		}
		// 		kdDebug() << "Move Ring: " << ring <<  " direction: " << direction << endl;
		switch(ring) {
		case 0:
//  			r1moveLeft();
			
			if ( direction )
				r1moveLeft();
			else
				r1moveRight();
			break;
		case 1:
// 			r2moveLeft();
			if ( direction )
				r2moveLeft();
			else
				r2moveRight();
			break;
		case 2:
//  			r3moveLeft();
			if ( direction )
				r3moveLeft();
			else
				r3moveRight();
			break;
		}
	}
	
	// TODO: check if really mixed rings
	bool finished = true;
	for ( int i = 0; i < 28; i++ ) {
		if ( pix[i] != pix_orig[i] ) {
			finished = false;
		}
	}

	for ( int i = 0; i < 28; i++ ) {
		// 		kdDebug() << "Found angle: " << ang[i] << endl;
		if ( ang[i] != 0 && ang[i] != 360  && ang[i] != - 360) {
			finished = false;
		}
	}
	if ( finished ) {
		kdDebug() << "Crushed to fixed Image! "<< endl;
		crushImage();
	}
	m_isCrushig = false;
	Repaint = true;
	// m_inGame = true;
	emit resetCounter();
	repaint();
}

void KFRMain::checkForHighscore() {
	kdDebug() << "void KFRMain::checkForHighscore()" << endl;
	if ( m_highScore->isHighscore( m_game.gameScore() ) ) {
		kdDebug() << "New highscore: " << m_game.gameScore() << endl;
		const QString& msg = i18n("<qt><center><h2>Congratulations!</h2>You reached a new highscore with <b>%1</b> points.</center></qt>" ).arg( m_game.gameScore() );
		const QString& header  = i18n( "New Highscore" );
		const QString& currName = Config().m_player; 
		QString user;
		while ( user.isNull() ) {
		 	user = KInputDialog::getText( header, msg , currName);
		}
		const QString& username = user;
		if ( ! username.isNull() && username != "" ) {
			m_highScore->addToHighscore( username , m_game.reachedLevel(), m_game.gameScore() );
			Config().m_player = username;
			Config().write();
			slotRefreshHighscroes();
		}
	} else {
		kdDebug() << "Not a highscore: " << m_game.gameScore() << endl;
	}
}


void KFRMain::startGameAnimation() {
	if ( ! m_inGame || m_wasInGame )
		return;
	kdDebug() << "Starting game Animation" << endl;
	m_animationStep = 0;
	// 	m_timerID = startTimer( 100 );
	// 	m_timer->start( 1 );
	// 	connect( m_timer, SIGNAL(timeout()),this,  SLOT( slotStartAnimation() ) );
}

void KFRMain::endGameAnimation() {
	if ( m_inGame || ! m_wasInGame )
		return;
	m_animationStep = 0;
	// 	m_timerID = startTimer( 100 );
	// 	startTimer( 10 );
	// 	m_timer->start( 10 );
	// 	connect( m_timer, SIGNAL(timeout()),this, SLOT( slotEndAnimation() ) );
	kdDebug() << "End game Animation" << endl;
}

void KFRMain::timerEvent( QTimerEvent *e ) {
	if ( m_animationStep > 9 ) {
		m_animationStep = -1;
		killTimer( m_timerID );
		return;
	}
	kdDebug() << "timer event, id:" <<  e->timerId() << endl;
	m_animationStep++;
	repaint();
}


void KFRMain::paintEvent( QPaintEvent *) {
	QPainter p( this );
	// FIXME: implement start/stop animation
	/*	p.setPen( QPen( QColor(" grey" ).light(), 1 ) );
		if ( m_animationStep > -1 && m_animationStep < 10 ) {
			static KPixmap bg_tmp;
			if ( bg_tmp.isNull() ) bg_tmp = KPixmap( bg );
	 		kdDebug() << "Draw fade background at step: " << m_animationStep << endl;
			bitBlt( &bg,0,0, &bg_fx_chain[ m_animationStep ],0,0,800,600, Qt::CopyROP, false  );
			QWidget::paintEvent( ptr );
			return;
	// 		p.drawPixmap( 0, 0, bg_fx_chain[ m_animationStep ] );
		} else {
		}*/
	paintPieces( &p , 0 );
	if ( m_inGame || m_inTrainigGame ) {
		if ( ! m_wasInGame ) {
			startGameAnimation();
			m_wasInGame = true;
		}
		showGameButtons( true );
		showCycles( &p );
		paintLevelString( &p );
		paintMovesString( &p );
	} /* else 	if ( m_inTrainigGame ) {
		if ( ! m_wasInGame ) {
			startGameAnimation();
			m_wasInGame = true;
		}
		showGameButtons( true );
		showCycles( &p );
		paintLevelString( &p );
		paintMovesString( &p );
	}*/ else {
		if ( m_wasInGame ) {
			endGameAnimation();
			m_wasInGame = false;
		}
		showGameButtons( false );
	}
/*	if ( m_gameOver ) {
		paintGameOver( &p );
	}*/
}
void KFRMain::paintLevelString(QPainter *painter) {
	// QPainter painter(  );
	if ( m_inGame ) {
		KFLevel* currLevel = m_game.getLevel();
		if ( currLevel ) {
			painter->setPen( QPen( QColor("lightGray" ), 2 ) );
			painter->setFont( QFont("Helvetica [Cronyx]", 12 ) );
			switch ( Config().m_GameLevel ) {
				case 0:
				painter->drawText( 10, 545, i18n("Child") );
				break;
				case 1:
				painter->drawText( 10, 545, i18n("Beginner") );
				break;
				case 2:
				painter->drawText( 10, 545, i18n("Advanced") );
				break;
				case 3:
				painter->drawText( 10, 545, i18n("Expert") );
				break;
			}
			painter->drawText( 10, 565, i18n("Level: %1").arg( m_currLevel ) );
			painter->drawText( 10, 585, i18n("Allowed Moves: %1").arg( currLevel->getMaxAllowedMoves() ) );
		} 
	} else if ( m_inTrainigGame ) {
// 		kdDebug() << "Drawing Training Level String" << endl;
		painter->setPen( QPen( QColor("lightGray" ), 2 ) );
		painter->setFont( QFont("Helvetica [Cronyx]", 12 ) );
		painter->drawText( 10, 585, i18n("Crushed with %1 moves.").arg( Config().m_Level ) );
	}
}

void KFRMain::paintMovesString(QPainter *painter) {
	// QPainter painter(  );
	QFont f( QFont("Helvetica [Cronyx]", 12 ) );
	QFontMetrics fm( f );
	painter->setPen( QPen( QColor("lightGray" ), 2 ) );
	painter->setFont( f );
	int pixelWidth = fm.width( i18n("Moves: %1").arg( m_neededMoves ) );
	painter->drawText( 800 - pixelWidth - 10 , 585, i18n("Moves: %1").arg( m_neededMoves ) );
}

// void KFRMain::paintGameOver(QPainter *painter) {
	// QPainter painter(  );
/*	QFont f( QFont("Helvetica [Cronyx]", 44 ) );
	f.setWeight( QFont::Bold );
	QFontMetrics fm( f );
	int pixelWidth = fm.width( "Game Over" );
	int pixelHeight = fm.height();
	painter->setPen( QPen( QColor("lightGray" ), 2 ) );
	painter->setFont( f );
	painter->drawText( (800 / 2) - ( pixelWidth / 2) , (600 / 2) - ( pixelHeight / 2), i18n("Game Over") );*/
// }

void KFRMain::showGameButtons( bool onoff ) {
	if ( onoff ) {
		// count->show();
		r1kfl->show();
		r1kfr->show();
		r2kfl->show();
		r2kfr->show();
		r3kfl->show();
		r3kfr->show();

	} else {
// 		count->hide();
		r1kfl->hide();
		r1kfr->hide();
		r2kfl->hide();
		r2kfr->hide();
		r3kfl->hide();
		r3kfr->hide();

	}
}
