#include "dialogs.h"
#include "dialogs.moc"

#include <qlabel.h>
#include <kapp.h>
#include <kseparator.h>
#include <klocale.h>
#include "defines.h"

//-----------------------------------------------------------------------------
DialogBase::DialogBase(const QString &caption, int buttonMask,
					   ButtonCode defaultButton,
					   QWidget *parent, const char *name)
: KDialogBase(Plain, caption, buttonMask ,defaultButton, parent, name, TRUE,
			  TRUE)
{
	// top layout
	top = new QVBoxLayout(plainPage(), spacingHint());
	top->setResizeMode(QLayout::Fixed);
	
	// title
	QLabel *lab = new QLabel(caption, plainPage());
	QFont f( font() );
	f.setBold(TRUE);
	lab->setFont(f);
	lab->setAlignment(AlignCenter);
	lab->setFrameStyle(QFrame::Panel | QFrame::Raised);
	top->addWidget(lab);
	top->addSpacing(2*spacingHint());
}

//-----------------------------------------------------------------------------
const unsigned int NB_HS = 10;
const char *HS_GRP       = "High Scores";
const char *HS_NAME      = "name";
const char *HS_SCORE     = "score";
const char *HS_LEVEL     = "level";

#define HSString(str, i) QString("%1%2").arg(str).arg(i)
#define HSName(i)  HSString(HS_NAME, i)
#define HSScore(i) HSString(HS_SCORE, i)
#define HSLevel(i) HSString(HS_LEVEL, i)

uint HighScores::nbEntries()
{
	KConfig *conf = kapp->config();
	conf->setGroup(HS_GRP);

	for (uint i=0; i<NB_HS; i++)
		if ( conf->readUnsignedNumEntry(HSScore(i), 0)==0 ) return i;
	return NB_HS;
}

int HighScores::betterEntry(const GameOverItem *goi)
{
	KConfig *conf = kapp->config();
	conf->setGroup(HS_GRP);

	// (we assume they are ordered and valid ...)
	uint ne = nbEntries();
	for (uint i=0; i<ne; i++) {
		uint score = conf->readUnsignedNumEntry(HSScore(i), 0);
		if ( goi && score<goi->score ) return i;
	}
	return ne<NB_HS ? (int)ne : -1;
}

HighScores::HighScores(const GameOverItem *goi, QWidget *parent,
					   const char *name)
: DialogBase(i18n("Hall of Fame"), Close, Close, parent, name), qle(0)
{
	KConfig *conf = kapp->config();
	conf->setGroup(HS_GRP);

	bEntry = betterEntry(goi);
	uint nEntry = nbEntries();
	
	if (goi) {
		ASSERT( bEntry!=-1 );

		// insert the new score
		if ( nEntry<NB_HS ) nEntry++;
		for (uint j=nEntry-1; j>(uint)bEntry; j--) {
			conf->writeEntry(HSScore(j), conf->readEntry(HSScore(j-1)));
            conf->writeEntry(HSName(j), conf->readEntry(HSName(j-1)));
            conf->writeEntry(HSLevel(j), conf->readEntry(HSLevel(j-1)));
		}
		conf->writeEntry(HSScore(bEntry), (uint)goi->score);
		conf->writeEntry(HSName(bEntry), i18n("Anonymous")); // default name
		conf->writeEntry(HSLevel(bEntry), (uint)goi->level);
	}

/* layout */
	QLabel *lab;
	QGridLayout *gl;
	QFont f( font() );
	f.setBold(TRUE);

	if ( nEntry==0 ) {
		lab = new QLabel(i18n("no score entry"), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		lab->setFont(f);
		top->addWidget(lab);
	} else {
		gl = new QGridLayout(top, 4, nEntry+1, 2*spacingHint());
		
		lab = new QLabel(i18n("Rank"), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		gl->addWidget(lab, 0, 0);
		
		lab = new QLabel(i18n("Player Name"), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		gl->addWidget(lab, 0, 1);
		
		lab = new QLabel(i18n("Level"), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		lab->setAlignment(AlignCenter);
		gl->addWidget(lab, 0, 2);
		
		lab = new QLabel(i18n("Score"), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		lab->setAlignment(AlignRight);
		gl->addWidget(lab, 0, 3);
	}
	
	for (uint j=0; j<nEntry; j++) {
		/* rank */
		QString str;
		str.sprintf("%i", j+1);
		lab = new QLabel(str, plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		gl->addWidget(lab, j+1, 0);

		/* name */
		if ( !goi || ((uint)bEntry!=j) ) {
			QString name = conf->readEntry(HSName(j));
			lab = new QLabel(plainPage());
			lab->setFont(f);
			lab->setText(name);
			lab->setMinimumSize( lab->sizeHint() );
			gl->addWidget(lab, j+1, 1);
		} else {
			qle = new QLineEdit(plainPage());
			qle->setMaxLength(10);
			qle->setFont(f);
			qle->setMinimumSize(qle->fontMetrics().maxWidth()*10,
								qle->sizeHint().height());
			qle->setFocus();
			connect(qle, SIGNAL(returnPressed()), SLOT(writeName()));
			gl->addWidget(qle, j+1, 1);
		}
		
		/* level */
		lab = new QLabel(conf->readEntry(HSLevel(j)), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		lab->setAlignment(AlignCenter);
		gl->addWidget(lab, j+1, 2);

		/* score */
		lab = new QLabel(conf->readEntry(HSScore(j)), plainPage());
		lab->setMinimumSize( lab->sizeHint() );
		lab->setFont(f);
		lab->setAlignment(AlignRight);
		gl->addWidget(lab ,j+1, 3);
	}

/* button */
	enableButtonSeparator(TRUE);
	if (goi) enableButton(Close, FALSE);
}

void HighScores::writeName()
{
	KConfig *conf = kapp->config();
	conf->setGroup(HS_GRP);
	QString str = qle->text();
	if ( str.length() ) conf->writeEntry(HSName(bEntry), str);
	conf->sync();
	str = conf->readEntry(HSName(bEntry));
	qle->setText(str);
	enableButton(Close, TRUE);
}

void HighScores::reject()
{
	if ( qle && qle->isEnabled() ) {
		qle->setEnabled(FALSE);
		focusNextPrevChild(TRUE); // sort of hack (wonder why its call in
		                          // setEnabled(FALSE) does nothing ...)
	} else KDialogBase::reject();
}

//-----------------------------------------------------------------------------
MultiScores::MultiScores(uint nbPlayers, QWidget *parent, const char *name)
: DialogBase(i18n("Multiplayers scores"), Close, Close, parent, name),
  i(0)
{
	grid = new QGridLayout(nbPlayers, 3, spacingHint());
	top->addLayout(grid);
}

void MultiScores::add(const GameOverItem &goi)
{
	QLabel *lab = new QLabel(goi.name, plainPage());
	grid->addWidget(lab, i, 0);
	QString str;
	str.setNum((int)goi.level);
	lab = new QLabel(str, plainPage());
	grid->addWidget(lab, i, 1);
	str.setNum((int)goi.score);
	lab = new QLabel(str, plainPage());
	grid->addWidget(lab, i, 2);
	i++;
}

//-----------------------------------------------------------------------------
const char *OP_GRP        = "Options";
const char *OP_MENUBAR    = "menubar visible";
const char *OP_SHOW_NEXT  = "show next piece";
const char *OP_SHADOW     = "show piece shadow";
const char *OP_ANIMATIONS = "enable animations";

OptionDialog::OptionDialog(QWidget *parent)
: DialogBase(i18n("Settings"), Ok|Cancel, Cancel, parent)
{
	shadow = new QCheckBox(i18n("Show tile's shadow"), plainPage());
	shadow->setChecked(readShadow());
	top->addWidget(shadow);
	top->addSpacing(spacingHint());

	next = new QCheckBox(i18n("Show next tile"), plainPage());
	next->setChecked(readShowNext());
	top->addWidget(next);
	
	anim = new QCheckBox(i18n("Enable animations"), plainPage());
	anim->setChecked(readAnimations());
	top->addWidget(anim);
}

KConfig *OptionDialog::config()
{
	KConfig *conf = kapp->config();
	conf->setGroup(OP_GRP);
	return conf;
}

void OptionDialog::accept()
{
	KConfig *conf = config();
	conf->writeEntry(OP_SHADOW, shadow->isChecked());
	conf->writeEntry(OP_SHOW_NEXT, next->isChecked());
	conf->writeEntry(OP_ANIMATIONS, anim->isChecked());
	
	DialogBase::accept();
}

bool OptionDialog::readShadow()
{
	return config()->readBoolEntry(OP_SHADOW, TRUE);
}

bool OptionDialog::readShowNext()
{
	return config()->readBoolEntry(OP_SHOW_NEXT, TRUE);
}

bool OptionDialog::readAnimations()
{
	return config()->readBoolEntry(OP_ANIMATIONS, TRUE);
}

bool OptionDialog::readMenuVisible()
{
	return config()->readBoolEntry(OP_MENUBAR, TRUE);
}

void OptionDialog::writeMenuVisible(bool visible)
{
	config()->writeEntry(OP_MENUBAR, visible);
}
