/*
This file is part of »dali«.

Copyright 2025 'kcf' <fenris@folksprak.org>

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

»dali« 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with »dali«. If not, see <http://www.gnu.org/licenses/>.
 */


namespace _dali.widgets
{
	
	/**
	 */
	type type_entry = {
		id : _dali.type_calendar_id;
		name : string;
		hue : float;
		access_level : _dali.enum_access_level;
	};
	
	
	/**
	 */
	export class class_widget_sources implements lib_plankton.zoo_widget.interface_widget
	{
		
		/**
		 * [dependency]
		 */
		private get_entries : (() => Promise<Array<type_entry>>);
		
		
		/**
		 * [hook]
		 */
		private action_toggle : ((entry : type_entry, mode : boolean) => void);
		
		
		/**
		 * [hook]
		 */
		private action_select : ((entry : type_entry) => void);
		
		
		/**
		 * [hook]
		 */
		private action_add : (() => void);
		
		
		/**
		 * [state]
		 */
		private priviliged : boolean;
		
		
		/**
		 * [state]
		 */
		private container : (null | Element);
		
		
		/**
		 */
		public constructor(
			get_entries : (() => Promise<Array<type_entry>>),
			{
				"action_select": action_select = ((calendar_id) => {}),
				"action_toggle": action_toggle = ((calendar_id, mode) => {}),
				"action_add": action_add = (() => {}),
				"initial_priviliged": initial_priviliged = false,
			}
			:
			{
				action_select ?: ((entry : type_entry) => void);
				action_toggle ?: ((entry : type_entry, mode : boolean) => void);
				action_add ?: (() => void);
				initial_priviliged ?: boolean;
			}
			=
			{
			}
		)
		{
			// dependencies
			this.get_entries = get_entries;
			
			// hooks
			this.action_select = action_select;
			this.action_toggle = action_toggle;
			this.action_add = action_add;
			
			// state
			this.priviliged = initial_priviliged;
			this.container = null;
		}
		
		
		/**
		 */
		private static id_encode(
			id : _dali.type_calendar_id
		)
		: string
		{
			return id.toFixed(0);
		}
		
		
		/**
		 */
		private static id_decode(
			representation : string
		)
		: _dali.type_calendar_id
		{
			return parseInt(representation);
		}
		
		
		/**
		 */
		public async update(
			{
				"priviliged": priviliged = null,
			}
			:
			{
				priviliged ?: boolean;
			}
			=
			{
			}
		)
		: Promise<void>
		{
			if (priviliged === null)
			{
				// do nothing
			}
			else
			{
				this.priviliged = priviliged;
			}
			const data : lib_plankton.map.type_map<_dali.type_calendar_id, type_entry> = lib_plankton.map.hashmap.implementation_map(
				lib_plankton.map.hashmap.make(
					calendar_id => class_widget_sources.id_encode(calendar_id),
					{
						"pairs": (
							(await this.get_entries())
							.map(
								entry => (
									{
										"key": entry.id,
										"value": entry,
									}
								)
							)
						),
					}
				)
			);
			// structure
			{
				this.container.innerHTML = await _dali.helpers.template_coin(
					"widget-sources",
					"main",
					{
						"label_create": lib_plankton.translate.get("widget.sources.create"),
						"entries": (
							(
								await _dali.helpers.promise_row<string>(
									lib_plankton.map.dump(data)
									.map(
										(pair) => () => {
											return _dali.helpers.template_coin(
												"widget-sources",
												"entry",
												{
													"name": pair.value.name,
													// "access_level": entry.access_level, // TODO
													"color": _dali.helpers.event_color(pair.value.hue),
													"rel": class_widget_sources.id_encode(pair.key),
												}
											);
										}
									)
								)
							)
							.join("")
						),
					}
				);
				this.container.querySelector(".sources").classList.toggle("sources-priviliged", this.priviliged);
			}
			// listeners
			{
				this.container.querySelector(".sources-create").addEventListener(
					"click",
					(event) => {
						event.preventDefault();
						this.action_add();
					}
				);
				this.container.querySelectorAll(".sources-entry-visibility").forEach(
					(element) => {
						element.addEventListener(
							"change",
							() => {
								const mode : boolean = (element as HTMLInputElement).checked;
								const key_encoded : string = element.parentElement.getAttribute("rel");
								const calendar_id : _dali.type_calendar_id = class_widget_sources.id_decode(key_encoded);
								const entry : type_entry = data.get(calendar_id);
								element.parentElement.classList.toggle("sources-entry-hidden", (! mode));
								this.action_toggle(entry, mode);
							}
						);
					}
				);
				this.container.querySelectorAll(".sources-entry").forEach(
					(element) => {
						element.addEventListener(
							"click",
							(event) => {
								if ((event.target as Element).classList.contains("sources-entry-visibility"))
								{
									// do nothing
								}
								else
								{
									const key_encoded : string = element.getAttribute("rel");
									const calendar_id : _dali.type_calendar_id = class_widget_sources.id_decode(key_encoded);
									const entry : type_entry = data.get(calendar_id);
									this.action_select(entry);
								}
							}
						);
					}
				);
			}
		}
		
		
		/**
		 * [implementation]
		 */
		public async load(
			target_element : Element
		)
		: Promise<void>
		{
			this.container = target_element;
			await this.update();
		}
		
	}
	
}
