#include <tdeapplication.h>
#include <tdeconfig.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <tdemessagebox.h>
#include <tdeglobal.h>
#include <highscore/kscoredialog.h>
#include <kstandarddirs.h>
#include <kseparator.h>
#include <klineedit.h>
#include <tdelocale.h>
#include <tdefiledialog.h>
#include <kurllabel.h>

#include <tqcheckbox.h>
#include <tqevent.h>
#include <tqframe.h>
#include <tqpen.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tdelistbox.h>
#include <tqstyle.h>
#include <tqrect.h>
#include <tqmap.h>
#include <tqpainter.h>
#include <tqpixmapcache.h>
#include <tqwidget.h>
#include <tqscrollview.h>
#include <tqvaluelist.h>
#include <tqptrlist.h>
#include <tqstringlist.h>
#include <tqstring.h>
#include <tqvbox.h>

#include "newgame.h"
#include "game.h"

NewGameDialog::NewGameDialog(bool enableCourses, TQWidget *parent, const char *_name)
	: KDialogBase(KDialogBase::TreeList, i18n("New Game"), Ok | Cancel, Ok, parent, _name)
{
	this->enableCourses = enableCourses;

	editors.setAutoDelete(true);
	TDEConfig *config = kapp->config();

	// lots o' colors :)
	startColors << yellow << blue << red << lightGray << cyan << darkBlue << magenta << darkGray << darkMagenta << darkYellow;

	playerPage = addPage(i18n("Players"));
	TQVBoxLayout *bigLayout = new TQVBoxLayout(playerPage, marginHint(), spacingHint());

	addButton = new KPushButton(i18n("&New Player"), playerPage);
	bigLayout->addWidget(addButton);

	connect(addButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(addPlayer()));

	scroller = new TQScrollView(playerPage);
	bigLayout->addWidget(scroller);
	layout = new TQVBox(scroller->viewport());
	if (!TQPixmapCache::find("grass", grass))
	{
		grass.load(locate("appdata", "pics/grass.png"));
		TQPixmapCache::insert("grass", grass);
	}
	scroller->viewport()->setBackgroundPixmap(grass);
	scroller->addChild(layout);

	TQMap<TQString, TQString> entries = config->entryMap("New Game Dialog");
	unsigned int i = 0;
	for (TQMap<TQString, TQString>::Iterator it = entries.begin(); it != entries.end(); ++it)
	{
		if (i > startColors.count())
			return;

		addPlayer();
		editors.last()->setName(it.key().right(it.key().length() - 1));
		editors.last()->setColor(TQColor(it.data()));
		++i;
	}

	if (editors.isEmpty())
	{
		addPlayer();
		addPlayer();
	}

	enableButtons();

	if (enableCourses)
	{
		coursePage = addPage(i18n("Course"), i18n("Choose Course to Play"));
		TQVBoxLayout *coursePageLayout = new TQVBoxLayout(coursePage, marginHint(), spacingHint());

		KURLLabel *coursesLink = new KURLLabel("http://web.mit.edu/~jasonkb/www/kolf/", "http://web.mit.edu/~jasonkb/www/kolf/", coursePage);
		connect(coursesLink, TQT_SIGNAL(leftClickedURL(const TQString &)), kapp, TQT_SLOT(invokeBrowser(const TQString &)));
		coursePageLayout->addWidget(coursesLink);

		TQHBoxLayout *hlayout = new TQHBoxLayout(coursePageLayout, spacingHint());

		// following use this group
		config->setGroup("New Game Dialog Mode");

		// find other courses
		externCourses = config->readListEntry("extra");

		/// course loading
		TQStringList items = externCourses + TDEGlobal::dirs()->findAllResources("appdata", "courses/*");
		TQStringList nameList;
		const TQString lastCourse(config->readEntry("course", ""));
		int curItem = 0;
		i = 0;
		for (TQStringList::Iterator it = items.begin(); it != items.end(); ++it, ++i)
		{
			TQString file = *it;
			CourseInfo curinfo;
			KolfGame::courseInfo(curinfo, file);
			info[file] = curinfo;
			names.append(file);
			nameList.append(curinfo.name);

			if (lastCourse == file)
				curItem = i;
		}

		const TQString newName(i18n("Create New"));
		info[TQString()] = CourseInfo(newName, newName, i18n("You"), 0, 0);
		names.append(TQString());
		nameList.append(newName);

		courseList = new TDEListBox(coursePage);
		hlayout->addWidget(courseList);
		courseList->insertStringList(nameList);
		courseList->setCurrentItem(curItem);
		connect(courseList, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(courseSelected(int)));
		connect(courseList, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(selectionChanged()));

		TQVBoxLayout *detailLayout = new TQVBoxLayout(hlayout, spacingHint());
		name = new TQLabel(coursePage);
		detailLayout->addWidget(name);
		author = new TQLabel(coursePage);
		detailLayout->addWidget(author);

		TQHBoxLayout *minorLayout = new TQHBoxLayout(detailLayout, spacingHint());
		par = new TQLabel(coursePage);
		minorLayout->addWidget(par);
		holes = new TQLabel(coursePage);
		minorLayout->addWidget(holes);

		detailLayout->addStretch();
		KPushButton *scores = new KPushButton(i18n("Highscores"), coursePage);
		connect(scores, TQT_SIGNAL(clicked()), this, TQT_SLOT(showHighscores()));
		detailLayout->addWidget(scores);

		detailLayout->addStretch();
		detailLayout->addWidget(new KSeparator(coursePage));

		minorLayout = new TQHBoxLayout(detailLayout, spacingHint());

		KPushButton *addCourseButton = new KPushButton(i18n("Add..."), coursePage);
		minorLayout->addWidget(addCourseButton);
		connect(addCourseButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(addCourse()));

		remove = new KPushButton(i18n("Remove"), coursePage);
		minorLayout->addWidget(remove);
		connect(remove, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeCourse()));

		courseSelected(curItem);
		selectionChanged();
	}
	
	// options page
	optionsPage = addPage(i18n("Options"), i18n("Game Options"));
	TQVBoxLayout *vlayout = new TQVBoxLayout(optionsPage, marginHint(), spacingHint());

	mode = new TQCheckBox(i18n("&Strict mode"), optionsPage);
	vlayout->addWidget(mode);
	mode->setChecked(config->readBoolEntry("competition", false));

	TQLabel *desc = new TQLabel(i18n("In strict mode, undo, editing, and switching holes is not allowed. This is generally for competition. Only in strict mode are highscores kept."), optionsPage);
	desc->setTextFormat(RichText);
	vlayout->addWidget(desc);
}

void NewGameDialog::slotOk()
{
	TDEConfig *config = kapp->config();

	config->setGroup("New Game Dialog Mode");
	config->writeEntry("competition", mode->isChecked());
	if (enableCourses)
	{
		config->writeEntry("course", currentCourse);
		config->writeEntry("extra", externCourses);
	}

	config->deleteGroup("New Game Dialog");
	config->setGroup("New Game Dialog");

	PlayerEditor *curEditor = 0;
	int i = 0;
	for (curEditor = editors.first(); curEditor; curEditor = editors.next(), ++i)
		config->writeEntry(TQString::number(i) + curEditor->name(), TQString(curEditor->color().name()));

	config->sync();

	KDialogBase::slotOk();
}

void NewGameDialog::courseSelected(int index)
{
	currentCourse = *names.at(index);

	CourseInfo &curinfo = info[currentCourse];

	name->setText(TQString("<strong>%1</strong>").arg(curinfo.name));

	author->setText(i18n("By %1").arg(curinfo.author));
	par->setText(i18n("Par %1").arg(curinfo.par));
	holes->setText(i18n("%1 Holes").arg(curinfo.holes));
}

void NewGameDialog::showHighscores()
{
	KScoreDialog *scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Custom1 | KScoreDialog::Score, this);
	scoreDialog->addField(KScoreDialog::Custom1, i18n("Par"), "Par");
	scoreDialog->setConfigGroup(info[currentCourse].untranslatedName + TQString(" Highscores"));
	scoreDialog->setComment(i18n("High Scores for %1").arg(info[currentCourse].name));
	scoreDialog->show();
}

void NewGameDialog::removeCourse()
{
	int curItem = courseList->currentItem();
	if (curItem < 0)
		return;

	TQString file = *names.at(curItem);
	if (externCourses.contains(file) < 1)
		return;

	names.remove(file);
	externCourses.remove(file);
	courseList->removeItem(curItem);

	selectionChanged();
}

void NewGameDialog::selectionChanged()
{
	const int curItem = courseList->currentItem();
	remove->setEnabled(!(curItem < 0 || externCourses.contains(*names.at(curItem)) < 1));
}

void NewGameDialog::addCourse()
{
	TQStringList files = KFileDialog::getOpenFileNames(":kourses", TQString::fromLatin1("application/x-kourse"), this, i18n("Pick Kolf Course"));

	bool hasDuplicates = false;

	for (TQStringList::Iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt)
	{
		if (names.contains(*fileIt) > 0)
		{
			hasDuplicates = true;
			continue;
		}

		CourseInfo curinfo;
		KolfGame::courseInfo(curinfo, *fileIt);
		info[*fileIt] = curinfo;
		names.prepend(*fileIt);
		externCourses.prepend(*fileIt);

		courseList->insertItem(curinfo.name, 0);
	}
	
	if (hasDuplicates)
		KMessageBox::information(this, i18n("Chosen course is already on course list."));

	courseList->setCurrentItem(0);
	courseSelected(0);
	selectionChanged();
}

void NewGameDialog::addPlayer()
{
	if (editors.count() >= startColors.count())
		return;

	editors.append(new PlayerEditor(i18n("Player %1").arg(editors.count() + 1), *startColors.at(editors.count()), layout));
	editors.last()->show();
	connect(editors.last(), TQT_SIGNAL(deleteEditor(PlayerEditor *)), this, TQT_SLOT(deleteEditor(PlayerEditor *)));

	enableButtons();
}

void NewGameDialog::deleteEditor(PlayerEditor *editor)
{
	if (editors.count() < 2)
		return;

	editors.removeRef(editor);

	enableButtons();
}

void NewGameDialog::enableButtons()
{
	addButton->setEnabled(!(editors.count() >= startColors.count()));
}

/////////////////////////

PlayerEditor::PlayerEditor(TQString startName, TQColor startColor, TQWidget *parent, const char *_name)
	: TQWidget(parent, _name)
{
	TQHBoxLayout *layout = new TQHBoxLayout(this, KDialogBase::spacingHint());

	if (!TQPixmapCache::find("grass", grass))
	{
		grass.load(locate("appdata", "pics/grass.png"));
		TQPixmapCache::insert("grass", grass);
	}
	setBackgroundPixmap(grass);

	editor = new KLineEdit(this);
	layout->addWidget(editor);
	editor->setFrame(false);
	editor->setText(startName);
	layout->addStretch();
	layout->addWidget(colorButton = new KColorButton(startColor, this));
	colorButton->setAutoMask(true);
	colorButton->setBackgroundPixmap(grass);

	KPushButton *remove = new KPushButton(i18n("Remove"), this);
	remove->setAutoMask(true);
	layout->addWidget(remove);
	remove->setBackgroundPixmap(grass);
	connect(remove, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeMe()));
}

void PlayerEditor::removeMe()
{
	emit deleteEditor(this);
}

#include "newgame.moc"