/*
 * Logserver
 * Copyright (C) 2017-2025 Joel Reardon
 *
 * 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 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef __IB__CONFIG__H__
#define __IB__CONFIG__H__

#include <map>
#include <memory>
#include <mutex>
#include <string>

using namespace std;

/* Config class storing some flags and string. Singleton pattern where _()
 * provides caller with a shared global config. It is thread safe. */
class Config {
public:

	Config() {}
	virtual ~Config() {}

	// provide singleton instance of config
	static Config* _() {
		static Config _config;
		return &_config;
	}

	// returns the value for a key
	virtual string get(const string& key) {
		unique_lock<mutex> ul(_m);
		return _name_to_string[key];
	}

	// sets a key-value pair
	virtual void set(const string& key, const string& val) {
		unique_lock<mutex> ul(_m);
		_name_to_string[key] = val;
	}

	// enables a boolean flag
	virtual void flag_on(const string& key) {
		unique_lock<mutex> ul(_m);
		_name_to_string[key] = "true";
	}

	// disables a boolean flag
	virtual void flag_off(const string& key) {
		unique_lock<mutex> ul(_m);
		_name_to_string[key] = "false";
	}

	// toggles a boolean flag
	virtual void flag_toggle(const string& key) {
		unique_lock<mutex> ul(_m);
		if (!_name_to_string.count(key))
			_name_to_string[key] = "false";

		_name_to_string[key] = flag_locked(key) ? "false" : "true";
	}

	// returns the value for a boolean flag
	virtual bool flag(const string& key) {
		unique_lock<mutex> ul(_m);

		return flag_locked(key);
	}

protected:
	virtual bool flag_locked(const string& key) {
		if (!_name_to_string.count(key)) return false;
		if (_name_to_string[key] == "true") return true;
		return false;
	}

	// disable copy
	Config(const Config&);

	// map of key to values for config
	map<string, string> _name_to_string;

	// for threadsafety
	mutex _m;

};

#endif  // __IB__CONFIG__H__
