namespace _heimdall.check_kinds.file_state
{
	
	/**
	 */
	function parameters_schema(
	) : _heimdall.helpers.json_schema.type_schema
	{
		return {
			"type": "object",
			"additionalProperties": false,
			"properties": {
				"path": {
					"type": "string"
				},
				"exist_mode": {
					"description": "whether the file is supposed to exist or not",
					"type": "boolean",
					"default": true,
				},
				"exist_critical": {
					"description": "whether a violation of the extist state (parameter 'exist_mode') shall be considered as critical (true) or concerning (false)",
					"type": "boolean",
					"default": true,
				},
				"age_threshold_concerning": {
					"description": "in seconds; ignored if 'exist_mode' is set to false",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
				"age_threshold_critical": {
					"description": "in seconds; ignored if 'exist_mode' is set to false",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
				"size_threshold_concerning": {
					"description": "in bytes; ignored if 'exist_mode' is set to false",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
				"size_threshold_critical": {
					"description": "in bytes; ignored if 'exist_mode' is set to false",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
				
				// deprecated
				"strict": {
					"deprecated": true,
					"description": "",
					"type": "boolean",
					"default": true,
				},
				"exist": {
					"deprecated": true,
					"description": "",
					"type": "boolean",
					"default": true,
				},
				"age_threshold": {
					"deprecated": true,
					"description": "",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
				"size_threshold": {
					"deprecated": true,
					"description": "",
					"anyOf": [
						{
							"type": "null",
						},
						{
							"type": "integer",
							"exclusiveMinimum": 0,
						},
					],
					"default": null,
				},
			},
			"required": [
				"path",
			]
		};
	}
	
	
	/**
	 */
	function normalize_order_node(
		node : any
	) : any
	{
		const version : string = (
			(! ("exist_mode" in node))
			? "v1"
			: "v2"
		);
		
		switch (version) {
			default: {
				throw (new Error("unhandled version"));
				break;
			}
			case "v1": {
				if (! ("path" in node)) {
					throw new Error("missing mandatory field 'path'");
				}
				else {
					const node_ = Object.assign(
						{
							"strict": true,
							"exist": true,
							"age_threshold": null,
							"size_threshold": null,
						},
						node
					);
					return {
						"path": node["path"],
						"exist_mode": node_["exist"],
						"exist_critical": node_["strict"],
						"age_threshold_concerning": (
							node_["strict"]
							? null
							: node_["age_threshold"]
						),
						"age_threshold_critical": (
							node_["strict"]
							? node_["age_threshold"]
							: null
						),
						"size_threshold_concerning": (
							node_["strict"]
							? null
							: node_["age_threshold"]
						),
						"size_threshold_critical": (
							node_["strict"]
							? node_["age_threshold"]
							: null
						),
					};
				}
				break;
			}
			case "v2": {
				if (! ("path" in node)) {
					throw new Error("missing mandatory field 'path'");
				}
				else {
					const node_ = Object.assign(
						{
							"exist_mode": true,
							"exist_critical": true,
							"age_threshold_concerning": null,
							"age_threshold_critical": null,
							"size_threshold_concerning": null,
							"size_threshold_critical": null,
						},
						node
					);
					return node_;
				}
				break;
			}
		}
	}
	
	
	/**
	 */
	async function run(
		parameters
	) : Promise<_heimdall.type_result>
	{
		const nm_fs = require("fs");
		
		let condition : _heimdall.enum_condition = _heimdall.enum_condition.ok;
		let faults : Array<string> = [];
		let data : Record<string, any> = {};
		
		let exists : boolean;
		let stats : {
			ctime : float;
			size : int;
		};
		await new Promise<void>(
			(resolve, reject) => {
				nm_fs.stat(
					parameters["path"],
					{
						"bigint": false,
					},
					(err, stats_) => {
						if (err) {
							exists = false;
							stats = null;
							resolve(undefined);
						}
						else {
							exists = true;
							stats = stats_;
							resolve(undefined);
						}
					}
				);
			}
		);
		if (! parameters["exist_mode"]) {
			if (exists) {
				condition = (
					parameters["exist_critical"]
					? _heimdall.enum_condition.concerning
					: _heimdall.enum_condition.critical
				);
				faults.push(lib_plankton.translate.get("checks.file_state.exists"));
			}
			else {
				// do nothing
			}
		}
		else {
			if (! exists) {
				condition = (
					parameters["exist_critical"]
					? _heimdall.enum_condition.concerning
					: _heimdall.enum_condition.critical
				);
				faults.push(lib_plankton.translate.get("checks.file_state.missing"));
			}
			else {
				// age
				{
					const timestamp_this : int = _heimdall.get_current_timestamp();
					const timestamp_that : int = Math.floor(stats.ctime);
					const age : int = (timestamp_this - timestamp_that);
					if (age < 0) {
						condition = _heimdall.enum_condition.critical;
						faults.push(lib_plankton.translate.get("checks.file_state.timestamp_implausible"));
					}
					else {
						if (
							(parameters["age_threshold_critical"] !== null)
							&&
							(age > parameters["age_threshold_critical"])
						) {
							condition = _heimdall.enum_condition.critical;
							faults.push(lib_plankton.translate.get("checks.file_state.too_old"));
						}
						else {
							if (
								(parameters["age_threshold_concerning"] !== null)
								&&
								(age > parameters["age_threshold_concerning"])
							) {
								condition = _heimdall.enum_condition.critical;
								faults.push(lib_plankton.translate.get("checks.file_state.too_old"));
							}
							else {
								// do nothing
							}
						}
					}
					data = Object.assign(
						data,
						{
							"timestamp_of_checking_instance": timestamp_this,
							"timestamp_of_file": timestamp_that,
							"age_value_in_seconds": age,
							"age_threshold_in_seconds_concerning": parameters["age_threshold_concerning"],
							"age_threshold_in_seconds_critical": parameters["age_threshold_critical"],
						}
					);
				}
				// size
				{
					const size : int = stats.size;
					if (size < 0) {
						condition = _heimdall.enum_condition.critical;
						faults.push(lib_plankton.translate.get("checks.file_state.size_implausible"));
					}
					else {
						if (
							(parameters["size_threshold_critical"] !== null)
							&&
							(size > parameters["size_threshold_critical"])
						) {
							condition = _heimdall.enum_condition.critical;
							faults.push(lib_plankton.translate.get("checks.file_state.too_big"));
						}
						else {
							if (
								(parameters["size_threshold_concerning"] !== null)
								&&
								(size > parameters["size_threshold_concerning"])
							) {
								condition = _heimdall.enum_condition.critical;
								faults.push(lib_plankton.translate.get("checks.file_state.too_big"));
							}
							else {
								// do nothing
							}
						}
					}
					data = Object.assign(
						data,
						{
							"size_value_in_bytes": size,
							"size_threshold_in_bytes": parameters["size_threshold"],
						}
					);
				}
			}
		}
		return {
			"condition": condition,
			"info": {
				"path": parameters["path"],
				"faults": faults,
				"data": data,
			}
		};
	}
	
	
	/**
	 */
	register_implementation(
		"file_state",
		{
			"parameters_schema": parameters_schema,
			"normalize_order_node": normalize_order_node,
			"run": run,
		}
	);
	
}
