/*
Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Backend
Copyright (C) 2024 Christian Fraß

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/>. 
 */

namespace _espe.conf
{
	
	/**
	 */
	type type_log_threshold = (
		"debug"
		|
		"info"
		|
		"notice"
		|
		"warning"
		|
		"error"
	);
	
	
	/**
	 */
	type type_log_format = (
		"jsonl"
		|
		"human_readable"
	);
	
	
	/**
	 */
	export type type_conf = {
		general : {
			language : (null | string);
			verification_secret : (null | string);
		};
		log : Array<
			{
				kind : "stdout";
				data : {
					threshold : type_log_threshold;
				};
			}
			|
			{
				kind : "file";
				data : {
					threshold : type_log_threshold;
					path : string;
				};
			}
			|
			{
				kind : "email";
				data : {
					threshold : type_log_threshold;
					smtp_credentials : {
						host : string;
						port : int;
						username : string;
						password : string;
					};
					sender : string;
					receivers : Array<string>;
				};
			}
		>;
		server : {
			host : string;
			port : int;
			path_base : string;
		};
		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 : _espe.helpers.type_smtp_credentials;
					sender : string;
				};
			}
			|
			{
				kind : "redirect";
				data : {
					smtp_credentials : _espe.helpers.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 : {
			organisation : {
				name : string;
				domain : string;
			};
			misc : {
				prefix_for_veiled_email_addresses : string;
				facultative_membership_number : boolean;
				auto_register : boolean;
			};
			summon_email : {
				remark : string;
			};
			password_policy : {
				minimum_length : (null | int);
				maximum_length : (null | int);
				must_contain_letter : boolean;
				must_contain_number : boolean;
				must_contain_special_character : boolean;
			};
			password_change : {
				cooldown_time : int;
			};
			name_index : {
				veil : boolean;
				salt : (null | string);
			};
			connections : {
				frontend_url_base : (null | string);
				login_url : (null | string);
			};
		};
		// TODO: evtl. in Datenbank verlagern
		admins : Array<
			{
				name : string;
				password_image : string;
				email_address : (null | string);
			}
		>;
		outputs : Array<
			{
				kind : "authelia_file";
				data : {
					path : string;
				}
			}
			|
			{
				kind : "http";
				data : {
					scheme : ("http" | "https");
					host : string;
					path : string;
					method : ("get" | "post" | "put" | "patch" | "delete" | "head" | "options");
					query : (null | string);
					headers : Record<string,string>;
				};
			}
			|
			{
				kind : "arc";
				data : {
					http_scheme : ("http" | "https");
					http_host : string;
					http_port : int;
					hash_salt : string;
				}
			}
		>;
	};
	
	
	/**
	 */
	var _data : (null | type_conf) = null;
	
	
	/**
	 */
	export function inject(
		conf_raw : any
	) : void
	{
		switch (conf_raw["version"]) {
			case 1: {
				_data = {
					"general": (
						((node_general) => ({
							"language": (node_general["language"] ?? null),
							"verification_secret": (node_general["verification_secret"] ?? null),
						})) (conf_raw["general"] ?? {})
					),
					"log": [
						{
							"kind": "stdout",
							"data": {
								"threshold": ((conf_raw["general"] ?? {})["verbosity"] ?? "notice"),
							}
						},
					],
					"server": (
						((node_server) => ({
							"host": "::",
							"port": (node_server["port"] ?? 4916),
							"path_base": (node_server["path_base"] ?? ""),
						})) (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"] ?? "console");
							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) => ({
							"organisation": {
								"name": ((node_settings["organisation"] ?? {})["name"] ?? "Example Orginsation"), // TODO: mandatory?
								"domain": ((node_settings["organisation"] ?? {})["domain"] ?? "example.org"), // TODO: mandatory?
							},
							"misc": (
								((node_settings_misc) => ({
									"prefix_for_veiled_email_addresses": (node_settings_misc["prefix_for_veiled_email_addresses"] ?? "member-"),
									"facultative_membership_number": (node_settings_misc["facultative_membership_number"] ?? false),
									"auto_register": (node_settings_misc["auto_register"] ?? false),
								})) (node_settings["misc"] ?? {})
							),
							"summon_email": (
								((node_settings_summon_email) => ({
									"remark": (node_settings_summon_email["remark"] ?? null),
								})) (node_settings["summon_email"] ?? {})
							),
							"password_policy": (
								((node_settings_password_policy) => ({
									"minimum_length": (
										("minimum_length" in node_settings_password_policy)
										? node_settings_password_policy["minimum_length"]
										: 8
									),
									"maximum_length": (
										("maximum_length" in node_settings_password_policy)
										? node_settings_password_policy["maximum_length"]
										: 240
									),
									"must_contain_letter": (node_settings_password_policy["must_contain_letter"] ?? true),
									"must_contain_number": (node_settings_password_policy["must_contain_number"] ?? true),
									"must_contain_special_character": (node_settings_password_policy["must_contain_special_character"] ?? true),
								})) (node_settings["password_policy"] ?? {})
							),
							"password_change": (
								((node_settings_password_change) => ({
									"cooldown_time": (node_settings_password_change["cooldown_time"] ?? 86400),
								})) (node_settings["password_change"] ?? {})
							),
							"name_index": (
								((node_settings_password_policy) => ({
									"veil": (node_settings_password_policy["veil"] ?? true),
									"salt": (node_settings_password_policy["salt"] ?? ""),
								})) (node_settings["name_index"] ?? {})
							),
							"connections": (
								((node_settings_connections) => ({
									"frontend_url_base": (node_settings_connections["frontend_url_base"] ?? null),
									"login_url": (node_settings_connections["login_url"] ?? null),
								})) (node_settings["connections"] ?? {})
							),
						})) (conf_raw["settings"] ?? {})
					),
					"admins": (conf_raw["admins"] ?? []),
					"outputs": (
						((node_output) => (
							("authelia" in node_output)
							? [
								{
									"kind": "authelia_file",
									"data": {
										"path": node_output["authelia"],
									}
								}
							]
							: [
							]
						)) (conf_raw["output"] ?? {})
					),
				};
				break;
			}
			case 2: {
				_data = {
					"general": (
						((node_general) => ({
							"language": (node_general["language"] ?? null),
							"verification_secret": (node_general["verification_secret"] ?? null),
						})) (conf_raw["general"] ?? {})
					),
					"log": (
						((node_log) => node_log.map(
							(node_log_entry : any) => ({
								"kind": node_log_entry["kind"],
								"data": Object.assign(
									{
										"format": "human_readable",
										"threshold": "notice",
									},
									(node_log_entry["data"] ?? {})
								)
							})
						)) (
							conf_raw["log"]
							??
							[
								{
									"kind": "console",
									"data": {
									}
								},
							]
						)
					),
					"server": (
						((node_server) => ({
							"host": "::",
							"port": (node_server["port"] ?? 4916),
							"path_base": (node_server["path_base"] ?? ""),
						})) (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"] ?? "console");
							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) => ({
							"organisation": {
								"name": ((node_settings["organisation"] ?? {})["name"] ?? "Example Orginsation"), // TODO: mandatory?
								"domain": ((node_settings["organisation"] ?? {})["domain"] ?? "example.org"), // TODO: mandatory?
							},
							"misc": (
								((node_settings_misc) => ({
									"prefix_for_veiled_email_addresses": (node_settings_misc["prefix_for_veiled_email_addresses"] ?? "member-"),
									"facultative_membership_number": (node_settings_misc["facultative_membership_number"] ?? false),
									"auto_register": (node_settings_misc["auto_register"] ?? false),
								})) (node_settings["misc"] ?? {})
							),
							"summon_email": (
								((node_settings_summon_email) => ({
									"remark": (node_settings_summon_email["remark"] ?? null),
								})) (node_settings["summon_email"] ?? {})
							),
							"password_policy": (
								((node_settings_password_policy) => ({
									"minimum_length": (
										("minimum_length" in node_settings_password_policy)
										? node_settings_password_policy["minimum_length"]
										: 8
									),
									"maximum_length": (
										("maximum_length" in node_settings_password_policy)
										? node_settings_password_policy["maximum_length"]
										: 240
									),
									"must_contain_letter": (node_settings_password_policy["must_contain_letter"] ?? true),
									"must_contain_number": (node_settings_password_policy["must_contain_number"] ?? true),
									"must_contain_special_character": (node_settings_password_policy["must_contain_special_character"] ?? true),
								})) (node_settings["password_policy"] ?? {})
							),
							"password_change": (
								((node_settings_password_change) => ({
									"cooldown_time": (node_settings_password_change["cooldown_time"] ?? 86400),
								})) (node_settings["password_change"] ?? {})
							),
							"name_index": (
								((node_settings_password_policy) => ({
									"veil": (node_settings_password_policy["veil"] ?? true),
									"salt": (node_settings_password_policy["salt"] ?? ""),
								})) (node_settings["name_index"] ?? {})
							),
							"connections": (
								((node_settings_connections) => ({
									"frontend_url_base": (node_settings_connections["frontend_url_base"] ?? null),
									"login_url": (node_settings_connections["login_url"] ?? null),
								})) (node_settings["connections"] ?? {})
							),
						})) (conf_raw["settings"] ?? {})
					),
					"admins": (conf_raw["admins"] ?? []),
					"outputs": (
						((node_output) => (
							("authelia" in node_output)
							? [
								{
									"kind": "authelia_file",
									"data": {
										"path": node_output["authelia"],
									}
								}
							]
							: [
							]
						)) (conf_raw["output"] ?? {})
					),
				};
				break;
			}
			case 3: {
				_data = {
					"general": (
						((node_general) => ({
							"language": (node_general["language"] ?? null),
							"verification_secret": (node_general["verification_secret"] ?? null),
						})) (conf_raw["general"] ?? {})
					),
					"log": (
						((node_log) => node_log.map(
							(node_log_entry : any) => ({
								"kind": node_log_entry["kind"],
								"data": Object.assign(
									{
										"format": "human_readable",
										"threshold": "notice",
									},
									(node_log_entry["data"] ?? {})
								)
							})
						)) (
							conf_raw["log"]
							??
							[
								{
									"kind": "console",
									"data": {
									}
								},
							]
						)
					),
					"server": (
						((node_server) => ({
							"host": "::",
							"port": (node_server["port"] ?? 4916),
							"path_base": (node_server["path_base"] ?? ""),
						})) (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"] ?? "console");
							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) => ({
							"organisation": {
								"name": ((node_settings["organisation"] ?? {})["name"] ?? "Example Orginsation"), // TODO: mandatory?
								"domain": ((node_settings["organisation"] ?? {})["domain"] ?? "example.org"), // TODO: mandatory?
							},
							"misc": (
								((node_settings_misc) => ({
									"prefix_for_veiled_email_addresses": (node_settings_misc["prefix_for_veiled_email_addresses"] ?? "member-"),
									"facultative_membership_number": (node_settings_misc["facultative_membership_number"] ?? false),
									"auto_register": (node_settings_misc["auto_register"] ?? false),
								})) (node_settings["misc"] ?? {})
							),
							"summon_email": (
								((node_settings_summon_email) => ({
									"remark": (node_settings_summon_email["remark"] ?? null),
								})) (node_settings["summon_email"] ?? {})
							),
							"password_policy": (
								((node_settings_password_policy) => ({
									"minimum_length": (
										("minimum_length" in node_settings_password_policy)
										? node_settings_password_policy["minimum_length"]
										: 8
									),
									"maximum_length": (
										("maximum_length" in node_settings_password_policy)
										? node_settings_password_policy["maximum_length"]
										: 240
									),
									"must_contain_letter": (node_settings_password_policy["must_contain_letter"] ?? true),
									"must_contain_number": (node_settings_password_policy["must_contain_number"] ?? true),
									"must_contain_special_character": (node_settings_password_policy["must_contain_special_character"] ?? true),
								})) (node_settings["password_policy"] ?? {})
							),
							"password_change": (
								((node_settings_password_change) => ({
									"cooldown_time": (node_settings_password_change["cooldown_time"] ?? 86400),
								})) (node_settings["password_change"] ?? {})
							),
							"name_index": (
								((node_settings_password_policy) => ({
									"veil": (node_settings_password_policy["veil"] ?? true),
									"salt": (node_settings_password_policy["salt"] ?? ""),
								})) (node_settings["name_index"] ?? {})
							),
							"connections": (
								((node_settings_connections) => ({
									"frontend_url_base": (node_settings_connections["frontend_url_base"] ?? null),
									"login_url": (node_settings_connections["login_url"] ?? null),
								})) (node_settings["connections"] ?? {})
							),
						})) (conf_raw["settings"] ?? {})
					),
					"admins": (conf_raw["admins"] ?? []),
					"outputs": (conf_raw["outputs"] ?? []),
				};
				break;
			}
			case 4: {
				_data = {
					"general": (
						((node_general) => ({
							"language": (node_general["language"] ?? null),
							"verification_secret": (node_general["verification_secret"] ?? null),
						})) (conf_raw["general"] ?? {})
					),
					"log": (
						((node_log) => node_log.map(
							(node_log_entry : any) => ({
								"kind": node_log_entry["kind"],
								"data": Object.assign(
									{
										"format": "human_readable",
										"threshold": "notice",
									},
									(node_log_entry["data"] ?? {})
								)
							})
						)) (
							conf_raw["log"]
							??
							[
								{
									"kind": "console",
									"data": {
									}
								},
							]
						)
					),
					"server": (
						((node_server) => ({
							"host": (node_server["host"] ?? "::"),
							"port": (node_server["port"] ?? 4916),
							"path_base": (node_server["path_base"] ?? ""),
						})) (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"] ?? "console");
							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) => ({
							"organisation": {
								"name": ((node_settings["organisation"] ?? {})["name"] ?? "Example Orginsation"), // TODO: mandatory?
								"domain": ((node_settings["organisation"] ?? {})["domain"] ?? "example.org"), // TODO: mandatory?
							},
							"misc": (
								((node_settings_misc) => ({
									"prefix_for_veiled_email_addresses": (node_settings_misc["prefix_for_veiled_email_addresses"] ?? "member-"),
									"facultative_membership_number": (node_settings_misc["facultative_membership_number"] ?? false),
									"auto_register": (node_settings_misc["auto_register"] ?? false),
								})) (node_settings["misc"] ?? {})
							),
							"summon_email": (
								((node_settings_summon_email) => ({
									"remark": (node_settings_summon_email["remark"] ?? null),
								})) (node_settings["summon_email"] ?? {})
							),
							"password_policy": (
								((node_settings_password_policy) => ({
									"minimum_length": (
										("minimum_length" in node_settings_password_policy)
										? node_settings_password_policy["minimum_length"]
										: 8
									),
									"maximum_length": (
										("maximum_length" in node_settings_password_policy)
										? node_settings_password_policy["maximum_length"]
										: 240
									),
									"must_contain_letter": (node_settings_password_policy["must_contain_letter"] ?? true),
									"must_contain_number": (node_settings_password_policy["must_contain_number"] ?? true),
									"must_contain_special_character": (node_settings_password_policy["must_contain_special_character"] ?? true),
								})) (node_settings["password_policy"] ?? {})
							),
							"password_change": (
								((node_settings_password_change) => ({
									"cooldown_time": (node_settings_password_change["cooldown_time"] ?? 86400),
								})) (node_settings["password_change"] ?? {})
							),
							"name_index": (
								((node_settings_password_policy) => ({
									"veil": (node_settings_password_policy["veil"] ?? true),
									"salt": (node_settings_password_policy["salt"] ?? ""),
								})) (node_settings["name_index"] ?? {})
							),
							"connections": (
								((node_settings_connections) => ({
									"frontend_url_base": (node_settings_connections["frontend_url_base"] ?? null),
									"login_url": (node_settings_connections["login_url"] ?? null),
								})) (node_settings["connections"] ?? {})
							),
						})) (conf_raw["settings"] ?? {})
					),
					"admins": (conf_raw["admins"] ?? []),
					"outputs": (
						((node_outputs) => node_outputs.map(
							(output_description : {kind : string; data : any;}) => {
								const kind : string = output_description["kind"];
								const node_options_data_raw = (output_description["data"] ?? {});
								switch (kind) {
									case "authelia_file": {
										return {
											"kind": kind,
											"data": {
												"path": (node_options_data_raw["path"] ?? "/var/authelia/users.yaml"),
											}
										};
										break;
									}
									case "http": {
										return {
											"kind": kind,
											"data": {
												"scheme": (node_options_data_raw["scheme"] ?? "http"),
												"host": (node_options_data_raw["host"] ?? "localhost"),
												"path": (node_options_data_raw["path"] ?? ""),
												"method": (node_options_data_raw["method"] ?? "post"),
												"query": (node_options_data_raw["query"] ?? null),
												"headers": (node_options_data_raw["headers"] ?? {"Content-Type": "application/json"}),
											},
										};
										break;
									}
									case "arc": {
										return {
											"kind": kind,
											"data": {
												"http_scheme": (node_options_data_raw["scheme"] ?? "http"),
												"http_host": (node_options_data_raw["http_host"] ?? "localhost"),
												"http_port": (node_options_data_raw["http_port"] ?? 7463),
												"hash_salt": node_options_data_raw["hash_salt"],
											}
										};
										break;
									}
									default: {
										throw (new Error("unhandled"));
										break;
									}
								}
							}
						)) (conf_raw["outputs"] ?? [])
					),
				};
				break;
			}
			default: {
				throw (new Error("invalid conf version: " + conf_raw["version"]));
				break;
			}
		}
	}
	
	
	/**
	 * @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 {
			inject(conf_raw);
			// 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;
		}
	}
	
}
