/*
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(
	"invitation_handle",
	async (parameters, target_element) => {
		async function set_state(
			state : ("load" | "fill" | "wait" | "error" | "success"),
			messages : Array<string> = []
		) : Promise<void>
		{
			target_element.querySelector(".invitation_handle").setAttribute("rel", state);
			target_element.querySelector(".invitation_handle-message").textContent = "";
			const class_ = (() => {
				switch (state)
				{
					case "load": return lib_plankton.zoo_widget.class_panel_info;
					case "wait": return lib_plankton.zoo_widget.class_panel_info;
					case "error": return lib_plankton.zoo_widget.class_panel_error;
					case "success": return lib_plankton.zoo_widget.class_panel_success;
					default: return lib_plankton.zoo_widget.class_panel;
				}
			}) ();
			const widget : lib_plankton.zoo_widget.interface_widget = (
				(messages.length <= 0)
				?
				new lib_plankton.zoo_widget.class_empty()
				:
				new class_(
					(
						(messages.length === 1)
						?
						new lib_plankton.zoo_widget.class_string(messages[0])
						:
						new lib_plankton.zoo_widget.class_list(
							messages
							.map(x => new lib_plankton.zoo_widget.class_string(x))
						)
					),
					{
						"collapseable": false,
						"collapsed_initial_value": false,
					}
				)
			);
			await widget.load(target_element.querySelector(".invitation_handle-message"));
		}
		
		// parameters
		const key : string = parameters["key"];
		
		update_nav({"mode": null});
		target_element.appendChild(_zackeneule.helpers.template_request("invitation_handle"));
		await set_state(
			"load",
			[
				lib_plankton.translate.get("common.loading"),
			]
		);
		
		target_element.querySelector(".invitation_handle-title").textContent = lib_plankton.translate.get("page.invitation_handle.title");
		
		let data : (
			null
			|
			{
				name_changeable : boolean;
				name_value : (null | string);
				label_changeable : boolean;
				label_value : (null | string);
				email_address_changeable : boolean;
				email_address_value : (null | string);
				groups_changeable : boolean;
				groups_value : Array<int>;
			}
		);
		try
		{
			data = await _zackeneule.backend.invitation_examine(key);
		}
		catch (error)
		{
			data = null;
		}
		
		if (data === null)
		{
			await set_state(
				"error",
				[
					lib_plankton.translate.get("page.invitation_handle.message.invalid"),
				]
			);
		}
		else
		{
			const password_policy : lib_plankton.password.type_policy = await _zackeneule.backend.password_policy();
			const group_data = await _zackeneule.logic.group_data();
			
			const form = new lib_plankton.zoo_form.class_form<
				{
					name : string;
					label : string;
					email_address : (null | string);
					groups : Array<int>;
					password_value : string;
					password_confirmation : string;
				},
				{
					name : string;
					label : string;
					email_address : string;
					groups : Array<int>;
					password_value : string;
					password_confirmation : string;
				}
			>(
				value => ({
					"name": value.name,
					"label": value.label,
					"email_address": (value.email_address ?? ""),
					"groups": value.groups,
					"password_value": value.password_value,
					"password_confirmation": value.password_confirmation,
				}),
				representation => ({
					"name": representation.name,
					"label": representation.label,
					"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),
									"pattern": "^[a-z0-9_\.]+$",
								}
							),
							"label": lib_plankton.translate.get("domain.member.name.label"),
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_list(
									lib_plankton.translate.get("domain.member.name.help")
									.split("\n\n")
									.map(x => new lib_plankton.zoo_widget.class_string(x))
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
						},
						{
							"name": "label",
							"input": new lib_plankton.zoo_input.class_input_text(
								{
									"read_only": (! data.label_changeable),
								}
							),
							"label": lib_plankton.translate.get("domain.member.label.label"),
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_list(
									lib_plankton.translate.get("domain.member.label.help")
									.split("\n\n")
									.map(x => new lib_plankton.zoo_widget.class_string(x))
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
						},
						{
							"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.label"),
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_list(
									lib_plankton.translate.get("domain.member.email_address.help")
									.split("\n\n")
									.map(x => new lib_plankton.zoo_widget.class_string(x))
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
						},
						{
							"name": "groups",
							"input": new lib_plankton.zoo_input.class_input_wrapped<Set<string>, Array<int>>(
								new lib_plankton.zoo_input.class_input_set(
									group_data.order.map(
										group_id => group_id.toFixed(0)
									),
									group_id_encoded => group_data.pool.get(parseInt(group_id_encoded)).label,
									{
										"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"),
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_list(
									(
										lib_plankton.translate.get("domain.member.groups.help")
										.split("\n\n")
										.map(x => new lib_plankton.zoo_widget.class_string(x))
									)
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
						},
						{
							"name": "password_value",
							"input": new lib_plankton.zoo_input.class_input_password(
								{
									"exhibit_initial_value": true,
								}
							),
							"label": lib_plankton.translate.get("page.invitation_handle.form.field.password_value.label"),
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_list(
									(
										lib_plankton.translate.get("page.invitation_handle.form.field.password_value.help")
										.split("\n\n")
										.map<lib_plankton.zoo_widget.interface_widget>(x => new lib_plankton.zoo_widget.class_string(x))
									)
									.concat(
										[
											new _zackeneule.widget.password_policy.class_password_policy(
												password_policy,
												{
													"title": "Richtlinien",
												}
											),
										]
									)
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
						},
						{
							"name": "password_confirmation",
							"input": new lib_plankton.zoo_input.class_input_password(
							),
							"label": lib_plankton.translate.get("page.invitation_handle.form.field.password_confirmation.label"),
							/*
							"help": new lib_plankton.zoo_widget.class_panel_info(
								new lib_plankton.zoo_widget.class_string(
									lib_plankton.translate.get("page.invitation_handle.form.field.password_confirmation.help")
								),
								{
									"collapseable": true,
									"collapsed_initial_value": true,
								}
							),
							 */
						},
					]
				),
				[
					{
						"label": lib_plankton.translate.get("page.invitation_handle.form.action.submit"),
						"procedure": async (get_value, get_representation) => {
							const value = await get_value();
							let flaws : Array<{incident : string; details : Record<string, any>;}>;
							await set_state(
								"wait",
								[
									lib_plankton.translate.get("common.checking"),
								]
							);
							if (value.password_value !== value.password_confirmation)
							{
								flaws = [
									{"incident": "password_mismatch", "details": {}},
								];
							}
							else
							{
								try
								{
									const flaws_ = await _zackeneule.backend.invitation_accept(
										key,
										{
											"label": value.label,
											"name": value.name,
											"email_address": value.email_address,
											"groups": value.groups,
											"password": value.password_value,
										}
									);
									flaws = (
										(
											flaws_
											.filter(
												flaw => (! flaw.incident.startsWith("password_"))
											)
										)
										.concat(
											(flaws_.find(flaw => flaw.incident.startsWith("password_")) !== undefined)
											?
											[{"incident": "password_invalid", "details": {}}]
											:
											[]
										)
									);
								}
								catch (error)
								{
									flaws = [
										{"incident": "unhandled_error", "details": {}},
									];
								}
							}
							if (flaws.length > 0)
							{
								await set_state(
									"error",
									flaws.map(
										flaw => lib_plankton.string.coin(
											lib_plankton.translate.get("page.invitation_handle.flaw." + flaw.incident),
											flaw.details
										)
									)
								);
							}
							else
							{
								await set_state(
									"success",
									[
										lib_plankton.translate.get("page.invitation_handle.message.successful"),
									]
								);
							}
						},
					}
				]
			);
			await form.setup(target_element.querySelector(".invitation_handle-form") as HTMLElement);		
			form.input_write(
				{
					"name": data.name_value,
					"label": data.label_value,
					"email_address": data.email_address_value,
					"groups": data.groups_value,
					"password_value": lib_plankton.password.generate(password_policy),
					"password_confirmation": "",
				}
			);
			set_state(
				"fill",
				[
				]
			);
		}
	}
);
