/*
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_get_entries = (
		(
			from_pit : lib_plankton.pit.type_pit,
			to_pit : lib_plankton.pit.type_pit,
			calendar_ids : Array<_dali.type_calendar_id>
		)
		=>
		Promise<Array<_dali.type_event_object_extended>>
	);
	
	
	/**
	 */
	export class class_widget_listview implements lib_plankton.zoo_widget.interface_widget
	{
		
		/**
		 * [dependency]
		 */
		private get_entries : type_get_entries;
		
		
		/**
		 * [hook]
		 */
		private action_select : (
			(
				event_key : _dali.type_event_key
			)
			=>
			void
		);
		
		
		/**
		 * [hook]
		 */
		private action_add : (
			(
			)
			=>
			void
		);
		
		
		/**
		 */
		private include_passed : boolean;
		
		
		/**
		 * [state]
		 */
		private container : (null | Element);
		
		
		/**
		 */
		public constructor(
			get_entries : type_get_entries,
			{
				"include_passed": include_passed = false,
				"action_select": action_select = ((event_key) => {}),
				"action_add": action_add = (() => {}),
			}
			:
			{
				include_passed ?: boolean;
				action_select ?: (
					(
						event_key : _dali.type_event_key
					)
					=>
					void
				);
				action_add ?: (
					(
					)
					=>
					void
				);
			}
			=
			{
				}
		)
		{
			// dependencies
			this.get_entries = get_entries;
			
			// hooks
			this.action_select = action_select;
			this.action_add = action_add;
			
			// state
			this.include_passed = include_passed;
			this.container = null;
		}
		
		
		/**
		 */
		public toggle_visibility(
			calendar_id : _dali.type_calendar_id,
			{
				"mode": mode = null,
			}
			:
			{
				mode ?: (null | boolean);
			}
			=
			{
			}
		)
		: void
		{
			this.container.querySelectorAll(".listview-entry").forEach(
				(element) => {
					const rel : string = element.getAttribute("rel");
					const parts : Array<string> = rel.split("/");
					const calendar_id_ : _dali.type_calendar_id = parseInt(parts[0]);
					if (! (calendar_id === calendar_id_))
					{
						// do nothing
					}
					else
					{
						element.classList.toggle(
							"listview-entry-hidden",
							((mode !== null) ? (! mode) : undefined)
						);
					}
				}
			);
		}
		
		
		/**
		 */
		public async update_entries(
		)
		: Promise<void>
		{
			// structure
			{
				const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now();
				const from_pit : lib_plankton.pit.type_pit = now_pit;
				const to_pit : lib_plankton.pit.type_pit = lib_plankton.pit.shift_week(now_pit, +4);
				const entries : Array<_dali.type_event_object_extended> = await this.get_entries(
					from_pit,
					to_pit,
					null
				);
				entries.sort(
					(x, y) => (
						lib_plankton.pit.from_datetime(x.event_object.begin)
						-
						lib_plankton.pit.from_datetime(y.event_object.begin)
					)
				);
				const dom_list : HTMLElement = this.container.querySelector(".listview-entries");
				dom_list.innerHTML = (
					(
						await _dali.helpers.promise_row<string>(
							entries
							.filter(
								(entry) => (
									this.include_passed
									?
									true
									:
									lib_plankton.pit.is_after(
										lib_plankton.pit.from_datetime(entry.event_object.begin),
										now_pit
									)
								)
							)
							.map(
								(entry) => () => _dali.helpers.template_coin(
									"widget-listview",
									"entry",
									{
										"name_value": entry.event_object.name,
										"calendar_value": entry.calendar_name,
										"when_value": lib_plankton.pit.timespan_format(
											entry.event_object.begin,
											entry.event_object.end,
											{
												"timezone_indicator": lib_plankton.translate.get("common.timezone_indicator"),
												"adjust_to_ce": true,
												"show_timezone": false,
											}
										),
										"location_label": lib_plankton.translate.get("event.location"),
										"location_extra_classes": (
											(entry.event_object.location === null)
											?
											" listview-entry-field-empty"
											:
											""
										),
										"location_value": (
											(entry.event_object.location === null)
											?
											"?"
											:
											entry.event_object.location
										),
										"link_label": lib_plankton.translate.get("event.link"),
										"link_extra_classes": (
											(entry.event_object.link === null)
											?
											" listview-entry-field-empty"
											:
											""
										),
										"link_value": (
											(entry.event_object.link === null)
											?
											"?"
											:
											entry.event_object.link
										),
										"link_action": lib_plankton.translate.get("common.open"),
										"description_label": lib_plankton.translate.get("event.description"),
										"description_extra_classes": (
											(entry.event_object.description === null)
											?
											" listview-entry-field-empty"
											:
											""
										),
										"description_value": (
											(entry.event_object.description === null)
											?
											"?"
											:
											entry.event_object.description
										),
										"raw": JSON.stringify(entry),
										"color": _dali.helpers.event_color(entry.hue),
										"rel": entry.key,
									},
								)
							)
						)
					)
					.join("")
				);
			}
			// listeners
			{
				this.container.querySelectorAll(".listview-entry").forEach(
					(element) => {
						element.addEventListener(
							"click",
							(event) => {
								if ((event.target as Element).nodeName === "A")
								{
									// do nothing
								}
								else
								{
									const event_key : string = element.getAttribute("rel");
									this.action_select(event_key);
								}
							}
						);
					}
				);
			}
		}
		
		
		/**
		 * [implementation]
		 */
		public async load(
			target_element : Element
		)
		: Promise<void>
		{
			this.container = target_element;
			
			// view
			{
				target_element.innerHTML = await _dali.helpers.template_coin(
					"widget-listview",
					"main",
					{
						"add_href": "",
						"add_label": lib_plankton.translate.get("widget.listview.add"),
						"add_extra_classes": (
							(! await _dali.is_logged_in())
							?
							" listview-add-hidden"
							:
							""
						),
						"entries": "",
					}
				);
			}
			
			// control
			{
				target_element.querySelector(".listview-add").addEventListener(
					"click",
					(event) => {
						event.preventDefault();
						this.action_add();
					}
				);
			}
			
			await this.update_entries();
			
			return Promise.resolve<void>(undefined);
		}
			
	}
	
}
