namespace _heimdall.state_repository
{
	
	/**
	 */
	var _connection : (null | lib_plankton.sqlite.type_connection) = null;
	
	
	/**
	 */
	function condition_decode(
		condition_encoded : int
	) : _heimdall.enum_condition
	{
		return {
			0: enum_condition.unknown,
			1: enum_condition.ok,
			2: enum_condition.concerning,
			3: enum_condition.critical,
		}[condition_encoded];
	}
	
	
	/**
	 */
	function condition_encode(
		condition : _heimdall.enum_condition
	) : int
	{
		switch (condition) {
			case enum_condition.unknown: return 0;
			case enum_condition.ok: return 1;
			case enum_condition.concerning: return 2;
			case enum_condition.critical: return 3;
		}
	}
	
	
	/**
	 */
	export async function init(
		database_path : string
	) : Promise<void>
	{
		_connection = await lib_plankton.sqlite.get_connection(database_path);
		await setup();
	}
	
	
	/**
	 */
	export async function kill(
	) : Promise<void>
	{
		await lib_plankton.sqlite.drop_connection(_connection);
		_connection = null;
	}
	
	
	/**
	 */
	export async function setup(
	) : Promise<void>
	{
		const result = await lib_plankton.sqlite.query_set(
			_connection,
			{
				"template": "CREATE TABLE IF NOT EXISTS results(check_name TEXT NOT NULL, timestamp INTEGER NOT NULL, condition TEXT NOT NULL, notification_sent BOOLEAN NOT NULL, info TEXT NOT NULL);",
				"arguments": {
				},
			},
		);
	}
	
	
	/**
	 */
	export async function clean(
		time_to_live : int,
		erase_state : boolean
	) : Promise<int>
	{
		const result = await lib_plankton.sqlite.query_put(
			_connection,
			{
				"template": "DELETE FROM results WHERE ((timestamp < :timestamp_min) OR :erase_state);",
				"arguments": {
					"timestamp_min": Math.floor((Date.now() / 1000) - time_to_live),
					"erase_state": erase_state,
				},
			}
		);
		return result.affected;
	}
	
	
	/**
	 */
	export async function probe(
		check_name : string,
		threshold : int
	) : Promise<
		Array<
			{
				timestamp : int;
				condition : _heimdall.enum_condition;
				notification_sent : boolean;
			}
		>
	>
	{
		const rows : Array<Record<string, any>> = await lib_plankton.sqlite.query_get(
			_connection,
			{
				"template": "SELECT timestamp, condition, notification_sent FROM results WHERE (check_name = :check_name) ORDER BY timestamp DESC LIMIT :limit;",
				"arguments": {
					"check_name": check_name,
					"limit": threshold,
				},
			}
		);
		return (
			rows
			.map(
				row => ({
					"timestamp": row["timestamp"],
					"condition": condition_decode(row["condition"]),
					"notification_sent": row["notification_sent"],
				})
			)
		);
	}
	
	
	/**
	 */
	export async function get_last_notification_timestamp(
		check_name : string
	) : Promise<(null | int)>
	{
		const rows : Array<Record<string, any>> = await lib_plankton.sqlite.query_get(
			_connection,
			{
				"template": "SELECT MAX(timestamp) AS max_timestamp FROM results WHERE (check_name = :check_name) AND (notification_sent = TRUE);",
				"arguments": {
					"check_name": check_name,
				},
			}
		);
		return rows[0]["max_timestamp"];
	}
	
	
	/**
	 */
	export async function feed(
		check_name : string,
		timestamp : int,
		condition : _heimdall.enum_condition,
		shall_send_notification : boolean,
		info : any
	) : Promise<void>
	{
		await lib_plankton.sqlite.query_put(
			_connection,
			{
				"template": "INSERT INTO results(check_name, timestamp, condition, notification_sent, info) VALUES (:check_name, :timestamp, :condition, :notification_sent, :info);",
				"arguments": {
					"check_name": check_name,
					"timestamp": timestamp,
					"condition": condition_encode(condition),
					"notification_sent": shall_send_notification,
					"info": lib_plankton.json.encode(info),
				}
			}
		);
	}
	
}
