/*
Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Frontend
Copyright (C) 2024 Christian Fraß

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public 
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later 
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see 
<https://www.gnu.org/licenses/>. 
 */

lib_plankton.zoo_page.register(
	"invite_handle",
	async (parameters, target_element) => {
		function set_state(
			state : ("load" | "fill" | "wait" | "done"),
			messages : Array<string> = []
		) : void
		{
			target_element.querySelector(".invite_handle").setAttribute("rel", state);
			target_element.querySelector(".invite_handle-message").textContent = "";
			let dom_list = document.createElement("ul");
			messages.forEach(
				message => {
					let dom_message = document.createElement("li");
					dom_message.textContent = message;
					dom_list.appendChild(dom_message);
				}
			);
			target_element.querySelector(".invite_handle-message").appendChild(dom_list);
		}
		
		// parameters
		const key : string = parameters["key"];
		
		update_nav({"mode": null});
		target_element.appendChild(template_request("invite_handle"));
		set_state(
			"load",
			[
			]
		);
		
		target_element.querySelector(".invite_handle-title").textContent = lib_plankton.translate.get("page.invite_handle.title");
		
		let data : (
			null
			|
			{
				name_changeable : boolean;
				name_value : (null | string);
				email_address_changeable : boolean;
				email_address_value : (null | string);
				groups_changeable : boolean;
				groups_value : Array<int>;
			}
		);
		try
		{
			data = await _espe.backend.invite_examine(key);
		}
		catch (error)
		{
			data = null;
		}
		
		if (data === null)
		{
			set_state(
				"done",
				[
					lib_plankton.translate.get("page.invite_handle.message.invalid"),
				]
			);
		}
		else
		{
			/**
			 * @todo cache
			 */
			const groups_as_array : Array<{id : int; name : string;}> = await _espe.backend.group_list();
			const groups_as_map : Map<int, {name : string;}> = new Map<int, {name : string;}>();
			for (const group_thingy of groups_as_array)
			{
				groups_as_map.set(group_thingy.id, {"name": group_thingy.name});
			}
			
			const form = new lib_plankton.zoo_form.class_form<
				{
					name : string;
					email_address : (null | string);
					groups : Array<int>;
					password_value : string;
					password_confirmation : string;
				},
				{
					name : string;
					email_address : string;
					groups : Array<int>;
					password_value : string;
					password_confirmation : string;
				}
			>(
				value => ({
					"name": value.name,
					"email_address": (value.email_address ?? ""),
					"groups": value.groups,
					"password_value": value.password_value,
					"password_confirmation": value.password_confirmation,
				}),
				representation => ({
					"name": representation.name,
					"email_address": representation.email_address,
					"groups": representation.groups,
					"password_value": representation.password_value,
					"password_confirmation": representation.password_confirmation,
				}),
				new lib_plankton.zoo_input.class_input_group(
					[
						{
							"name": "name",
							"input": new lib_plankton.zoo_input.class_input_text(
								{
									"read_only": (! data.name_changeable),
								}
							),
							"label": lib_plankton.translate.get("domain.member.name.label"),
						},
						{
							"name": "groups",
							/*
							"input": new lib_plankton.zoo_input.class_input_list(
								() => new lib_plankton.zoo_input.class_input_text(
									{
										"read_only": (! data.groups_changeable),
									}
								),
								{
									"read_only": (! data.groups_changeable),
								}
							),
							 */
							"input": new lib_plankton.zoo_input.class_input_wrapped<Set<string>, Array<int>>(
								new _espe.class_input_set(
									groups_as_array.map(
										group_thingy => group_thingy.id.toFixed(0)
									),
									group_id_encoded => groups_as_map.get(parseInt(group_id_encoded)).name,
									{
										"read_only": (! data.groups_changeable),
									}
								),
								(value_inner) => {
									const array : Array<int> = [];
									for (const group_id_encoded of value_inner)
									{
										array.push(parseInt(group_id_encoded));
									}
									return array;
								},
								(value_outer) => new Set<string>(value_outer.map(group_id => group_id.toFixed(0)))
							),
							"label": lib_plankton.translate.get("domain.member.groups.label"),
						},
						{
							"name": "email_address",
							"input": new lib_plankton.zoo_input.class_input_text(
								{
									"read_only": (! data.email_address_changeable),
								}
							),
							"label": lib_plankton.translate.get("domain.member.email_address_private.label"),
						},
						{
							"name": "password_value",
							"input": new lib_plankton.zoo_input.class_input_password(
							),
							"label": lib_plankton.translate.get("page.member_register.form.field.password_value.label"),
							"help": lib_plankton.translate.get("page.member_register.form.field.password_value.help"),
						},
						{
							"name": "password_confirmation",
							"input": new lib_plankton.zoo_input.class_input_password(
							),
							"label": lib_plankton.translate.get("page.member_register.form.field.password_confirmation.label"),
						},
					]
				),
				[
					{
						"label": lib_plankton.translate.get("page.invite_handle.form.action.submit"),
						"procedure": async (get_value, get_representation) => {
							const value = await get_value();
							let flaws : Array<{incident : string; details : Record<string, any>;}>;
							set_state(
								"wait",
								[
								]
							);
							if (value.password_value !== value.password_confirmation)
							{
								flaws = [
									{"incident": "password_mismatch", "details": {}},
								];
							}
							else
							{
								try
								{
									flaws = await _espe.backend.invite_accept(
										key,
										{
											"groups": value.groups,
											"name": value.name,
											"email_address": value.email_address,
											"password": value.password_value,
										}
									);
								}
								catch (error)
								{
									flaws = [
										{"incident": "unhandled_error", "details": {}},
									];
								}
							}
							if (flaws.length > 0)
							{
								set_state(
									"fill",
									flaws.map(
										flaw => lib_plankton.string.coin(
											lib_plankton.translate.get("page.member_register.flaw." + flaw.incident),
											flaw.details
										)
									)
								);
							}
							else
							{
								set_state(
									"done",
									[
										// lib_plankton.translate.get("page.member_register.success")
										lib_plankton.translate.get("page.invite_handle.message.successful"),
									]
								);
							}
						},
					}
				]
			);
			await form.setup(target_element.querySelector(".invite_handle-form") as HTMLElement);		
			form.input_write(
				{
					"name": data.name_value,
					"email_address": data.email_address_value,
					"groups": data.groups_value,
					"password_value": "",
					"password_confirmation": "",
				}
			);
			set_state(
				"fill",
				[
				]
			);
		}
	}
);
