import { ActivityLog } from "./Components/ActivityLog";
import { EndpointsProvider } from "../EndpointsProvider";
import { Paginator } from "../Utils/Paginator";
import { Scheduler } from "../Utils/Scheduler";

export class ActivityLogs {

	/**
	 * Instance variables.
	 */
	private CurrentPage: number = 1;
	private CurrentLimit: number = 25;
	private CurrentCategory: number = 0;
	private CurrentUser = document.querySelector<HTMLElement>("#activity-log-rows-container").dataset.user;
	private Loader = document.querySelector<HTMLElement>("#activity-log-loader");
	private CategorySelect = document.querySelector<HTMLInputElement>("#category-select");
	private IsProcessing = false;
	private Paginators: Paginator[] = [];

	/**
	 * Setting up event listeners for paginators and category changes.
	 */
	public constructor() {

		for (const paginator of Array.from(document.querySelectorAll<HTMLElement>("pagination"))) {
			const newPaginator = new Paginator(paginator);
			this.HookPaginatorEvents(newPaginator);
			this.Paginators.push(newPaginator);
		}

		this.HookCategoryEvent();

		this.LoadActivityLogs(
			this.CurrentPage,
			this.CurrentLimit,
			this.CurrentCategory,
			this.CurrentUser,
		);

	}

	/**
	 * Paginator event handlers that updates the current page based on interaction from the user.
	 * @param paginator 
	 */
	private HookPaginatorEvents(paginator: Paginator) {
		paginator.OnPagePrev(pageNumber => {
			this.CurrentPage = pageNumber;
			this.LoadActivityLogs(
				pageNumber,
				this.CurrentLimit,
				this.CurrentCategory,
				this.CurrentUser,
			)
		});

		paginator.OnPageNext(pageNumber => {
			this.CurrentPage = pageNumber;
			this.LoadActivityLogs(
				pageNumber,
				this.CurrentLimit,
				this.CurrentCategory,
				this.CurrentUser,
			)
		});

		paginator.OnPageManuallyEntered(pageNumber => {
			this.CurrentPage = pageNumber;
			this.LoadActivityLogs(
				pageNumber,
				this.CurrentLimit,
				this.CurrentCategory,
				this.CurrentUser,
			)
		});
	}
	/**
	 * Category event handler that updates the category when changed.
	 */
	private HookCategoryEvent() {
		this.CategorySelect.addEventListener("change", e => {
			document.querySelector<HTMLInputElement>("input[name='paginator-current-page']").value = "1";
			this.LoadActivityLogs(
				1,
				this.CurrentLimit,
				parseInt(this.CategorySelect.value),
				this.CurrentUser,
			);
		});
	}

	/**
	 * Loads Activity Logs based on current informaton, i.e page number and category.
	 * @param page 
	 * @param limit 
	 * @param category 
	 * @param user 
	 * @returns 
	 */
	private async LoadActivityLogs(page: number, limit: number, category: number, user: string): Promise<void> {
		if (this.IsProcessing) {
			return;
		}

		ActivityLog.ActivityLogsContainer.innerHTML = "";

		this.IsProcessing = true;
		this.Loader.style.display = "block";
		this.CurrentPage = page;
		this.CurrentLimit = limit;
		this.CurrentCategory = category;
		this.CurrentUser = user;

		const urlParams = new URLSearchParams();
		urlParams.set("limit", String(limit));
		urlParams.set("page", String(page));
		urlParams.set("category", String(category));
		urlParams.set("user", user);

		const response = await fetch(`${EndpointsProvider.EndPoints.ActivityLogs}?${urlParams.toString()}`, {
			cache: "no-cache",
			credentials: "same-origin",
			method: "get",
		});

		await Scheduler.Wait(150);

		let data;
		try {
			data = await response.json();
		} catch (jsonSyntaxError) {
			alert(jsonSyntaxError);
			return;
		}

		this.Loader.style.display = "none";

		if (data.status === 1) {
			// Set paginator stuff
			for (const paginator of this.Paginators) {
				paginator.SetMaxPages(data.totalPages);
			}

			for (const activityLog of data.activityLogs) {
				new ActivityLog(
					activityLog.id,
					activityLog.categoryID,
					activityLog.userID,
					activityLog.timestamp,
					activityLog.jsonData,
					activityLog.username,
					activityLog.categoryDescription,
					activityLog.timeAgo,
				);
			}

			if (data.activityLogs.length === 0) {
				document.querySelector<HTMLElement>("#no-logs-to-display-message").style.display = "block";
			} else {
				document.querySelector<HTMLElement>("#no-logs-to-display-message").style.display = "none";
			}
		} else if (data.status === -1) {
			alert(data.error);
		}

		this.IsProcessing = false;
	}
}

new ActivityLogs();