using System.Globalization;
using Connected.Annotations;
using Connected.Extensions;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;

namespace Connected.Components;

public partial class Slider<T> : UIComponent
{
   protected string Classname =>
      new CssBuilder("slider")
         .AddClass($"slider-{Size.ToDescription()}")
         .AddClass($"slider-{Color.ToDescription()}")
         .AddClass("slider-vertical", Vertical)
         .AddClass(AdditionalClassList)
         .Build();

   protected string _value;
   protected string _min = "0";
   protected string _max = "100";
   protected string _step = "1";

   /// <summary>
   /// The minimum allowed value of the slider. Should not be equal to max.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Validation)]
   public T Min
   {
      get => Converter.ConvertBack(_min);
      set => _min = Converter.Convert(value);
   }

   /// <summary>
   /// The maximum allowed value of the slider. Should not be equal to min.
   /// </summary>
   /// 
   [Parameter]
   [Category(CategoryTypes.Slider.Validation)]
   public T Max
   {
      get => Converter.ConvertBack(_max);
      set => _max = Converter.Convert(value);
   }

   /// <summary>
   /// How many steps the slider should take on each move.
   /// </summary>
   /// 
   [Parameter]
   [Category(CategoryTypes.Slider.Validation)]
   public T Step
   {
      get => Converter.ConvertBack(_step);
      set => _step = Converter.Convert(value);
   }

   /// <summary>
   /// If true, the slider will be disabled.
   /// </summary>
   /// 
   [Parameter]
   [Category(CategoryTypes.Slider.Behavior)]
   public bool Disabled { get; set; } = false;

   /// <summary>
   /// Child content of component.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Behavior)]
   public RenderFragment ChildContent { get; set; }

   [Parameter]
   [Category(CategoryTypes.Slider.Behavior)]
   public ToStringConverter<T> Converter { get; set; } = new DefaultConverter<T>() { Culture = CultureInfo.InvariantCulture };

   [Parameter] public EventCallback<T> ValueChanged { get; set; }

   [Parameter]
   [Category(CategoryTypes.Slider.Data)]
   public T Value
   {
      get => Converter.ConvertBack(_value);
      set
      {
         var d = Converter.Convert(value);
         if (_value == d)
            return;
         _value = d;
         ValueChanged.InvokeAsync(value);
      }
   }

   /// <summary>
   /// The color of the component. It supports the Primary, Secondary and Tertiary theme colors.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Appearance)]
   public ThemeColor Color { get; set; } = ThemeColor.Primary;

   protected string Text
   {
      get => _value;
      set
      {
         if (_value == value)
            return;
         _value = value;
         ValueChanged.InvokeAsync(Value);
      }
   }

   /// <summary>
   /// If true, the dragging the slider will update the Value immediately.
   /// If false, the Value is updated only on releasing the handle.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Behavior)]
   public bool Immediate { get; set; } = true;

   /// <summary>
   /// If true, displays the slider vertical.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Appearance)]
   public bool Vertical { get; set; } = false;

   /// <summary>
   /// If true, displays tick marks on the track.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Appearance)]
   public bool TickMarks { get; set; } = false;

   /// <summary>
   /// Labels for tick marks, will attempt to map the labels to each step in index order.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Appearance)]
   public string[] TickMarkLabels { get; set; }

   /// <summary>
   /// Labels for tick marks, will attempt to map the labels to each step in index order.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Slider.Appearance)]
   public Size Size { get; set; } = Size.Small;

   /// <summary>
   /// The variant to use.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Button.Appearance)]
   public Variant Variant { get; set; } = Variant.Text;

   /// <summary>
   /// Displays the value over the slider thumb.
   /// </summary>
   [Parameter]
   [Category(CategoryTypes.Button.Appearance)]
   public bool ValueLabel { get; set; }

   private int _tickMarkCount = 0;
   protected override void OnParametersSet()
   {
      if (TickMarks)
      {
         var min = Convert.ToDouble(Min);
         var max = Convert.ToDouble(Max);
         var step = Convert.ToDouble(Step);

         _tickMarkCount = 1 + (int)((max - min) / step);
      }
   }

   private double CalculatePosition()
   {
      var min = Convert.ToDouble(Min);
      var max = Convert.ToDouble(Max);
      var value = Convert.ToDouble(Value);
      var result = 100.0 * (value - min) / (max - min);

      result = Math.Min(Math.Max(0, result), 100);

      return Math.Round(result, 2);
   }
}
