/** @file dependencies.cpp
 *
 *	Definition of dependency to string (and vice versa) convertion module.
 *
 *	See dependencies.h for more info.
 *
 *	(C) Ceslav Przywara 2008, MFF UK Prague
 *
 */

// String -> index.
#include <map>
// Index -> string.
#include <vector>

// Self header
#include "dependencies.h"

namespace ace {

/*
 */
typedef std::map<std::string, dependency_index_t> string_to_dependency_t;
/*
 */
typedef std::vector<std::string> dependency_to_string_t;

// Extern "constants" definition.
namespace dependency {
	dependency_index_t head = 0;
	dependency_index_t undef = 0;
}

// Number of all dependencies must be const (used as array boundary).
const dependency_index_t number_of_dependencies = 118;

// Dependencies table.
// Note: The hashing scheme is based on indices of given values,
// so it may be affected by any changes in table below.
const char* dependency_to_cstring_tab[number_of_dependencies] = {
	"Adv", "Adv_Ap", "Adv_Co", "Adv_Pa",
	"AdvAtr", "AdvAtr_Ap", "AdvAtr_Co", "AdvAtr_Pa",
	"Apos", "Apos_Ap", "Apos_Co", "Apos_Pa",
	"Atr", "Atr_Ap", "Atr_Co", "Atr_Pa",
	"AtrAdv", "AtrAdv_Ap", "AtrAdv_Co", "AtrAdv_Pa",
	"AtrAtr", "AtrAtr_Ap", "AtrAtr_Co", "AtrAtr_Pa",
	"AtrObj", "AtrObj_Ap", "AtrObj_Co", "AtrObj_Pa",
	"Atv", "Atv_Ap", "Atv_Co", "Atv_Pa",
	"AtvV", "AtvV_Ap", "AtvV_Co", "AtvV_Pa",
	"Aux", "Aux_Ap", "Aux_Co", "Aux_Pa",
	"AuxC", "AuxC_Ap", "AuxC_Co", "AuxC_Pa",
	"AuxG", "AuxG_Ap", "AuxG_Co", "AuxG_Pa",
	"AuxK", "AuxK_Ap", "AuxK_Co", "AuxK_Pa",
	"AuxO", "AuxO_Ap", "AuxO_Co", "AuxO_Pa",
	"AuxP", "AuxP_Ap", "AuxP_Co", "AuxP_Pa",
	"AuxR", "AuxR_Ap", "AuxR_Co", "AuxR_Pa",
	"AuxS", "AuxS_Ap", "AuxS_Co", "AuxS_Pa",
	"AuxT", "AuxT_Ap", "AuxT_Co", "AuxT_Pa",
	"AuxV", "AuxV_Ap", "AuxV_Co", "AuxV_Pa",
	"AuxX", "AuxX_Ap", "AuxX_Co", "AuxX_Pa",
	"AuxY", "AuxY_Ap", "AuxY_Co", "AuxY_Pa",
	"AuxZ", "AuxZ_Ap", "AuxZ_Co", "AuxZ_Pa",
	"Coord", "Coord_Ap", "Coord_Co", "Coord_Pa",
	"ExD", "ExD_Ap", "ExD_Co", "ExD_Pa",
	"Head",
	"Obj", "Obj_Ap", "Obj_Co", "Obj_Pa",
	"ObjAtr", "ObjAtr_Ap", "ObjAtr_Co", "ObjAtr_Pa",
	"Pnom", "Pnom_Ap", "Pnom_Co", "Pnom_Pa",
	"Pred", "Pred_Ap", "Pred_Co", "Pred_Pa",
	"Sb", "Sb_Ap", "Sb_Co", "Sb_Pa",
	"Undef"
};

/** Inits string to dependency mapping.
 */
string_to_dependency_t _init_str2dep(void) {

	string_to_dependency_t str2dep;
	
	// Init by using `dependency_to_string`.
	for ( unsigned i = 0; i < number_of_dependencies; ++i ) {
		std::string str = std::string(dependency_to_cstring_tab[i]);
		str2dep.insert(string_to_dependency_t::value_type(str, static_cast<dependency_index_t>(i)));
		if ( str == std::string("Head") ) {
			// Set Head to appropriate value.
			dependency::head = static_cast<dependency_index_t>(i);
		}
		if ( str == std::string("Undef") ) {
			// Set Undef to appropriate value.
			dependency::undef = static_cast<dependency_index_t>(i);
		}
	}

	return str2dep;
}

/*	Interface item implementation - for info see description in header file.
 */
dependency_index_t string2dependency(std::string& str) {
	static string_to_dependency_t str2dep = _init_str2dep();
	
	string_to_dependency_t::iterator founded = str2dep.find(str);
	return (founded == str2dep.end()) ? dependency::undef : founded->second;
}

/*	Interface item implementation - for info see description in header file.
 */
const char * dependency2cstring(dependency_index_t dependency_index) {
	return dependency_to_cstring_tab[dependency_index];
}

} // namespace ace
