/*
 * This file is part of the Simutrans project under the Artistic License.
 * (see LICENSE.txt)
 */

#include <string>
#include <stdio.h>
#include "../simdebug.h"

#include "../dataobj/tabfile.h"
#include "../dataobj/environment.h"

#include "../macros.h"
#include "../sound/sound.h"

#include "../utils/simstring.h"

#include "../tpl/stringhashtable_tpl.h"

#include "spezial_obj_tpl.h"
#include "sound_desc.h"
#include "ground_desc.h"

/*
 * sound of the program
 */
class sound_ids {
public:
	std::string filename;
	sint16 id;
	sound_ids() { id=NO_SOUND; }
	sound_ids(sint16 i) { id=i;  }
	sound_ids(sint16 i, const char* fn) : filename(fn), id(i) {}
};


static stringhashtable_tpl<sound_ids *> name_sound;
static bool sound_on = false;

const int NUM_SOUND_PATHS = 2;
static std::string sound_paths[NUM_SOUND_PATHS];


sint16 sound_desc_t::compatible_sound_id[MAX_OLD_SOUNDS]=
{
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND
};

// sound with the names of climates and "beaches" and "forest" are reserved for ambient noises
sint16 sound_desc_t::beach_sound = NO_SOUND;
sint16 sound_desc_t::forest_sound = NO_SOUND;
sint16 sound_desc_t::climate_sounds[MAX_CLIMATES]=
{
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND,
	NO_SOUND, NO_SOUND, NO_SOUND, NO_SOUND
};

sint16 sound_desc_t::message_sound;

/* init sounds */
/* standard sounds and old sounds are found in the file <pakset>/sound/sound.tab */
void sound_desc_t::init(const std::string &pak_dir, const std::string &addon_dir)
{
	// ok, now init
	sound_on = true;
	sound_paths[0] = addon_dir + "sound/";
	sound_paths[1] = pak_dir + "sound/";

	tabfile_t soundconf;
	const std::string tabfilename = pak_dir + "sound/sound.tab";

	if (!soundconf.open(tabfilename.c_str())) {
		return;
	}

DBG_MESSAGE("sound_desc_t::init()","successfully opened sound/sound.tab"  );
	tabfileobj_t contents;
	soundconf.read(contents);

	// max. 16 old sounds ...
	for( unsigned i=0;  i<MAX_OLD_SOUNDS;  i++ ) {
		char buf[1024];
		sprintf(buf, "sound[%i]", i);
		const char *fn=ltrim(contents.get(buf));
		if(fn[0]>0) {
DBG_MESSAGE("sound_desc_t::init()","reading sound %s", fn  );
			compatible_sound_id[i] = get_sound_id( fn );
DBG_MESSAGE("sound_desc_t::init()","assigned system sound %d to sound %s (id=%i)", i, (const char *)fn, compatible_sound_id[i] );
		}
	}
	message_sound = get_sound_id("message.wav");

	// now assign special sounds for climates, beaches and forest
	beach_sound = get_sound_id( "beaches.wav" );
	forest_sound = get_sound_id( "forest.wav" );

	for(  int i=0;  i<MAX_CLIMATES;  i++  ) {
		char name[64];
		sprintf( name, "%s.wav", ground_desc_t::get_climate_name_from_bit((climate)i) );
		climate_sounds[i] = get_sound_id( name );
	}
}


/* return sound id from index */
sint16 sound_desc_t::get_sound_id(const char *name)
{
	if(  !sound_on  ||  name==NULL  ||  *name==0  ) {
		return NO_SOUND;
	}

	sound_ids *s = name_sound.get(name);
	if(s!=NULL  &&  s->id!=NO_SOUND) {
		DBG_MESSAGE("sound_desc_t::get_sound_id()", "Successfully retrieved sound \"%s\" with internal id %hi", s->filename.c_str(), s->id );
		return s->id;
	}

	// not loaded: try to load it
	sint16 sample_id = NO_SOUND;
	for(  int i=0;  i<NUM_SOUND_PATHS;  i++  ) {
		sample_id = dr_load_sample((sound_paths[i] + name).c_str());
		if(  sample_id!=NO_SOUND  ) {
			break;
		}
	}

	if(sample_id==NO_SOUND) {
		dbg->warning("sound_desc_t::get_sound_id()", "Sound \"%s\" not found", name );
		return NO_SOUND;
	}

	s = new sound_ids(sample_id, name);
	name_sound.put(s->filename.c_str(), s );
DBG_MESSAGE("sound_desc_t::get_sound_id()", "Successfully loaded sound \"%s\" with internal id %hi", s->filename.c_str(), s->id );
	return s->id;
}



/*
 * if there is already such a sound => fail, else success and get an internal sound id
 * do not store desc as it will be deleted anyway
 */
bool sound_desc_t::register_desc(sound_desc_t *desc)
{
	if(  !sound_on  ) {
		return false;
	}

	// register, if not there (all done by this one here)
	desc->sound_id = get_sound_id( desc->get_name() );
	if(desc->sound_id!=NO_SOUND) {
		if(desc->nr>=0  &&  desc->nr<=8) {
			compatible_sound_id[desc->nr] = desc->sound_id;
DBG_MESSAGE("sound_desc_t::register_desc", "Successfully registered sound %s internal id %i as compatible sound %i", desc->get_name(), desc->sound_id, desc->nr );
			return true;
		}
	}

	dbg->warning("sound_desc_t::register_desc", "Failed to register sound %s internal id %i", desc->get_name(), desc->sound_id);
	return false;
}
