using Blazored.LocalStorage;

using collAnon.Client.Services;

using decePubClient.Models;
using decePubClient.Services;

using Markdig;

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

using SocialPub.ClientModels;

using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Text.Json;
using System.Web;

namespace decePubClient.Extensions
{
	public static class ExtensionMethods
	{
		#region Navigation Manager

		public static NameValueCollection QueryString(this NavigationManager navigationManager) =>
				HttpUtility.ParseQueryString(new Uri(navigationManager.Uri).Query);

		public static string QueryString(this NavigationManager navigationManager, string key) =>
				navigationManager.QueryString()[key];

		public static T QueryString<T>(this NavigationManager navigationManager, string key)
		{
			var value = navigationManager.QueryString()[key];
			var converter = TypeDescriptor.GetConverter(typeof(T));
			if (converter.IsValid(value))
				return (T)Convert.ChangeType(value, typeof(T));
			else
				return default;
		}

		#endregion Navigation Manager

		#region Setups

		public static async Task SetDefaultCulture(this WebAssemblyHost host)
		{
			var culture = default(CultureInfo);
			try
			{
				var storage = host.Services.GetRequiredService<ILocalStorageService>();
				var publicCache = await storage.GetItemAsync<PublicCacheData>(nameof(PublicCacheData));
				if (publicCache is null)
				{
					publicCache = new();
					var status = host.Services.GetRequiredService<AppStatusService>();
					var browserLanguage = status.Language();
					if (browserLanguage.Contains("en"))
						browserLanguage = "en-GB";
					var appConfig = host.Services.GetRequiredService<AppConfiguration>();
					if (!string.IsNullOrEmpty(publicCache.PageSettings.CurrentLanguageCode) &&
									publicCache.PageSettings.CurrentLanguageCode.Contains("en"))
						publicCache.PageSettings.CurrentLanguageCode = "en-GB";
					culture = new(publicCache.PageSettings.CurrentLanguageCode ?? browserLanguage);
					publicCache.PageSettings.CurrentLanguageCode = culture.TwoLetterISOLanguageName;
					await storage.SetItemAsync(nameof(PublicCacheData), publicCache);
				}

				culture ??= new(publicCache.PageSettings.CurrentLanguageCode == "en" ? "en-GB" : publicCache.PageSettings.CurrentLanguageCode);
				CultureInfo.DefaultThreadCurrentCulture = culture;
				CultureInfo.DefaultThreadCurrentUICulture = culture;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				culture = new("en-GB");
				CultureInfo.DefaultThreadCurrentCulture = culture;
				CultureInfo.DefaultThreadCurrentUICulture = culture;
			}
		}

		#endregion Setups

		public static string GetLogLevelClass(this string logType) => logType switch
		{
			"Debug" => "has-text-grey",
			"Information" => "has-text-info",
			"Warning" => "has-text-warning-dark",
			"Error" => "has-text-danger",
			"Fatal" => "has-text-danger-dark",
			_ => string.Empty
		};


		#region Formats

		public static MarkdownPipeline Pipeline =>
				 new MarkdownPipelineBuilder().UseGenericAttributes().Build();

		public static string ToJson(this object value) =>
				 JsonSerializer.Serialize(value);

		public static string ToBase64PngImage(this string base64Image) =>
				$"data:image/png;base64,{base64Image}";

		#endregion Formats

		#region Models

		public static string ToString(this WebResult webResult, CoalescingStringLocalizer localizer) =>
				localizer["{0} - {1}", webResult.StatusCode, webResult.ErrorMessage];

		public static string Timeframe(this DateTime creationDate, CoalescingStringLocalizer localizer)
		{
			var timeframe = DateTime.Now - creationDate.ToLocalTime();
			switch ((int)timeframe.TotalHours)
			{
				case >= 24:
					return localizer["{0} day/s", (int)timeframe.TotalDays];

				case >= 1 and < 24:
					return localizer["{0} hour/s", (int)timeframe.TotalHours];

				case 0:
					return localizer["{0} minute/s", (int)timeframe.TotalMinutes];

				default:
					return string.Empty;
			}
		}

		public static AuthorizationPolicy IsAdminPolicy() =>
				new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
						.RequireClaim(Policies.IsAdmin, true.ToString().ToLower())
						.RequireClaim(Policies.IsUser, true.ToString().ToLower())
						.RequireClaim(Policies.IsModerator, true.ToString().ToLower())
						.Build();

		public static AuthorizationPolicy IsUserPolicy() =>
				new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
						.RequireClaim(Policies.IsUser, true.ToString().ToLower())
						.Build();

		public static AuthorizationPolicy IsUserModeratorPolicy() =>
				new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
						.RequireClaim(Policies.IsModerator, true.ToString().ToLower())
						.Build();

		#endregion
	}
}