/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-0/gui/massadd.cpp $
 * $Id: massadd.cpp 30459 2008-01-12 23:07:51Z sev $
 */

#include "engines/engine.h"
#include "base/game.h"
#include "base/plugins.h"
#include "common/events.h"

#include "gui/launcher.h"	// For addGameToConf()
#include "gui/massadd.h"
#include "gui/newgui.h"
#include "gui/widget.h"


namespace GUI {

/*
TODO:
- Themify this dialog
- Add a ListWidget showing all the games we are going to add, and update it live
- Add a 'busy' mouse cursor (animated?) which indicates to the user that
  something is in progress, and show this cursor while we scan
*/

enum {
	// Upper bound (im milliseconds) we want to spend in handleTickle.
	// Setting this low makes the GUI more responsive but also slows
	// down the scanning.
	kMaxScanTime = 50
};

enum {
	kOkCmd = 'OK  ',
	kCancelCmd = 'CNCL'
};



MassAddDialog::MassAddDialog(const FilesystemNode &startDir)
	: Dialog("massadddialog"),
	_dirsScanned(0),
	_okButton(0),
	_dirProgressText(0),
	_gameProgressText(0) {

	// The dir we start our scan at
	_scanStack.push(startDir);


	// Create dialog items
	// We need:
	// - "OK" button, only enabled after the scan has finished
	// - "Cancel" / "Abort" button, always active
	// - static text as headline for the dialog
	// - static text displaying the progress text
	// - (future) a listbox showing all the games we added/are going to add

	new StaticTextWidget(this, "massadddialog_caption",	"Mass Add Dialog");

	_dirProgressText = new StaticTextWidget(this, "massadddialog_dirprogress",
											"... progress ...");

	_gameProgressText = new StaticTextWidget(this, "massadddialog_gameprogress",
											 "... progress ...");

	_okButton = new ButtonWidget(this, "massadddialog_ok", "OK", kOkCmd, Common::ASCII_RETURN);
	_okButton->setEnabled(false);

	new ButtonWidget(this, "massadddialog_cancel", "Cancel", kCancelCmd, Common::ASCII_ESCAPE);

}


void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
	// FIXME: It's a really bad thing that we use two arbitrary constants
	if (cmd == kOkCmd) {
		// Add all the detected games to the config
		for (GameList::const_iterator iter = _games.begin(); iter != _games.end(); ++iter) {
			printf("  Added gameid '%s', desc '%s'\n",
				(*iter)["gameid"].c_str(),
				(*iter)["description"].c_str());
			addGameToConf(*iter);
		}

		// Write everything to disk
		ConfMan.flushToDisk();

		close();
	} else if (cmd == kCancelCmd) {
		// User cancelled, so we don't do anything and just leave.
		close();
	} else {
		Dialog::handleCommand(sender, cmd, data);
	}
}

void MassAddDialog::handleTickle() {
	if (_scanStack.empty())
		return;	// We have finished scanning

	uint32 t = g_system->getMillis();

	// Perform a breadth-first scan of the filesystem.
	while (!_scanStack.empty() && (g_system->getMillis() - t) < kMaxScanTime) {
		FilesystemNode dir = _scanStack.pop();

		FSList files;
		if (!dir.getChildren(files, FilesystemNode::kListAll)) {
			error("browser returned a node that is not a directory: '%s'",
					dir.getPath().c_str());
		}

		// Run the detector on the dir
		GameList candidates(PluginManager::instance().detectGames(files));

		if (candidates.size() >= 1) {
			// At least one match was found. For now we just take the first one...
			// a more sophisticated solution would do something more clever here,
			// e.g. ask the user which one to pick (make sure to display the
			// path, too).
			GameDescriptor result = candidates[0];
			result["path"] = dir.getPath();

			_games.push_back(result);
		}


		// Recurse into all subdirs
		for (FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
			if (file->isDirectory()) {
				_scanStack.push(*file);
			}
		}

		_dirsScanned++;
	}


	// Update the dialog
	char buf[256];

	if (_scanStack.empty()) {
		// Enable the OK button
		_okButton->setEnabled(true);

		snprintf(buf, sizeof(buf), "Scan complete!");
		_dirProgressText->setLabel(buf);

		snprintf(buf, sizeof(buf), "Discovered %d games.", _games.size());
		_gameProgressText->setLabel(buf);

	} else {
		snprintf(buf, sizeof(buf), "Scanned %d directories ...", _dirsScanned);
		_dirProgressText->setLabel(buf);

		snprintf(buf, sizeof(buf), "Discovered %d games ...", _games.size());
		_gameProgressText->setLabel(buf);
	}

	drawDialog();
}


} // end of namespace GUI

