namespace _espe.helpers
{
	
	/**
	 */
	/*
	export function yaml_encode(
		thing : any
	) : string
	{
	}
	 */
	
	
	/**
	 * @todo outsource
	 */
	export async function bcrypt_compute(
		input : string,
		options : {
			rounds ?: int;
		} = {}
	) : Promise<string>
	{
		options = Object.assign(
			{
				"rounds": 12,
			},
			options
		);
		const nm_bcrypt = require("bcrypt");
		const salt : string = await nm_bcrypt.genSalt(options.rounds)
		const result : string = await nm_bcrypt.hash(input, salt);
		return result;
	}
	
	
	/**
	 * @todo outsource
	 */
	export async function bcrypt_compare(
		password_shall_image : string,
		password_is : string
	) : Promise<boolean>
	{
		const nm_bcrypt = require("bcrypt");
		const result = await nm_bcrypt.compare(password_is, password_shall_image);
		return result;
	}
	
	
	/**
	 * @deprecated
	 */
	export function database_implementation(
	) : lib_plankton.database.type_database
	{
		return _espe.database.get_implementation();
	}
	
	
	/**
	 */
	export async function verification_get(
		data : any
	) : Promise<string>
	{
		const secret : (null | string) = _espe.conf.get().general.verification_secret;
		if (secret === null) {
			return Promise.reject<string>(new Error("no verification secret specified; add in conf as 'general.verification_secret'!"));
		}
		else {
			return lib_plankton.sha256.get(
				lib_plankton.json.encode(data),
				secret
			);
		}
	}
	
	
	/**
	 */
	export async function verification_check(
		data : any,
		verification : string
	) : Promise<boolean>
	{
		const secret : (null | string) = _espe.conf.get().general.verification_secret;
		if (secret === null) {
			return Promise.reject<boolean>(new Error("no verification secret specified; add in conf as 'general.verification_secret'!"));
		}
		else {
			const verification_expected : string = lib_plankton.sha256.get(
				lib_plankton.json.encode(data),
				secret
			);
			return (verification === verification_expected);
		}
	}
	
	
	/**
	 * @todo outsource?
	 */
	async function email_send_real(
		smtp_credentials : {
			host : string;
			port : int;
			username : string;
			password : string;
		},
		receivers : Array<string>,
		subject : string,
		content : string,
		options : {
			sender ?: (null | string);
		} = {}
	) : Promise<void>
	{
		options = Object.assign(
			{
				"sender": /*null*/"admin@example.org",
			},
			options
		);
		lib_plankton.log.info(
			"email_send_real",
			{
				"receivers": receivers,
				"subject": subject,
			}
		);
		const nm_nodemailer = require("nodemailer");
		const transporter = nm_nodemailer.createTransport(
			{
				"host": smtp_credentials.host,
				"port": smtp_credentials.port,
				"secure": false,
				"auth": {
					"user": smtp_credentials.username,
					"pass": smtp_credentials.password,
				},
				"debug": true,
			}
		);
		const info = await transporter.sendMail(
			{
				"from": (options.sender ?? ""),
				"to": receivers.join(", "),
				"subject": subject,
				"text": content,
			}
		)
	}
	
	
	/**
	 */
	export async function email_send(
		receivers : Array<string>,
		subject : string,
		content : string
	) : Promise<void>
	{
		const mode : string = _espe.conf.get().email_sending.kind;
		lib_plankton.log.info(
			"email_send",
			{
				"mode": mode,
				"receivers": receivers,
				"subject": subject,
			}
		);
		switch (mode) {
			case "regular": {
				if (_espe.conf.get().email_sending.data["smtp_credentials"] === null) {
					return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
				}
				else {
					return email_send_real(
						_espe.conf.get().email_sending.data["smtp_credentials"],
						receivers,
						subject,
						content,
						{
							"sender": _espe.conf.get().email_sending.data["sender"],
						}
					);
				}
				break;
			}
			case "redirect": {
				if (_espe.conf.get().email_sending.data["smtp_credentials"] === null) {
					return Promise.reject<void>("no smtp credentials specified; add in conf as 'email_sending.data.smtp_credentials'!");
				}
				else {
					return email_send_real(
						_espe.conf.get().email_sending.data["smtp_credentials"],
						[_espe.conf.get().email_sending.data["target"]],
						lib_plankton.string.coin(
							"[REDIRECTION] {{receivers}} | {{original_subject}}",
							{
								"receivers": receivers.join(", "),
								"original_subject": subject
							}
						),
						content,
						{
							"sender": _espe.conf.get().email_sending.data["sender"],
						}
					);
				}
				break;
			}
			case "console": {
				lib_plankton.log.info(
					"email_send_content",
					{
						"content": content,
					}
				);
				break;
			}
			case "drop": {
				// do nothing
				break;
			}
			default: {
				throw (new Error("unhandled email mode: " + mode));
				break;
			}
		}
	}
	
}
