namespace _dali.widgets.listview
{
	
	/**
	 */
	type type_entry = {
		calendar_id : _dali.type.calendar_id;
		calendar_name : string;
		access_level : _dali.type.enum_access_level;
		event_id : (null | _dali.type.local_resource_event_id);
		event_object : _dali.type.event_object;
	};
	
	
	/**
	 */
	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<type_entry>>
	);
	
	
	/**
	 */
	export class class_widget_listview extends _dali.class_widget
	{
		
		/**
		 */
		private get_entries : type_get_entries;
		
		
		/**
		 */
		private container : (null | Element);
		
		
		/**
		 */
		private action_select_event : (
			(
				calendar_id : _dali.type.calendar_id,
				access_level : _dali.type.enum_access_level,
				event_id : _dali.type.local_resource_event_id
			)
			=>
			void
		);
		
		
		/**
		 */
		private action_add : (
			(
			)
			=>
			void
		);
		
		
		/**
		 */
		public constructor(
			get_entries : type_get_entries,
			options : {
				action_select_event ?: (
					(
						calendar_id : _dali.type.calendar_id,
						access_level : _dali.type.enum_access_level,
						event_id : _dali.type.local_resource_event_id
					)
					=>
					void
				);
				action_add ?: (
					(
					)
					=>
					void
				);
			} = {}
		)
		{
			options = Object.assign(
				{
					"action_select_event": (calendar_id, access_level, event_id) => {},
					"action_select_add": () => {},
				},
				options
			);
			super();
			this.get_entries = get_entries;
			this.container = null;
			this.action_select_event = options.action_select_event;
			this.action_add = options.action_add;
		}
		
		
		/**
		 */
		public toggle_visibility(
			calendar_id : _dali.type.calendar_id
		) : 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");
					}
				}
			);
		}
		
		
		/**
		 * [implementation]
		 */
		public async load(
			target_element : Element
		) : Promise<void>
		{
			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<type_entry> = 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)
				)
			);
			
			// 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.backend.is_logged_in())
							?
							" listview-add-hidden"
							:
							""
						),
						"entries": (
							(
								await _dali.helpers.promise_row<string>(
									entries
									.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": lib_plankton.color.output_hex(
													lib_plankton.color.give_generic(
														(entry.calendar_id - 1),
														{
															"saturation": 0.375,
															"value": 0.375,
														}
													),
												),
												"rel": lib_plankton.string.coin(
													"{{calendar_id}}/{{event_id}}/{{access_level}}",
													{
														"calendar_id": entry.calendar_id.toFixed(0),
														"event_id": (
															(! (entry.event_id === null))
															?
															entry.event_id.toFixed(0)
															:
															"-"
														),
														"access_level": (() => {
															switch (entry.access_level) {
																case _dali.type.enum_access_level.none: return "none";
																case _dali.type.enum_access_level.view: return "view";
																case _dali.type.enum_access_level.edit: return "edit";
																case _dali.type.enum_access_level.admin: return "admin";
															}
														}) (),
													}
												),
											},
										)
									)
								)
							)
							.join("")
						),
					}
				);
			}
			
			// control
			{
				target_element.querySelector(".listview-add").addEventListener(
					"click",
					(event) => {
						event.preventDefault();
						this.action_add();
					}
				);
				target_element.querySelectorAll(".listview-entry").forEach(
					(element) => {
						element.addEventListener(
							"click",
							(event) => {
								if ((event.target as Element).nodeName === "A") {
									// do nothing
								}
								else {
									const rel : string = element.getAttribute("rel");
									const parts : Array<string> = rel.split("/");
									const calendar_id : _dali.type.calendar_id = parseInt(parts[0]);
									const event_id : (null | _dali.type.local_resource_event_id) = (
										parts[1] === "-"
										?
										null
										:
										parseInt(parts[1])
									);
									const access_level : _dali.type.enum_access_level = (() => {
										switch (parts[2]) {
											case "none": return _dali.type.enum_access_level.none;
											case "view": return _dali.type.enum_access_level.view;
											case "edit": return _dali.type.enum_access_level.edit;
											case "admin": return _dali.type.enum_access_level.admin;
										}
									}) ();
									this.action_select_event(
										calendar_id,
										access_level,
										event_id,
									);
								}
							}
						);
					}
				);
			}
			
			this.container = target_element.querySelector(".listview");
			
			return Promise.resolve<void>(undefined);
		}
			
	}
	
}
