/*
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011, 2012 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 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 Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/


#include "Configuration.h"
#include "Logger.h"
#include <fstream>
#include <iostream>
#include <string.h>

#ifdef DEBUG_CONFIG
#define	debugLogEarly gLogEarly
#else
#define	debugLogEarly(x,y,z)
#endif


using namespace std;

char gCmdName[20] = {0}; // Use a char* to avoid avoid static initialization of string, and race at startup.

static const char* createConfigTable = {
	"CREATE TABLE IF NOT EXISTS CONFIG ("
		"KEYSTRING TEXT UNIQUE NOT NULL, "
		"VALUESTRING TEXT, "
		"STATIC INTEGER DEFAULT 0, "
		"OPTIONAL INTEGER DEFAULT 0, "
		"COMMENTS TEXT DEFAULT ''"
	")"
};

static std::string replaceAll(const std::string input, const std::string search, const std::string replace)
{
	std::string output = input;
 	int index = 0;

	while (true) {
		index = output.find(search, index);
		if (index == std::string::npos) {
			break;
		}

		output.replace(index, replace.length(), replace);
		index += replace.length();
	}

	return output;
}


float ConfigurationRecord::floatNumber() const
{
	float val;
	sscanf(mValue.c_str(),"%f",&val);
	return val;
}


ConfigurationTable::ConfigurationTable(const char* filename, const char *wCmdName, ConfigurationKeyMap wSchema)
{
	gLogEarly(LOG_INFO, "opening configuration table from path %s", filename);
	// Connect to the database.
	int rc = sqlite3_open(filename,&mDB);
	// (pat) When I used malloc here, sqlite3 sporadically crashes.
	if (wCmdName) {
		strncpy(gCmdName,wCmdName,18);
		gCmdName[18] = 0;
		strcat(gCmdName,":");
	}
	if (rc) {
		gLogEarly(LOG_EMERG, "cannot open configuration database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
		sqlite3_close(mDB);
		mDB = NULL;
		return;
	}
	// Create the table, if needed.
	if (!sqlite3_command(mDB,createConfigTable)) {
		gLogEarly(LOG_EMERG, "cannot create configuration table in database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
	}

	// Build CommonLibs schema
	ConfigurationKey *tmp;
	tmp = new ConfigurationKey("Log.Alarms.Max","20",
		"alarms",
		ConfigurationKey::CUSTOMER,
		ConfigurationKey::VALRANGE,
		"10:20",// educated guess
		false,
		"Maximum number of alarms to remember inside the application."
	);
	mSchema[tmp->getName()] = *tmp;
	free(tmp);

	tmp = new ConfigurationKey("Log.File","",
		"",
		ConfigurationKey::DEVELOPER,
		ConfigurationKey::FILEPATH_OPT,// audited
		"",
		false,
		"Path to use for textfile based logging.  "
			"By default, this feature is disabled.  "
			"To enable, specify an absolute path to the file you wish to use, eg: /tmp/my-debug.log.  "
			"To disable again, execute \"unconfig Log.File\"."
	);
	mSchema[tmp->getName()] = *tmp;
	free(tmp);

	tmp = new ConfigurationKey("Log.Level","NOTICE",
		"",
		ConfigurationKey::CUSTOMER,
		ConfigurationKey::CHOICE,
		"EMERG|EMERGENCY - report serious faults associated with service failure or hardware damage,"
			"ALERT|ALERT - report likely service disruption caused by misconfiguration or poor connectivity,"
			"CRIT|CRITICAL - report anomalous events that are likely to degrade service,"
			"ERR|ERROR - report internal errors of the software that may result in degradation of service in unusual circumstances,"
			"WARNING|WARNING - report anomalous events that may indicate a degradation of normal service,"
			"NOTICE|NOTICE - report anomalous events that probably do not affect service but may be of interest to network operators,"
			"INFO|INFORMATION - report normal events,"
			"DEBUG|DEBUG - only for use by developers and will degrade system performance",
		false,
		"Default logging level when no other level is defined for a file."
	);
	mSchema[tmp->getName()] = *tmp;
	free(tmp);

	// Add application specific schema
	mSchema.insert(wSchema.begin(), wSchema.end());

	// Init the cross checking callback to something predictable
	mCrossCheck = NULL;
}

string ConfigurationTable::getDefaultSQL(const std::string& program, const std::string& version)
{
	stringstream ss;
	ConfigurationKeyMap::iterator mp;

	ss << "--" << endl;
	ss << "-- This file was generated using: " << program << " --gensql" << endl;
	ss << "-- binary version: " << version << endl;
	ss << "--" << endl;
	ss << "-- Future changes should not be put in this file directly but" << endl;
	ss << "-- rather in the program's ConfigurationKey schema." << endl;
	ss << "--" << endl;
	ss << "PRAGMA foreign_keys=OFF;" << endl;
	ss << "BEGIN TRANSACTION;" << endl;
	ss << "CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');" << endl;

	mp = mSchema.begin();
	while (mp != mSchema.end()) {
		ss << "INSERT INTO \"CONFIG\" VALUES(";
			// name
			ss << "'" << mp->first << "',";
			// default
			ss << "'" << mp->second.getDefaultValue() << "',";
			// static
			if (mp->second.isStatic()) {
				ss << "1";
			} else {
				ss << "0";
			}
			ss << ",";
			// optional
			ss << "0,";
			// description
			ss << "'";
			if (mp->second.getType() == ConfigurationKey::BOOLEAN) {
				ss << "1=enabled, 0=disabled - ";
			}
			ss << mp->second.getDescription();
			if (mp->second.isStatic()) {
				ss << "  Static.";
			}
			ss << "'";
		ss << ");" << endl;
		mp++;
	}

	ss << "COMMIT;" << endl;
	ss << endl;

	return ss.str();
}

string ConfigurationTable::getTeX(const std::string& program, const std::string& version)
{
	stringstream ss;
	ConfigurationKeyMap::iterator mp;

	ss << "% START AUTO-GENERATED CONTENT" << endl;
	ss << "% -- these sections were generated using: " << program << " --gentex" << endl;
	ss << "% -- binary version: " << version << endl;

	ss << "\\subsection{Customer Site Parameters}" << endl;
	ss << "These parameters must be changed to fit your site." << endl;
	ss << "\\begin{itemize}" << endl;
	mp = mSchema.begin();
	while (mp != mSchema.end()) {
		if (mp->second.getVisibility() == ConfigurationKey::CUSTOMERSITE) {
			ss << "	\\item ";
				// name
				ss << mp->first << " -- ";
				// description
				ss << mp->second.getDescription();
			ss << endl;
		}
		mp++;
	}
	ss << "\\end{itemize}" << endl;
	ss << endl;

	ss << "\\subsection{Customer Tuneable Parameters}" << endl;
	ss << "These parameters can be changed to optimize your site." << endl;
	ss << "\\begin{itemize}" << endl;
	mp = mSchema.begin();
	while (mp != mSchema.end()) {
		if (mp->second.getVisibility() != ConfigurationKey::CUSTOMERSITE &&
			(
				mp->second.getVisibility() == ConfigurationKey::CUSTOMER ||
				mp->second.getVisibility() == ConfigurationKey::CUSTOMERTUNE ||
				mp->second.getVisibility() == ConfigurationKey::CUSTOMERWARN
			)) {
			ss << "	\\item ";
				// name
				ss << mp->first << " -- ";
				// description
				ss << mp->second.getDescription();
			ss << endl;
		}
		mp++;
	}
	ss << "\\end{itemize}" << endl;
	ss << endl;

	ss << "\\subsection{Developer/Factory Parameters}" << endl;
	ss << "These parameters should only be changed by when developing new code." << endl;
	ss << "\\begin{itemize}" << endl;
	mp = mSchema.begin();
	while (mp != mSchema.end()) {
		if (mp->second.getVisibility() == ConfigurationKey::FACTORY ||
			mp->second.getVisibility() == ConfigurationKey::DEVELOPER) {
			ss << "	\\item ";
				// name
				ss << mp->first << " -- ";
				// description
				ss << mp->second.getDescription();
			ss << endl;
		}
		mp++;
	}
	ss << "\\end{itemize}" << endl;
	ss << "% END AUTO-GENERATED CONTENT" << endl;
	ss << endl;

	string tmp = replaceAll(ss.str(), "^", "\\^");
	return replaceAll(tmp, "_", "\\_");
}

bool ConfigurationTable::defines(const string& key)
{
	try {
		ScopedLock lock(mLock);
		return lookup(key).defined();
	} catch (ConfigurationTableKeyNotFound) {
		debugLogEarly(LOG_ALERT, "configuration parameter %s not found", key.c_str());
		return false;
	}
}

bool ConfigurationTable::keyDefinedInSchema(const std::string& name)
{
	return mSchema.find(name) == mSchema.end() ? false : true;
}

bool ConfigurationTable::isValidValue(const std::string& name, const std::string& val) {
	bool ret = false;

	ConfigurationKey key = mSchema[name];

	switch (key.getType()) {
		case ConfigurationKey::BOOLEAN: {
			if (val == "1" || val == "0") {
				ret = true;
			}
			break;
		}

		case ConfigurationKey::CHOICE_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::CHOICE: {
			int startPos = -1;
			uint endPos = 0;

			std::string tmp = key.getValidValues();

			do {
				startPos++;
				if ((endPos = tmp.find('|', startPos)) != std::string::npos) {
					if (val == tmp.substr(startPos, endPos-startPos)) {
						ret = true;
						break;
					}
				} else {
					if (val == tmp.substr(startPos, tmp.find(',', startPos)-startPos)) {
						ret = true;
						break;
					}
				}

			} while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);
			break;
		}

		case ConfigurationKey::CIDR_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::CIDR: {
			uint delimiter;
			std::string ip;
			int cidr = -1;

			delimiter = val.find('/');
			if (delimiter != std::string::npos) {
				ip = val.substr(0, delimiter);
				std::stringstream(val.substr(delimiter+1)) >> cidr;
				if (ConfigurationKey::isValidIP(ip) && 0 <= cidr && cidr <= 32) {
					ret = true;
				}
			}
			break;
		}

		case ConfigurationKey::FILEPATH_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::FILEPATH: {
			regex_t r;
			const char* expression = "^[a-zA-Z0-9/_.-]+$";
			int result = regcomp(&r, expression, REG_EXTENDED);
			if (result) {
				char msg[256];
				regerror(result,&r,msg,255);
				break;//abort();
			}
			if (regexec(&r, val.c_str(), 0, NULL, 0)==0) {
				ret = true;
			}
			regfree(&r);
			break;
		}

		case ConfigurationKey::IPADDRESS_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::IPADDRESS: {
			ret = ConfigurationKey::isValidIP(val);
			break;
		}

		case ConfigurationKey::IPANDPORT: {
			uint delimiter;
			std::string ip;
			int port = -1;

			delimiter = val.find(':');
			if (delimiter != std::string::npos) {
				ip = val.substr(0, delimiter);
				std::stringstream(val.substr(delimiter+1)) >> port;
				if (ConfigurationKey::isValidIP(ip) && 1 <= port && port <= 65535) {
					ret = true;
				}
			}
			break;
		}

		case ConfigurationKey::MIPADDRESS_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::MIPADDRESS: {
			int startPos = -1;
			uint endPos = 0;

			do {
				startPos++;
				endPos = val.find(' ', startPos);
				if (ConfigurationKey::isValidIP(val.substr(startPos, endPos-startPos))) {
					ret = true;
				} else {
					ret = false;
					break;
				}

			} while ((startPos = endPos) != (int)std::string::npos);
			break;
		}

		case ConfigurationKey::PORT_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::PORT: {
			int intVal;

			std::stringstream(val) >> intVal;

			if (1 <= intVal && intVal <= 65535) {
				ret = true;
			}
			break;
		}

		case ConfigurationKey::REGEX_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::REGEX: {
			regex_t r;
			const char* expression = val.c_str();
			int result = regcomp(&r, expression, REG_EXTENDED);
			if (result) {
				char msg[256];
				regerror(result,&r,msg,255);
			} else {
				ret = true;
			}
			regfree(&r);
			break;
		}

		case ConfigurationKey::STRING_OPT: {
			if (val.length() == 0) {
				ret = true;
				break;
			}
		}
		case ConfigurationKey::STRING: {
			regex_t r;
			const char* expression = key.getValidValues().c_str();
			int result = regcomp(&r, expression, REG_EXTENDED);
			if (result) {
				char msg[256];
				regerror(result,&r,msg,255);
				break;//abort();
			}
			if (regexec(&r, val.c_str(), 0, NULL, 0)==0) {
				ret = true;
			}
			regfree(&r);
			break;
		}

		case ConfigurationKey::VALRANGE: {
			regex_t r;
			int result;
			if (key.getValidValues().find('.') != std::string::npos) {
				result = regcomp(&r, "^[0-9.-]+$", REG_EXTENDED);
			} else {
				result = regcomp(&r, "^[0-9-]+$", REG_EXTENDED);
			}
			if (result) {
				char msg[256];
				regerror(result,&r,msg,255);
				break;//abort();
			}
			if (regexec(&r, val.c_str(), 0, NULL, 0)!=0) {
				ret = false;
			} else if (key.getValidValues().find('.') != std::string::npos) {
				ret = ConfigurationKey::isInValRange<float>(key, val, false);
			} else {
				ret = ConfigurationKey::isInValRange<int>(key, val, true);
			}

			regfree(&r);
			break;
		}
	}

	return ret;
}

ConfigurationKeyMap ConfigurationTable::getSimilarKeys(const std::string& snippet) {
	ConfigurationKeyMap tmp;

	ConfigurationKeyMap::const_iterator mp = mSchema.begin();
	while (mp != mSchema.end()) {
		if (mp->first.find(snippet) != std::string::npos) {
			tmp[mp->first] = mp->second;
		}
		mp++;
	}

	return tmp;
}

const ConfigurationRecord& ConfigurationTable::lookup(const string& key)
{
	assert(mDB);
	checkCacheAge();
	// We assume the caller holds mLock.
	// So it is OK to return a reference into the cache.

	// Check the cache.
	// This is cheap.
	ConfigurationMap::const_iterator where = mCache.find(key);
	if (where!=mCache.end()) {
		if (where->second.defined()) return where->second;
		throw ConfigurationTableKeyNotFound(key);
	}

	// Check the database.
	// This is more expensive.
	char *value = NULL;
	sqlite3_single_lookup(mDB,"CONFIG",
			"KEYSTRING",key.c_str(),"VALUESTRING",value);

	// value found, cache the result
	if (value) {
		mCache[key] = ConfigurationRecord(value);
	// key definition found, cache the default
	} else if (keyDefinedInSchema(key)) {
		mCache[key] = ConfigurationRecord(mSchema[key].getDefaultValue());
	// total miss, cache the error
	} else {
		mCache[key] = ConfigurationRecord(false);
		throw ConfigurationTableKeyNotFound(key);
	}

	free(value);

	// Leave mLock locked.  The caller holds it still.
	return mCache[key];
}



bool ConfigurationTable::isStatic(const string& key)
{
	if (keyDefinedInSchema(key)) {
		return mSchema[key].isStatic();
	} else {
		return false;
	}
}




string ConfigurationTable::getStr(const string& key)
{
	// We need the lock because rec is a reference into the cache.
	try {
		ScopedLock lock(mLock);
		return lookup(key).value();
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}
}


bool ConfigurationTable::getBool(const string& key)
{
	try {
		return getNum(key) != 0;
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}
}


long ConfigurationTable::getNum(const string& key)
{
	// We need the lock because rec is a reference into the cache.
	try {
		ScopedLock lock(mLock);
		return lookup(key).number();
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}
}


float ConfigurationTable::getFloat(const string& key)
{
	try {
		ScopedLock lock(mLock);
		return lookup(key).floatNumber();
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}
}

std::vector<string> ConfigurationTable::getVectorOfStrings(const string& key)
{
	// Look up the string.
	char *line=NULL;
	try {
		ScopedLock lock(mLock);
		const ConfigurationRecord& rec = lookup(key);
		line = strdup(rec.value().c_str());
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}

	assert(line);
	char *lp = line;
	
	// Parse the string.
	std::vector<string> retVal;
	while (lp) {
		while (*lp==' ') lp++;
		if (*lp == '\0') break;
		char *tp = strsep(&lp," ");
		if (!tp) break;
		retVal.push_back(tp);
	}
	free(line);
	return retVal;
}


std::vector<unsigned> ConfigurationTable::getVector(const string& key)
{
	// Look up the string.
	char *line=NULL;
	try {
		ScopedLock lock(mLock);
		const ConfigurationRecord& rec = lookup(key);
		line = strdup(rec.value().c_str());
	} catch (ConfigurationTableKeyNotFound) {
		// Raise an alert and re-throw the exception.
		debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
		throw ConfigurationTableKeyNotFound(key);
	}

	assert(line);
	char *lp = line;

	// Parse the string.
	std::vector<unsigned> retVal;
	while (lp) {
		// Watch for multiple or trailing spaces.
		while (*lp==' ') lp++;
		if (*lp=='\0') break;
		retVal.push_back(strtol(lp,NULL,0));
		strsep(&lp," ");
	}
	free(line);
	return retVal;
}


bool ConfigurationTable::remove(const string& key)
{
	assert(mDB);

	ScopedLock lock(mLock);
	// Clear the cache entry and the database.
	ConfigurationMap::iterator where = mCache.find(key);
	if (where!=mCache.end()) mCache.erase(where);
	// Really remove it.
	string cmd = "DELETE FROM CONFIG WHERE KEYSTRING=='"+key+"'";
	return sqlite3_command(mDB,cmd.c_str());
}



void ConfigurationTable::find(const string& pat, ostream& os) const
{
	// Prepare the statement.
	string cmd = "SELECT KEYSTRING,VALUESTRING FROM CONFIG WHERE KEYSTRING LIKE \"%" + pat + "%\"";
	sqlite3_stmt *stmt;
	if (sqlite3_prepare_statement(mDB,&stmt,cmd.c_str())) return;
	// Read the result.
	int src = sqlite3_run_query(mDB,stmt);
	while (src==SQLITE_ROW) {
		const char* value = (const char*)sqlite3_column_text(stmt,1);
		os << sqlite3_column_text(stmt,0) << " ";
		int len = 0;
		if (value) {
			len = strlen(value);
		}
		if (len && value) os << value << endl;
		else os << "(disabled)" << endl;
		src = sqlite3_run_query(mDB,stmt);
	}
	sqlite3_finalize(stmt);
}


ConfigurationRecordMap ConfigurationTable::getAllPairs() const
{
	ConfigurationRecordMap tmp;

	// Prepare the statement.
	string cmd = "SELECT KEYSTRING,VALUESTRING FROM CONFIG";
	sqlite3_stmt *stmt;
	if (sqlite3_prepare_statement(mDB,&stmt,cmd.c_str())) return tmp;
	// Read the result.
	int src = sqlite3_run_query(mDB,stmt);
	while (src==SQLITE_ROW) {
		const char* key = (const char*)sqlite3_column_text(stmt,0);
		const char* value = (const char*)sqlite3_column_text(stmt,1);
		if (key && value) {
			tmp[string(key)] = ConfigurationRecord(value);
		} else if (key && !value) {
			tmp[string(key)] = ConfigurationRecord(false);
		}
		src = sqlite3_run_query(mDB,stmt);
	}
	sqlite3_finalize(stmt);

	return tmp;
}

bool ConfigurationTable::set(const string& key, const string& value)
{
	assert(mDB);
	ScopedLock lock(mLock);
	string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",\"" + value + "\",1)";
	bool success = sqlite3_command(mDB,cmd.c_str());
	// Cache the result.
	if (success) mCache[key] = ConfigurationRecord(value);
	return success;
}

bool ConfigurationTable::set(const string& key, long value)
{
	char buffer[30];
	sprintf(buffer,"%ld",value);
	return set(key,buffer);
}


bool ConfigurationTable::set(const string& key)
{
	assert(mDB);
	ScopedLock lock(mLock);
	string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",NULL,1)";
	bool success = sqlite3_command(mDB,cmd.c_str());
	if (success) mCache[key] = ConfigurationRecord(true);
	return success;
}


void ConfigurationTable::checkCacheAge()
{
	// mLock is set by caller 
	static time_t timeOfLastPurge = 0;
	time_t now = time(NULL);
	// purge every 3 seconds
	// purge period cannot be configuration parameter
	if (now - timeOfLastPurge < 3) return;
	timeOfLastPurge = now;
	// this is purge() without the lock
	ConfigurationMap::iterator mp = mCache.begin();
	while (mp != mCache.end()) {
		ConfigurationMap::iterator prev = mp;
		mp++;
		mCache.erase(prev);
	}
}


void ConfigurationTable::purge()
{
	ScopedLock lock(mLock);
	ConfigurationMap::iterator mp = mCache.begin();
	while (mp != mCache.end()) {
		ConfigurationMap::iterator prev = mp;
		mp++;
		mCache.erase(prev);
	}
}


void ConfigurationTable::setUpdateHook(void(*func)(void *,int ,char const *,char const *,sqlite3_int64))
{
	assert(mDB);
	sqlite3_update_hook(mDB,func,NULL);
}


void ConfigurationTable::setCrossCheckHook(vector<string> (*wCrossCheck)(const string&))
{
	mCrossCheck = wCrossCheck;
}


vector<string> ConfigurationTable::crossCheck(const string& key) {
	vector<string> ret;

	if (mCrossCheck != NULL) {
		ret = mCrossCheck(key);
	}

	return ret;
}

void HashString::computeHash()
{
	// FIXME -- Someone needs to review this hash function.
	const char* cstr = c_str();
	mHash = 0;
	for (unsigned i=0; i<size(); i++) {
		mHash = mHash ^ (mHash >> 32);
		mHash = mHash*127 + cstr[i];
	}
}


void SimpleKeyValue::addItem(const char* pair_orig)
{
	char *pair = strdup(pair_orig);
	char *key = pair;
	char *mark = strchr(pair,'=');
	if (!mark) return;
	*mark = '\0';
	char *value = mark+1;
	mMap[key] = value;
	free(pair);
}



const char* SimpleKeyValue::get(const char* key) const
{
	HashStringMap::const_iterator p = mMap.find(key);
	if (p==mMap.end()) return NULL;
	return p->second.c_str();
}


void SimpleKeyValue::addItems(const char* pairs_orig)
{
	char *pairs = strdup(pairs_orig);
	char *thisPair;
	while ((thisPair=strsep(&pairs," "))!=NULL) {
		addItem(thisPair);
	}
	free(pairs);
}


bool ConfigurationKey::isValidIP(const std::string& ip) {
	struct sockaddr_in sa;
	return inet_pton(AF_INET, ip.c_str(), &(sa.sin_addr)) != 0;
}


void ConfigurationKey::getMinMaxStepping(const ConfigurationKey &key, std::string &min, std::string &max, std::string &stepping) {
	uint delimiter;
	int startPos;
	uint endPos;

	std::string tmp = key.getValidValues();
	stepping = "1";

	// grab steps if they're defined
	startPos = tmp.find('(');
	if (startPos != (int)std::string::npos) {
		endPos = tmp.find(')');
		stepping = tmp.substr(startPos+1, endPos-startPos-1);
		tmp = tmp.substr(0, startPos);
	}
	startPos = 0;

	delimiter = tmp.find(':', startPos);
	min = tmp.substr(startPos, delimiter-startPos);
	max = tmp.substr(delimiter+1, tmp.find(',', delimiter)-delimiter-1);
}


template<class T> bool ConfigurationKey::isInValRange(const ConfigurationKey &key, const std::string& val, const bool isInteger) {
	bool ret = false;

	T convVal;
	T min;
	T max;
	T steps;
	std::string strMin;
	std::string strMax;
	std::string strSteps;

	std::stringstream(val) >> convVal;

	ConfigurationKey::getMinMaxStepping(key, strMin, strMax, strSteps);
	std::stringstream(strMin) >> min;
	std::stringstream(strMax) >> max;
	std::stringstream(strSteps) >> steps;

	// TODO : only ranges checked, steps not enforced
	if (isInteger) {
		if (val.find('.') == std::string::npos && min <= convVal && convVal <= max) {
			ret = true;
		}
	} else {
		if (min <= convVal && convVal <= max) {
			ret = true;
		}
	}

	return ret;
}

const std::string ConfigurationKey::getARFCNsString() {
	stringstream ss;
	int i;
	float downlink;
	float uplink;

	// 128:251 GSM850
	downlink = 869.2;
	uplink = 824.2;
	for (i = 128; i <= 251; i++) {
		ss << i << "|GSM850 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
		downlink += 0.2;
		uplink += 0.2;
	}

	// 1:124 PGSM900
	downlink = 935.2;
	uplink = 890.2;
	for (i = 1; i <= 124; i++) {
		ss << i << "|PGSM900 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
		downlink += 0.2;
		uplink += 0.2;
	}

	// 512:885 DCS1800
	downlink = 1805.2;
	uplink = 1710.2;
	for (i = 512; i <= 885; i++) {
		ss << i << "|DCS1800 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
		downlink += 0.2;
		uplink += 0.2;
	}

	// 512:810 PCS1900
	downlink = 1930.2;
	uplink = 1850.2;
	for (i = 512; i <= 810; i++) {
		ss << i << "|PCS1900 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
		downlink += 0.2;
		uplink += 0.2;
	}

	ss << endl;

	return ss.str();
}

const std::string ConfigurationKey::visibilityLevelToString(const ConfigurationKey::VisibilityLevel& visibility) {
	std::string ret = "UNKNOWN ERROR";

	switch (visibility) {
		case ConfigurationKey::CUSTOMER:
			ret = "customer - can be freely changed by the customer without any detriment to their system";
			break;
		case ConfigurationKey::CUSTOMERSITE:
			ret = "customer site - these values are different for each BTS and should not be left default";
			break;
		case ConfigurationKey::CUSTOMERTUNE:
			ret = "customer tune - should only be changed to tune an installation to better suit the physical environment or MS usage pattern";
			break;
		case ConfigurationKey::CUSTOMERWARN:
			ret = "customer warn - a warning will be presented and confirmation required before changing this sensitive setting";
			break;
		case ConfigurationKey::DEVELOPER:
			ret = "developer - should only be changed by developers to debug/optimize the implementation";
			break;
		case ConfigurationKey::FACTORY:
			ret = "factory - set once at the factory, should never be changed";
			break;
	}

	return ret;
}

const std::string ConfigurationKey::typeToString(const ConfigurationKey::Type& type) {
	std::string ret = "UNKNOWN ERROR";

	switch (type) {
		case BOOLEAN:
			ret = "boolean";
			break;
		case CHOICE_OPT:
			ret = "multiple choice (optional)";
			break;
		case CHOICE:
			ret = "multiple choice";
			break;
		case CIDR_OPT:
			ret = "CIDR notation (optional)";
			break;
		case CIDR:
			ret = "CIDR notation";
			break;
		case FILEPATH_OPT:
			ret = "file path (optional)";
			break;
		case FILEPATH:
			ret = "file path";
			break;
		case IPADDRESS_OPT:
			ret = "IP address (optional)";
			break;
		case IPADDRESS:
			ret = "IP address";
			break;
		case IPANDPORT:
			ret = "IP address and port";
			break;
		case MIPADDRESS_OPT:
			ret = "space-separated list of IP addresses (optional)";
			break;
		case MIPADDRESS:
			ret = "space-separated list of IP addresses";
			break;
		case PORT_OPT:
			ret = "IP port (optional)";
			break;
		case PORT:
			ret = "IP port";
			break;
		case REGEX_OPT:
			ret = "regular expression (optional)";
			break;
		case REGEX:
			ret = "regular expression";
			break;
		case STRING_OPT:
			ret = "string (optional)";
			break;
		case STRING:
			ret = "string";
			break;
		case VALRANGE:
			ret = "value range";
			break;
	}

	return ret;
}

void ConfigurationKey::printKey(const ConfigurationKey &key, const std::string& currentValue, ostream& os) {
	os << key.getName() << " ";
	if (!currentValue.length()) {
		os << "(disabled)";
	} else {
		os << currentValue;
	}
	if (currentValue.compare(key.getDefaultValue()) == 0) {
		os << "     [default]";
	}
	os << endl;
}

void ConfigurationKey::printDescription(const ConfigurationKey &key, ostream& os) {
	std::string tmp;

	os << " - description:      " << key.getDescription() << std::endl;
	if (key.getUnits().length()) {
		os << " - units:            " << key.getUnits() << std::endl;
	}
	os << " - type:             " << ConfigurationKey::typeToString(key.getType()) << std::endl;
	if (key.getDefaultValue().length()) {
		os << " - default value:    " << key.getDefaultValue() << std::endl;
	}
	os << " - visibility level: " << ConfigurationKey::visibilityLevelToString(key.getVisibility()) << std::endl;
	os << " - static:           " << key.isStatic() << std::endl;

	tmp = key.getValidValues();
	if (key.getType() == ConfigurationKey::VALRANGE) {
		int startPos = tmp.find('(');
		uint delimiter = 0;
		if (startPos != (int)std::string::npos) {
			tmp = tmp.substr(0, startPos);
		}
		startPos = -1;

		do {
			startPos++;
			delimiter = tmp.find(':', startPos);
			os << " - valid values:     " << "from " << tmp.substr(startPos, delimiter-startPos) << " to "
				<< tmp.substr(delimiter+1, tmp.find(',', delimiter)-delimiter-1) << std::endl;

		} while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);

	} else if (key.getType() == ConfigurationKey::CHOICE) {
		int startPos = -1;
		uint endPos = 0;

		do {
			startPos++;
			if ((endPos = tmp.find('|', startPos)) != std::string::npos) {
				os << " - valid values:     " << tmp.substr(startPos, endPos-startPos);
				os << " = " << tmp.substr(endPos+1, tmp.find(',', endPos)-endPos-1) << std::endl;
			} else {
				os << " - valid values:     " << tmp.substr(startPos, tmp.find(',', startPos)-startPos) << std::endl;
			}

		} while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);

	} else if (key.getType() == ConfigurationKey::BOOLEAN) {
		os << " - valid values:     0 = disabled" << std::endl;
		os << " - valid values:     1 = enabled" << std::endl;

	} else if (key.getType() == ConfigurationKey::STRING) {
		os << " - valid val regex:  " << tmp << std::endl;

	} else if (key.getValidValues().length()) {
		os << " - raw valid values: " << tmp << std::endl;
	}
}


// vim: ts=4 sw=4
