/*
This file is part of »zeitbild«.

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

»zeitbild« 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.

»zeitbild« 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 »zeitbild«. If not, see <http://www.gnu.org/licenses/>.
 */


/**
 */
namespace _zeitbild
{

	
	/**
	 */
	export function access_level_to_string(
		access_level : _zeitbild.enum_access_level
	)
	: string
	{
		switch (access_level)
		{
			case _zeitbild.enum_access_level.none: {return "none";}
			case _zeitbild.enum_access_level.view: {return "view";}
			case _zeitbild.enum_access_level.edit: {return "edit";}
			case _zeitbild.enum_access_level.admin: {return "admin";}
			default: {throw (new Error("invalid access level: " + String(access_level)));}
		}
	}
	
	
	/**
	 */
	export function access_level_from_string(
		representation : string
	)
	: _zeitbild.enum_access_level
	{
		switch (representation)
		{
			case "none": {return _zeitbild.enum_access_level.none;}
			case "view": {return _zeitbild.enum_access_level.view;}
			case "edit": {return _zeitbild.enum_access_level.edit;}
			case "admin": {return _zeitbild.enum_access_level.admin;}
			default: {throw (new Error("invalid encoded access level: " + String(representation)));}
		}
	}
	
	
	/**
	 */
	export function access_level_order(
		x : _zeitbild.enum_access_level,
		y : _zeitbild.enum_access_level
	)
	: boolean
	{
		const list : Array<_zeitbild.enum_access_level> = [
			_zeitbild.enum_access_level.none,
			_zeitbild.enum_access_level.view,
			_zeitbild.enum_access_level.edit,
			_zeitbild.enum_access_level.admin,
		];
		return (list.indexOf(x) <= list.indexOf(y));
	}
	

	/**
	 */
	export function access_level_determine_raw(
		public_ : boolean,
		access_level_attributed : (
			null
			|
			{
				default : _zeitbild.enum_access_level,
				group : Array<_zeitbild.enum_access_level>;
				user : (null | _zeitbild.enum_access_level);
			}
		)
	)
	: _zeitbild.enum_access_level
	{
		return lib_plankton.call.convey(
			_zeitbild.enum_access_level.none,
			[
				// if public
				(x : _zeitbild.enum_access_level) => (
					public_
					?
					_zeitbild.enum_access_level.view
					:
					x
				),
				// if logged in
				(x : _zeitbild.enum_access_level) => (
					(access_level_attributed === null)
					?
					x
					:
					lib_plankton.call.convey(
						x,
						[
							// default
							(y : _zeitbild.enum_access_level) => access_level_attributed.default,
							// group
							(y : _zeitbild.enum_access_level) => (
								lib_plankton.call.null_prop(
									lib_plankton.list.max<_zeitbild.enum_access_level, _zeitbild.enum_access_level>(
										access_level_attributed.group,
										z => z,
										{
											"compare_value": _zeitbild.access_level_order,
										}
									),
									z => z.value
								)
								??
								y
							),
							// user
							(y : _zeitbild.enum_access_level) => (
								(access_level_attributed.user === null)
								?
								y
								:
								access_level_attributed.user
							),
						]
					)
				),
			]
		);
	}
	
	
	/**
	 */
	export function access_level_determine(
		calendar_object : _zeitbild.type_calendar_object,
		user : (
			null
			|
			{
				id : _zeitbild.type_user_id;
				object : _zeitbild.type_user_object;
			}
		)
	)
	: _zeitbild.enum_access_level
	{
		return access_level_determine_raw(
			calendar_object.access.public,
			(
				(user === null)
				?
				null
				:
				{
					"default": calendar_object.access.default_level,
					"group": (
						user.object.groups
						.map<(null | _zeitbild.enum_access_level)>(
							group_id => (
								calendar_object.access.attributed_group.has(group_id)
								?
								calendar_object.access.attributed_group.get(group_id)
								:
								null
							)
						)
						.filter(
							x => (x !== null)
						)
					),
					"user": (
						lib_plankton.call.try_catch_wrap<_zeitbild.enum_access_level>(
							() => calendar_object.access.attributed_user.get(user.id)
						).value
					)
				}
			)
		);
	}
	
}
