using Connected.Extensions;
using Connected.Utilities.BindingConverters;
using Microsoft.AspNetCore.Components;

namespace Connected.Components;

public partial class RangeInput<T> : InputBase<Range<T>>
{
   private string _textStart, _textEnd;

   public RangeInput()
   {
      Value = new Range<T>();
      SetConverter(new RangeConverter<T>());
   }

   protected string Classname => InputCssHelper.GetClassname(this,
      () => !string.IsNullOrEmpty(Text) || Adornment == Adornment.Start || !string.IsNullOrWhiteSpace(PlaceholderStart) || !string.IsNullOrWhiteSpace(PlaceholderEnd));

   /// <summary>
   /// Type of the input element. It should be a valid HTML5 input type.
   /// </summary>
   [Parameter] public InputType InputType { get; set; } = InputType.Text;

   internal override InputType GetInputType() => InputType;

   protected string InputClassname => InputCssHelper.GetInputClassname(this);

   protected string AdornmentClassname => InputCssHelper.GetAdornmentClassname(this);

   /// <summary>
   /// The short hint displayed in the start input before the user enters a value.
   /// </summary>
   [Parameter] public string PlaceholderStart { get; set; }

   /// <summary>
   /// The short hint displayed in the end input before the user enters a value.
   /// </summary>
   [Parameter] public string PlaceholderEnd { get; set; }

   protected string InputTypeString => InputType.ToDescription();

   /// <summary>
   /// ChildContent of the MudInput will only be displayed if InputType.Hidden and if its not null.
   /// </summary>
   [Parameter] public RenderFragment ChildContent { get; set; }

   private ElementReference _elementReferenceStart, _elementReferenceEnd;

   /// <summary>
   /// Custom separator icon, leave null for default.
   /// </summary>
   [Parameter] public string SeparatorIcon { get; set; } = Icons.Material.Filled.ArrowRightAlt;

   /// <summary>
   /// Focuses the start input of MudRangeInput
   /// </summary>
   /// <returns></returns>
   public ValueTask FocusStartAsync() => _elementReferenceStart.FocusAsync();

   /// <summary>
   /// Selects the start text of MudRangeInput
   /// </summary>
   /// <returns></returns>
   public ValueTask SelectStartAsync() => _elementReferenceStart.SelectAsync();

   /// <summary>
   /// Selects the specified range of the start text
   /// </summary>
   /// <param name="pos1">Start position of the selection</param>
   /// <param name="pos2">End position of the selection</param>
   /// <returns></returns>
   public ValueTask SelectRangeStartAsync(int pos1, int pos2) => _elementReferenceStart.SelectRangeAsync(pos1, pos2);

   /// <summary>
   /// Focuses the end input of MudRangeInput
   /// </summary>
   /// <returns></returns>
   public ValueTask FocusEndAsync() => _elementReferenceEnd.FocusAsync();

   /// <summary>
   /// Selects the end text of MudRangeInput
   /// </summary>
   /// <returns></returns>
   public ValueTask SelectEndAsync() => _elementReferenceEnd.SelectAsync();

   /// <summary>
   /// Selects the specified range of the end text
   /// </summary>
   /// <param name="pos1">Start position of the selection</param>
   /// <param name="pos2">End position of the selection</param>
   /// <returns></returns>
   public ValueTask SelectRangeEndAsync(int pos1, int pos2) => _elementReferenceEnd.SelectRangeAsync(pos1, pos2);

   public string TextStart
   {
      get => _textStart;
      set
      {
         if (_textStart == value)
            return;
         _textStart = value;
         SetTextAsync(RangeConverter<T>.Join(_textStart, _textEnd)).AndForget();
      }
   }

   public string TextEnd
   {
      get => _textEnd;
      set
      {
         if (_textEnd == value)
            return;
         _textEnd = value;
         SetTextAsync(RangeConverter<T>.Join(_textStart, _textEnd)).AndForget();
      }
   }

   protected override async Task UpdateTextPropertyAsync(bool updateValue)
   {
      await base.UpdateTextPropertyAsync(updateValue);

      RangeConverter<T>.Split(Text, out _textStart, out _textEnd);
   }

   protected override async Task UpdateValuePropertyAsync(bool updateText)
   {
      await base.UpdateValuePropertyAsync(updateText);

      RangeConverter<T>.Split(Text, out _textStart, out _textEnd);
   }
}
