using System.Diagnostics.CodeAnalysis;
using Connected.Annotations;
using Connected.Extensions;
using Connected.Services;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace Connected.Components;

public partial class Switch<T> : BooleanInput<T>
{
   protected string Classname =>
   new CssBuilder("switch")
      .AddClass($"disabled", Disabled)
      .AddClass($"readonly", ReadOnly)
      .AddClass(LabelPosition == LabelPosition.End ? "ltr" : "rtl", true)
      .AddClass(AdditionalClassList)
   .Build();

   protected string SwitchClassname =>
   new CssBuilder("button-root mud-icon-button mud-switch-base")
      .AddClass($"ripple mud-ripple-switch", !DisableRipple && !ReadOnly && !Disabled)
      .AddClass($"{Color.ToDescription()}-text hover:mud-{Color.ToDescription()}-hover", BoolValue == true)
      .AddClass($"{UnCheckedColor.ToDescription()}-text hover:mud-{UnCheckedColor.ToDescription()}-hover", BoolValue == false)
      .AddClass($"switch-disabled", Disabled)
      .AddClass($"readonly", ReadOnly)
      .AddClass($"checked", BoolValue)
   .Build();

   protected string TrackClassname =>
   new CssBuilder("switch-track")
      .AddClass($"{Color.ToDescription()}", BoolValue == true)
      .AddClass($"{UnCheckedColor.ToDescription()}", BoolValue == false)
   .Build();

   //Excluded because not used
   [ExcludeFromCodeCoverage]
   protected string SpanClassname =>
   new CssBuilder("switch-span mud-flip-x-rtl")
   .Build();

   private IKeyInterceptor _keyInterceptor;
   [Inject] private IKeyInterceptorFactory KeyInterceptorFactory { get; set; }

   /// <summary>
   /// The color of the component. It supports the theme colors.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Appearance)]
   public ThemeColor Color { get; set; } = ThemeColor.Default;

   /// <summary>
   /// The base color of the component in its none active/unchecked state. It supports the theme colors.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Radio.Appearance)]
   public ThemeColor UnCheckedColor { get; set; } = ThemeColor.Default;

   /// <summary>
   /// The text/label will be displayed next to the switch if set.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Behavior)]
   public string Label { get; set; }

   /// <summary>
   /// The position of the text/label.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Behavior)]
   public LabelPosition LabelPosition { get; set; } = LabelPosition.End;

   /// <summary>
   /// Shows an icon on Switch's thumb.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Appearance)]
   public string ThumbIcon { get; set; }

   /// <summary>
   /// The color of the thumb icon. Supports the theme colors.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Appearance)]
   public ThemeColor ThumbIconColor { get; set; } = ThemeColor.Default;

   /// <summary>
   /// If true, disables ripple effect.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.FormComponent.Appearance)]
   public bool DisableRipple { get; set; }

   protected internal void HandleKeyDown(KeyboardEventArgs obj)
   {
      if (Disabled || ReadOnly)
         return;
      switch (obj.Key)
      {
         case "ArrowLeft":
         case "Delete":
            SetBoolValueAsync(false);
            break;
         case "ArrowRight":
         case "Enter":
         case "NumpadEnter":
            SetBoolValueAsync(true);
            break;
         case " ":
            if (BoolValue == true)
            {
               SetBoolValueAsync(false);
            }
            else
            {
               SetBoolValueAsync(true);
            }
            break;
      }
   }

   private string _elementId = "switch_" + Guid.NewGuid().ToString().Substring(0, 8);

   protected override void OnInitialized()
   {
      base.OnInitialized();

      if (Label == null && For != null)
         Label = For.GetLabelString();
   }

   protected override async Task OnAfterRenderAsync(bool firstRender)
   {
      if (firstRender)
      {
         _keyInterceptor = KeyInterceptorFactory.Create();

         await _keyInterceptor.Connect(_elementId, new KeyInterceptorOptions()
         {
            //EnableLogging = true,
            TargetClass = "switch-base",
            Keys = {
                new KeyOptions { Key="ArrowUp", PreventDown = "key+none" }, // prevent scrolling page, instead increment
                     new KeyOptions { Key="ArrowDown", PreventDown = "key+none" }, // prevent scrolling page, instead decrement
                     new KeyOptions { Key=" ", PreventDown = "key+none", PreventUp = "key+none" },
             },
         });

         _keyInterceptor.KeyDown += HandleKeyDown;
      }
      await base.OnAfterRenderAsync(firstRender);
   }

   protected override void Dispose(bool disposing)
   {
      base.Dispose(disposing);

      if (disposing == true)
      {
         if (_keyInterceptor != null)
         {
            _keyInterceptor.KeyDown -= HandleKeyDown;
            _keyInterceptor.Dispose();
         }
      }
   }
}
