namespace _espe.conf
{
	
	/**
	 */
	type type_smtp_credentials = {
		host : string;
		port : int;
		username : string;
		password : string;
	};
	
	
	/**
	 */
	export type type_conf = {
		general : {
			verbosity : (
				"none"
				|
				"debug"
				|
				"notice"
				|
				"info"
				|
				"warning"
				|
				"error"
			);
			verification_secret : (null | string);
		};
		server : {
			port : int;
		};
		database : (
			{
				kind : "sqlite";
				data : {
					path : string;
				};
			}
			|
			{
				kind : "postgresql";
				data : {
					host : string;
					port ?: int;
					username : string;
					password : string;
					schema : string;
				};
			}
		);
		email_sending : (
			{
				kind : "regular";
				data : {
					smtp_credentials : type_smtp_credentials;
					sender : string;
				};
			}
			|
			{
				kind : "redirect";
				data : {
					smtp_credentials : type_smtp_credentials;
					sender : string;
					target : string;
				};
			}
			|
			{
				kind : "console";
				data : {
				};
			}
			|
			{
				kind : "drop";
				data : {
				};
			}
		);
		session_management : {
			in_memory : boolean;
			drop_all_at_start : boolean;
			lifetime : int;
		};
		settings : {
			target_domain : string;
			prefix_for_numberbased_email_addresses : string;
			registration_email : {
				subject : string;
				body : string;
			};
		};
		// TODO: evtl. in Datenbank verlagern
		admins : Array<
			{
				name : string;
				password_image : string;
				email_address : (null | string);
			}
		>;
	};
	
	
	/**
	 */
	var _data : (null | type_conf) = null;
	
	
	/**
	 * @todo mandatory fields
	 */
	export async function load(
		path : string
	) : Promise<void>
	{
		let conf_raw : any;
		if (! (await lib_plankton.file.exists(path))) {
			// return Promise.reject<void>(new Error("configuration file not found: " + path + "; using fallback"));
			conf_raw = {};
		}
		else {
			try {
				conf_raw = lib_plankton.json.decode(await lib_plankton.file.read(path));
			}
			catch (error) {
				conf_raw = null;
			}
		}
		if (conf_raw === null) {
			return Promise.reject<void>("configuration file could not be read");
		}
		else {
			_data = {
				"general": (
					((node_general) => ({
						"verbosity": (node_general["verbosity"] ?? "notice"),
						"verification_secret": (node_general["verification_secret"] ?? null),
					})) (conf_raw["general"] ?? {})
				),
				"server": (
					((node_server) => ({
						"port": (node_server["port"] ?? 7979),
					})) (conf_raw["server"] ?? {})
				),
				"database": (
					((node_database) => {
						const kind : string = (node_database["kind"] ?? "sqlite");
						const node_database_data_raw = (node_database["data"] ?? {});
						switch (kind) {
							case "sqlite": {
								return {
									"kind": kind,
									"data": {
										"path": (node_database_data_raw["path"] ?? "data.sqlite"),
									}
								};
								break;
							}
							case "postgresql": {
								return {
									"kind": kind,
									"data": node_database_data_raw,
								};
								break;
							}
							default: {
								throw (new Error("unhandled"));
								break;
							}
						}
					}) (conf_raw["database"] ?? {})
				),
				"email_sending": (
					((node_email_sending) => {
						const kind : string = (node_email_sending["kind"] ?? "regular");
						const data_raw = (node_email_sending["data"] ?? {});
						switch (kind) {
							case "regular": {
								return {
									"kind": kind,
									"data": {
										"smtp_credentials": (data_raw["smtp_credentials"] ?? null),
										"sender": data_raw["sender"],
									}
								};
								break;
							}
							case "redirect": {
								return {
									"kind": kind,
									"data": {
										"smtp_credentials": (data_raw["smtp_credentials"] ?? null),
										"sender": data_raw["sender"],
										"target": data_raw["target"],
									}
								};
								break;
							}
							case "console": {
								return {
									"kind": kind,
									"data": {
									}
								};
								break;
							}
							case "drop": {
								return {
									"kind": kind,
									"data": {
									}
								};
								break;
							}
							default: {
								throw (new Error("unhandled"));
								break;
							}
						}
					}) (conf_raw["email_sending"] ?? {})
				),
				"session_management": (
					((node_session_management) => ({
						"in_memory": (node_session_management["in_memory"] ?? true),
						"drop_all_at_start": (node_session_management["drop_all_at_start"] ?? true),
						"lifetime": (node_session_management["lifetime"] ?? 900),
					})) (conf_raw["session_management"] ?? {})
				),
				"settings": (
					((node_settings) => ({
						"target_domain": (node_settings["target_domain"] ?? "example.org"),
						"prefix_for_numberbased_email_addresses": (node_settings["prefix_for_numberbased_email_addresses"] ?? "member-"),
						"registration_email": {
							"subject": ((node_settings["registration_email"] ?? {})["subject"] ?? "Registration"),
							"body": ((node_settings["registration_email"] ?? {})["body"] ?? "URL: {{url}}"),
						},
					})) (conf_raw["settings"] ?? {})
				),
				"admins": (conf_raw["admins"] ?? []),
			};
			// process.stderr.write(JSON.stringify(_data, undefined, "\t"));
			return Promise.resolve<void>(undefined);
		}
	}
	
	
	/**
	 */
	export function get(
	) : type_conf
	{
		if (_data === null) {
			throw (new Error("conf not loaded yet"));
		}
		else {
			return _data;
		}
	}
	
}


