/**
 * Enum representing the location of the notifications
 * @readonly
 * @enum {string}
 */
const NotificationLocation = {
	TOPLEFT: "top-left",
	TOPCENTER: "top-center",
	TOPRIGHT: "top-right",
	BOTTOMLEFT: "bottom-left",
	BOTTOMCENTER: "bottom-center",
	BOTTOMRIGHT: "bottom-right",
};

/**
 * Enum representing notification types
 * @readonly
 * @enum {string}
 */
const NotificationType = {
	INFO: "info",
	ERROR: "error",
	WARN: "warn",
	SUCCESS: "success",
};

/**
 * Responsible for the notification system
 */
const notifications = {
	/** @type {NotificationLocation} */
	_location: NotificationLocation.BOTTOMLEFT,
	/** @type {NotificationLocation} */
	get location() {
		return this.location;
	},
	/** @type {NotificationLocation} */
	set location(location) {
		this._location = location;
	},

	// Notification Area Element
	_areaEl: null,

	// Dialog BG Element
	_dialogBGEl: null,
	// Dialog Element
	_dialogEl: null,

	/**
	 * Creates a simple notification for the user. Equivalent to alert()
	 *
	 * @param {string | HTMLElement} message Message to display to the user.
	 * @param {Object} options Extra options for the notification.
	 * @param {NotificationType} options.type Notification type
	 * @param {boolean} options.collapsed Whether notification is collapsed by default
	 * @param {number} options.timeout Timeout for the notification
	 */
	notify(message, options = {}) {
		defaultOpt(options, {
			type: NotificationType.INFO,
			collapsed: false,
			timeout: config.notificationTimeout,
		});

		const notificationEl = document.createElement("div");
		notificationEl.classList.add("notification", options.type);
		if (!options.collapsed) notificationEl.classList.add("expanded");
		notificationEl.title = new Date().toISOString();
		notificationEl.addEventListener("click", () =>
			notificationEl.classList.toggle("expanded")
		);

		const contentEl = document.createElement("div");
		contentEl.classList.add("notification-content");
		contentEl.innerHTML = message;

		notificationEl.append(contentEl);

		const closeBtn = document.createElement("button");
		closeBtn.classList.add("notification-closebtn");
		closeBtn.addEventListener("click", () => notificationEl.remove());

		notificationEl.append(closeBtn);

		if (
			config.notificationHighlightAnimationDuration &&
			config.notificationHighlightAnimationDuration > 0
		) {
			const notificationHighlightEl = document.createElement("div");
			notificationHighlightEl.style.animationDuration = `${config.notificationHighlightAnimationDuration}ms`;
			notificationHighlightEl.classList.add(
				"notification-highlight",
				`notification-${options.type}`
			);

			document.body.appendChild(notificationHighlightEl);
			setTimeout(() => {
				notificationHighlightEl.remove();
			}, config.notificationHighlightAnimationDuration);
		}

		this._areaEl.prepend(notificationEl);
		if (options.timeout)
			setTimeout(() => {
				if (this._areaEl.contains(notificationEl)) {
					notificationEl.remove();
				}
			}, options.timeout);
	},

	/**
	 * Creates a dialog box for the user with set options.
	 *
	 * @param {string} title The title of the dialog box to be displayed to the user.
	 * @param {string | HTMLElement} message The message to be displayed to the user.
	 * @param {Object} options Extra options for the dialog.
	 * @param {Array<{label: string, value: any}>} options.choices The choices to be displayed to the user.
	 */
	async dialog(title, message, options = {}) {
		defaultOpt(options, {
			// By default, it is a await notifications.dialogation dialog
			choices: [
				{label: "No", value: false},
				{label: "Yes", value: true},
			],
		});

		const titleEl = this._dialogEl.querySelector(".dialog-title");
		titleEl.textContent = title;

		const contentEl = this._dialogEl.querySelector(".dialog-content");
		contentEl.innerHTML = message;

		const choicesEl = this._dialogEl.querySelector(".dialog-choices");
		while (choicesEl.firstChild) {
			choicesEl.firstChild.remove();
		}

		return new Promise((resolve, reject) => {
			options.choices.forEach((choice) => {
				const choiceBtn = document.createElement("button");
				choiceBtn.textContent = choice.label;
				choiceBtn.addEventListener("click", () => {
					this._dialogBGEl.style.display = "none";
					this._dialogEl.style.display = "none";

					resolve(choice.value);
				});

				choicesEl.append(choiceBtn);
			});

			this._dialogBGEl.style.display = "flex";
			this._dialogEl.style.display = "block";
		});
	},
};
var k = 0;

window.addEventListener("DOMContentLoaded", () => {
	// Creates the notification area
	const notificationArea = document.createElement("div");
	notificationArea.classList.add(
		"notification-area",
		NotificationLocation.BOTTOMLEFT
	);

	notifications._areaEl = notificationArea;

	document.body.appendChild(notificationArea);

	// Creates the dialog box element
	const dialogBG = document.createElement("div");
	dialogBG.classList.add("dialog-bg");
	dialogBG.style.display = "none";

	const dialogEl = document.createElement("div");
	dialogEl.classList.add("dialog");
	dialogEl.style.display = "none";

	const titleEl = document.createElement("div");
	titleEl.classList.add("dialog-title");

	const contentEl = document.createElement("div");
	contentEl.classList.add("dialog-content");

	const choicesEl = document.createElement("div");
	choicesEl.classList.add("dialog-choices");

	dialogEl.append(titleEl);
	dialogEl.append(contentEl);
	dialogEl.append(choicesEl);

	dialogBG.append(dialogEl);

	notifications._dialogEl = dialogEl;
	notifications._dialogBGEl = dialogBG;

	document.body.appendChild(dialogBG);
});