using Connected.Enums;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace Connected;
internal class Navigation
{
	private const int MaxPagesOnList = 256;
	private readonly NavigationManager _navigationManager;

	[Inject]
	private IJSRuntime JS { get; set; }

	private List<string> _backPages;
	private List<string> _forwardPages;

	public Navigation(NavigationManager navigationManager)
	{
		_navigationManager = navigationManager;
		_backPages = new List<string>();
		_forwardPages = new List<string>();
	}

	/// <summary>
	/// Navigates to the specified url.
	/// </summary>
	/// <param name="url">The destination url (relative or absolute).</param>
	public async Task NavigateTo(string url, Target t=Target.Self)
	{
		string target = Helper.GetEnumDescription<Target>(t);
		if (!target.Equals("_self"))
		{
			if (!url.Equals(_navigationManager.Uri))
				_backPages.Add(_navigationManager.Uri);
			_navigationManager.NavigateTo(url);
		} else
		{
			if (JS is not null)
				await JS.InvokeVoidAsync("open", url, target.ToString());
		}
	}

	/// <summary>
	/// Returns true if it is possible to navigate to the previous url.
	/// </summary>
	private bool CanNavigateBack()
	{
		return (_backPages.Count > 1);
	}

	private bool CanNavigateForward()
	{
		return (_forwardPages.Count > 1);
	}

	private void UpdateBackPageList()
	{
		string url = _navigationManager.Uri;
		_backPages.Add(url);
		if (_backPages.Count() > MaxPagesOnList)
		{
			_backPages.RemoveAt(0);
		}
	}

	private string GetFromBackPageList()
	{
		string result = _backPages.Last();
		_backPages.RemoveAt(_backPages.Count()-1);
		return result;
	}

	private string GetFromForwardPageList()
	{
		string result = _forwardPages.Last();
		_forwardPages.RemoveAt(_forwardPages.Count() - 1);
		return result;
	}

	private void UpdateForwardPageList()
	{
		string url = _navigationManager.Uri;
		_forwardPages.Add(url);
		if (_forwardPages.Count() > MaxPagesOnList)
		{
			_forwardPages.RemoveAt(0);
		}
	}

	/// <summary>
	/// Navigates to the previous url if possible or does nothing if it is not.
	/// </summary>
	public async Task Back()
	{
		if (!CanNavigateBack()) return;
		var backPageUrl = GetFromBackPageList();
		UpdateForwardPageList();

		await NavigateTo(backPageUrl);
	}

	/// <summary>
	/// Navigates to the forward url if possible or does nothing if it is not.
	/// </summary>
	public async Task Forward()
	{
		if (!CanNavigateForward()) return;
		var forwardPageUrl = GetFromForwardPageList();
		UpdateBackPageList();

		await	NavigateTo(forwardPageUrl);
	}
}


