/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002-2005 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /home9/user/studenten/dahms/c-source/cvs_root/tinsel/tinsel.cpp,v 1.10 2006/09/07 16:10:21 dahms Exp $
 */

#include "common/stdafx.h"
#include "base/plugins.h"
#include "common/fs.h"
#include "common/system.h"
#include "common/config-manager.h"
#include "sound/mixer.h"

#include "tinsel/tinsel.h"
#include "tinsel/features.h"
#include "tinsel/index.h"
#include "tinsel/scnfile.h"
#include "tinsel/sound.h"
#include "tinsel/midi.h"

using namespace Tinsel;

TinselEngine::TinselEngine(OSystem *syst) : Engine(syst) {
	debug(2, "TinselEngine::TinselEngine()");
}

TinselEngine::~TinselEngine() {
}

void TinselEngine::errorString(const char *buf1, char *buf2) {
	strcpy(buf2, buf1);
}

int TinselEngine::init() {
	debug(2, "TinselEngine::init()");

	_features = getFeatures();
	ConfMan.setInt("features", (int)_features);

	debug(2, "features: %d", _features);

	if(_features & GF_DW1)
	{
		_system->setWindowCaption("Discworld");

		_system->beginGFXTransaction();
		initCommonGFX(false);
		_system->initSize(320, 200);
		_system->endGFXTransaction();
	}
	else if(_features & GF_DW2)
	{
		_system->setWindowCaption("Discworld 2");

		_system->beginGFXTransaction();
		initCommonGFX(true);
		//_system->setGraphicsMode("1x");
		_system->initSize(640, 480);
		_system->endGFXTransaction();
	}

	_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, 100);
	_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, 100);
	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 100);

	_index = new Index();
	_midi = new Midi(_mixer);
	_sound = new Sound(_mixer);

	//_midi->loadFile(0x00009e40);

	return 0;
}

int TinselEngine::go() {
	uint32 start, cur;

	debug(2, "TinselEngine::go()");

	SCNFile *scnfile = new SCNFile(
		(_features & GF_GRA) ? "title.gra" : "title.scn", _features);

	if(scnfile->getBackgroundBitmap()) {
		setBackgroundBitmap(scnfile->getBackgroundBitmap());
	}

	delete scnfile;

	//_sound->playSound(16);

	// main loop
	while(true)
	{
		cur = start = _system->getMillis();

		do {
			handleEvents();

			_system->delayMillis(20);
			cur = _system->getMillis();
		}
		while (cur < (start + 100));
	}

	return 0;
}

int TinselEngine::getFeatures() {
	const char *gameid = ConfMan.get("gameid").c_str();
	int features = 0;

	if(strncmp(gameid, "dw1", 3) == 0) features |= GF_DW1;
	if(strncmp(gameid, "dw2", 3) == 0) features |= GF_DW2;
	if(strncmp(gameid + 3, "gra", 3) == 0) features |= GF_GRA;

	return features;
}

void TinselEngine::handleEvents() {
	OSystem::Event event;
	static int index = 0;

	while (_system->pollEvent(event)) {
		switch (event.type) {

		case OSystem::EVENT_KEYDOWN:
			if(event.kbd.flags & OSystem::KBD_CTRL) {
				switch (event.kbd.keycode) {

				case 'd':
					//_debugger->attach();
					break;

				case 's':
					_sound->playSound(index++);
					break;

				default:
					debug("keydown: CTRL + %d", event.kbd.keycode);
					break;

				} // switch (event.kbd.keycode)
			} else {
				switch (event.kbd.keycode) {

				case 27: // ESC
					shutdown();
					break;

				default:
					debug("keydown: %d", event.kbd.keycode);
					break;

				}
			}
			break;

		case OSystem::EVENT_MOUSEMOVE:
			break;

		case OSystem::EVENT_LBUTTONDOWN:
			debug("left button down");
			break;

		case OSystem::EVENT_RBUTTONDOWN:
			break;

		case OSystem::EVENT_QUIT:
			shutdown();
			return;
			break;

		default:
			break;
		} // switch (event.type)
	}
}

bool TinselEngine::setBackgroundBitmap(Bitmap *bitmap) {
	uint32 width, height;
	const uint8 *pal;

	width = bitmap->getWidth();
	height = bitmap->getHeight();

	if(_features & GF_DW1) {
		if(width > 320) width = 320;
		if(height > 200) height = 200;
	}
	else if(_features & GF_DW2) {
		if(width > 640) width = 640;
		if(height > 480) height = 480;
	}

	debug("setting palette");

	if(bitmap->getPalette()) {
		pal = bitmap->getPalette()->palette;
		assert(pal);
		//Common::hexdump(pal, 1024);
		_system->setPalette((const byte *)pal, 0, 256);
	}

	debug("setting background image (%ux%u)", width, height);

	_system->clearScreen();
	_system->copyRectToScreen(bitmap->getBitmap(), bitmap->getWidth(), 0, 0,
		width, height);
	_system->updateScreen();

	return true;
}

void TinselEngine::shutdown() {
	_system->quit();
}
