#pragma warning disable 1998
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ITVisions.Blazor
{

 public enum LogType
 {
  info, warn, error
 }
 /// <summary>
 /// Hilfsklasse für Blazor WebAssembly und Blazor Server
 /// </summary>
 public partial class BlazorUtil
 {
  IJSRuntime _jsRuntime { get; set; }
  private NavigationManager NavigationManager { get; set; } = null;
  private IHttpContextAccessor httpContextAccessor { get; set; } = null;

  // DI
  public BlazorUtil(IJSRuntime jsRuntime, NavigationManager NavigationManager, IHttpContextAccessor httpContextAccessor)
  {
   _jsRuntime = jsRuntime;
   this.NavigationManager = NavigationManager;
   this.httpContextAccessor = httpContextAccessor;
  }

  public bool IsWebAssembly => _jsRuntime.GetType().FullName.Contains("WebAssembly");
  public bool IsBlazorServer => !IsWebAssembly;


  public string GetBlazorVersionInfo()
  {
   string blazorType = "unknown";
   string blazorVersion = "";
   if (_jsRuntime != null)
   {
    if (IsWebAssembly)
    {
     blazorType = "Blazor WebAssembly";
    }
    if (_jsRuntime.GetType().FullName.Contains("Server"))
    {
     blazorType = "Blazor Server";
    }
    blazorVersion = _jsRuntime.GetType().Assembly.GetName().Version.ToString();
   }

   // Version of .NET Core or Mono
   string runtime = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;

   return blazorType + (!String.IsNullOrEmpty(blazorVersion) ? " v" + blazorVersion : "") + " @ " + runtime;
  }

  public string GetASPNETVersion()
  {
   var ass = System.Reflection.Assembly.GetAssembly(typeof(Microsoft.AspNetCore.Components.IComponent));
   var vers = ass.GetCustomAttributes(typeof(System.Reflection.AssemblyInformationalVersionAttribute), false);
   if (vers.Length == 0) return "n/a";
   return ((System.Reflection.AssemblyInformationalVersionAttribute)vers[0]).InformationalVersion;
  }

  public async void Log(string s, object o)
  {
   s = s + ": " + ObjectToString(o);
   Log(s);
  }

  public async void Warn(string s, object o)
  {
   s = s + ": " + ObjectToString(o);
   Log(s, LogType.warn);
  }

  public async void Error(string s, object o)
  {
   s = s + ": " + ObjectToString(o);
   Log(s, LogType.error);
  }

  private static string ObjectToString(object o)
  {
   string s;
   if (o == null) return "(null)";
   // Aufbereitung für Ausgabe
   if (o.GetType().IsPrimitive || o is string) s = o.ToString();
   else s = o.GetType().Name + " {" + o.ToNameValueString(attributeSeparator: ";") + "}";
   return s;
  }

  public async void Log(object o)
  {
   Log(ObjectToString(o));
  }

  public async void Log(string s, LogType typ = LogType.info)
  {
   if (IsWebAssembly) 
   { // Blazor Webassembly!
    Console.WriteLine(typ.ToString() + ": " + s); return;
    //await _jsRuntime.InvokeAsync<string>("console." + typ.ToString(), "LOG: " + s);
   }
   else // Blazor Server
   {
    try
    {
     await _jsRuntime.InvokeAsync<string>("console." + typ.ToString(), "LOG: " + s);
    }
    catch (Exception)
    {
     // mache nichts, es kann in Blazor Server sein, dass die JSRuntime noch nicht verfügbar ist!
    }
   }
  }

  public async Task SetTitle(string text)
  {
   if (_jsRuntime == null) return;
   Log("SetTitle " + text);
   await _jsRuntime.InvokeVoidAsync("SetTitle", text);
  }

  public async ValueTask Alert(string text)
  {
   if (_jsRuntime == null) return;
   Log("Alert");
   await _jsRuntime.InvokeAsync<bool>("ShowAlert", text);
  }


  /// <summary>
  /// Zeige einen Browser-Dialog "confirm"
  /// </summary>
  /// <param name="text1">Zeile 1</param>
  /// <param name="text2">Zeile 2</param>
  /// <returns></returns>
  public async ValueTask<bool> Confirm(string text1, string text2 = "")
  {
   if (_jsRuntime == null) return false;
   Log("Confirm");
   return await _jsRuntime.InvokeAsync<bool>("ShowConfirm", text1, text2);
  }

  public async Task<string> GetCookiesAsString()
  {
   if (_jsRuntime == null) return null;
   var s = await _jsRuntime.InvokeAsync<string>("getCookie");
   return s;
  }

  public async Task<SortedDictionary<string, string>> GetCookies()
  {
   var r = new SortedDictionary<string, string>();
   var s = await GetCookiesAsString();
   if (String.IsNullOrEmpty(s)) return r;
   var cookies = s.Split(';');
   foreach (var cookie in cookies)
   {
    var cookieNameWert = cookie.Split('=');
    r.Add(cookieNameWert[0].Trim(), cookieNameWert[1].Trim());
   }
   return r;
  }
 }
}