/**
 */
namespace _zeitbild.frontend_web.backend
{
	
	/**
	 */
	var _data_chest : (
		null
		|
		lib_plankton.storage.type_chest<string, string, void, string, string>
	) = null;
	
	
	/**
	 */
	export async function init(
	) : Promise<void>
	{
		_data_chest = lib_plankton.storage.localstorage.implementation_chest(
			{
				"corner": "zeitbild",
			}
		);
		return Promise.resolve<void>(undefined);
	}
	
	
	/**
	 */
	async function get_session_key(
	) : Promise<(null | string)>
	{
		try {
			return (await _data_chest.read("session_key"));
		}
		catch (error) {
			return null;
		}
	}
	
	
	/**
	 */
	export async function is_logged_in(
	) : Promise<boolean>
	{
		return ((await get_session_key()) !== null);
	}
	
	
	/**
	 */
	async function call(
		method : lib_plankton.http.enum_method,
		action : string,
		input : (null | any)
	) : Promise<any>
	{
		const with_body : boolean = (
			[
				lib_plankton.http.enum_method.post,
				lib_plankton.http.enum_method.put,
				lib_plankton.http.enum_method.patch,
			].includes(method)
		);
		const session_key : (null | string) = await get_session_key();
		const http_request : lib_plankton.http.type_request = {
			"version": "HTTP/2",
			"scheme": (
				(_zeitbild.frontend_web.conf.get()["backend"]["scheme"] === "http")
				?
				"http"
				:
				"https"
			),
			"host": lib_plankton.string.coin(
				"{{host}}:{{port}}",
				{
					"host": _zeitbild.frontend_web.conf.get()["backend"]["host"],
					"port": _zeitbild.frontend_web.conf.get()["backend"]["port"].toFixed(0),
				}
			),
			"path": lib_plankton.string.coin(
				"{{base}}{{action}}",
				{
					"base": _zeitbild.frontend_web.conf.get()["backend"]["path"],
					"action": action,
				}
			),
			"method": method,
			"query": (
				(with_body || (input === null))
				?
				null
				:
				("?" + lib_plankton.www_form.encode(input))
			),
			"headers": Object.assign(
				{},
				(
					(! with_body)
					?
					{}
					:
					{"Content-Type": "application/json"}
				),
				(
					(session_key === null)
					?
					{}
					:
					{"X-Session-Key": session_key}
				)
			),
			"body": (
				((! with_body) || (input === null))
				?
				null
				:
				/*Buffer.from*/(lib_plankton.json.encode(input))
			),
		};
		const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(http_request);
		if (
			! (
				(http_response.status_code >= 200)
				&&
				(http_response.status_code < 300)
			)
		) {
			return Promise.reject<any>(http_response.body.toString());
		}
		else {
			const output : any = lib_plankton.json.decode(http_response.body.toString());
			return Promise.resolve<any>(output);
		}
	}
	
	
	/**
	 */
	export async function session_prepare(
	) : Promise<{kind : string; data : any;}>
	{
		return call(
			lib_plankton.http.enum_method.get,
			"/session/prepare",
			{
			}
		);
	}
	
	
	/**
	 */
	export function set_session_key(
		session_key : string
	) : Promise<void>
	{
		return (
			_data_chest.write("session_key", session_key)
			.then<void>(() => Promise.resolve<void>(undefined))
		);
	}
	
	/**
	 */
	export async function session_begin(
		name : string,
		password : string
	) : Promise<void>
	{
		const session_key : string = await call(
			lib_plankton.http.enum_method.post,
			"/session/begin",
			{
				"name": name,
				"password": password,
			}
		);
		await _data_chest.write("session_key", session_key);
		return Promise.resolve<void>(undefined);
	}
	
	
	/**
	 */
	export async function session_end(
	) : Promise<void>
	{
		await call(
			lib_plankton.http.enum_method.delete,
			"/session/end",
			null
		);
		await _data_chest.delete("session_key");
		return Promise.resolve<void>(undefined);
	}
	
	
	/**
	 */
	export async function calendar_list(
	) : Promise<
		Array<
			{
				key : _zeitbild.frontend_web.type.calendar_id;
				preview : {
					name : string;
				}
			}
		>
	>
	{
		return call(
			lib_plankton.http.enum_method.get,
			"/calendar",
			null
		);
	}
	
	
	/**
	 */
	export async function calendar_event_add(
		calendar_id : _zeitbild.frontend_web.type.calendar_id,
		event_object : _zeitbild.frontend_web.type.event_object
	) : Promise<void>
	{
		return call(
			lib_plankton.http.enum_method.post,
			lib_plankton.string.coin(
				"/calendar/{{calendar_id}}/event",
				{
					"calendar_id": calendar_id,
				}
			),
			event_object
		);
	}
	
	
	/**
	 * @todo event id type
	 */
	export async function calendar_event_remove(
		calendar_id : _zeitbild.frontend_web.type.calendar_id,
		event_id : int
	) : Promise<void>
	{
		return call(
			lib_plankton.http.enum_method.delete,
			lib_plankton.string.coin(
				"/calendar/{{calendar_id}}/event/{{event_id}}",
				{
					"calendar_id": calendar_id,
					"event_id": event_id,
				}
			),
			null
		);
	}
	
	
	/**
	 * @todo prevent loops
	 */
	export async function events(
		from_pit : _zeitbild.frontend_web.helpers.type_pit,
		to_pit : _zeitbild.frontend_web.helpers.type_pit,
		options : {
			calendar_ids ?: (null | Array<_zeitbild.frontend_web.type.calendar_id>);
		} = {}
	) : Promise<
		Array<
			{
				calendar_id : _zeitbild.frontend_web.type.calendar_id;
				calendar_name : string;
				event : _zeitbild.frontend_web.type.event_object;
			}
		>
	>
	{
		options = Object.assign(
			{
				"calendar_ids": null,
			},
			options
		);
		
		return call(
			lib_plankton.http.enum_method.get,
			"/events",
			Object.assign(
				{
					"from": from_pit,
					"to": to_pit,
				},
				(
					(options.calendar_ids === null)
					?
					{}
					:
					{"calendar_ids": options.calendar_ids.join(",")}
				)
			)
		);
	}

}
