namespace _heimdall.check_kinds.tls_certificate
{
	
	/**
	 */
	function parameters_schema(
	) : _heimdall.helpers.json_schema.type_schema
	{
		return {
			"type": "object",
			"additionalProperties": false,
			"properties": {
				"host": {
					"type": "string"
				},
				"port": {
					"type": "integer",
					"default": 443
				},
				"expiry_threshold_concerning": {
					"description": "in days; allowed amount of valid days before the certificate expires; threshold for condition 'concerning'; 'null' means 'report at no value'",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"minimum": 0
						},
					],
					"default": 7,
				},
				"expiry_threshold_critical": {
					"description": "in days; allowed amount of valid days before the certificate expires; threshold for condition 'critical'; 'null' means 'report at no value'",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"minimum": 0
						},
					],
					"default": 1,
				},
				"expiry_threshold": {
					"deprecated": true,
					"description": "",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"minimum": 0
						},
					],
					"default": null,
				},
				"strict": {
					"deprecated": true,
					"description": "",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "boolean",
						},
					],
					"default": null,
				},
			},
			"required": [
				"host",
			]
		};
	}
	
	
	/**
	 */
	function normalize_order_node(
		node : any
	) : any
	{
		const version : string = (
			(
				(! ("expiry_threshold_concerning" in node))
				&&
				(! ("expiry_threshold_critical" in node))
			)
			? "v1"
			: "v2"
		);
		
		switch (version) {
			default: {
				throw (new Error("unhandled version"));
				break;
			}
			case "v1": {
				if (! ("host" in node)) {
					throw new Error("missing mandatory field 'host'");
				}
				else {
					const node_ = Object.assign(
						{
							"port": 443,
							"expiry_threshold": 7,
							"strict": true,
						},
						node
					);
					return {
						"host": node_["host"],
						"port": node_["port"],
						"expiry_threshold_concerning": (
							node_["strict"]
							? null
							: node_["expiry_threshold"]
						),
						"expiry_threshold_critical": (
							node_["strict"]
							? node_["expiry_threshold"]
							: null
						),
					};
				}
				break;
			}
			case "v2": {
				if (! ("host" in node)) {
					throw new Error("missing mandatory field 'host'");
				}
				else {
					const node_ = Object.assign(
						{
							"port": 443,
							"expiry_threshold_concerning": 7,
							"expiry_threshold_critical": 1,
						},
						node
					);
					return node_;
				}
				break;
			}
		}
	}
	
	
	/**
	 */
	async function run(
		parameters
	) : Promise<_heimdall.type_result>
	{
		// TODO: outsource to parameters
		const timeout : float = 5.0;
		
		type type_stuff = {
			valid_from : int;
			valid_to : int;
		};
		
		// const nm_child_process = require("x509");
		const nm_tls = require("tls");
		const nm_ssl_checker = require("ssl-checker");
		
		let faults : Array<string> = [];
		let data : Record<string, any> = {};
		let condition : _heimdall.enum_condition = _heimdall.enum_condition.ok;
		let version : (null | string);
		
		const stuff : (null | type_stuff) = await (
			nm_ssl_checker(parameters["host"], {"port": parameters["port"]})
			.then(
				x => ({
					"valid_from": Math.floor((new Date(x["validFrom"])).getTime() / 1000),
					"valid_to": Math.floor((new Date(x["validTo"])).getTime() / 1000),
				})
			)
		);
		
		if (stuff === null) {
			faults.push(lib_plankton.translate.get("checks.tls_certificate.not_obtainable"));
			condition = _heimdall.enum_condition.critical;
			version = null;
		}
		else {
			version = "TLSv1.3";
			const current_timestamp : int = _heimdall.get_current_timestamp();
			const expiry_timestamp = stuff.valid_to;
			const days : int = Math.ceil((expiry_timestamp - current_timestamp) / (60 * 60 * 24));
			data = Object.assign(
				data,
				{
					"expiry_timestamp": expiry_timestamp,
					"days": days,
				}
			);
			if (
				(parameters["expiry_threshold_critical"] !== null)
				&&
				(days <= parameters["expiry_threshold_critical"])
			) {
				faults.push(lib_plankton.translate.get("checks.tls_certificate.expires_soon"));
				condition = _heimdall.enum_condition.critical;
			}
			else {
				if (
					(parameters["expiry_threshold_concerning"] !== null)
					&&
					(days <= parameters["expiry_threshold_concerning"])
				) {
					faults.push(lib_plankton.translate.get("checks.tls_certificate.expires_soon"));
					condition = _heimdall.enum_condition.concerning;
				}
				else {
					// no nothing
				}
			}
		}
		
		return Promise.resolve({
			"condition": condition,
			"info": {
				"host": parameters["host"],
				"port": parameters["port"],
				"faults": faults,
				"data": data,
			}
		});
	}
	
	
	/**
	 */
	register_implementation(
		"tls_certificate",
		{
			"parameters_schema": parameters_schema,
			"normalize_order_node": normalize_order_node,
			"run": run,
		}
	);
	
}
