using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;

using CommonHelpers.WASM;
using AFXUI;

namespace BookRegistry.Client.Shared {

//**************************************************************************************************
/// <summary>
/// Check-box control (application components lib.)
/// </summary>
public partial class ACheckBox: AComponent {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public ElementReference? InputElement { get; protected set; }
public ElementReference? LabelElement { get; protected set; }
//==================================================================================================

public static string? DefaultInputClasses;
public static string? DefaultInputStyle;
public static string? DefaultContainerStyle = "display: inline";
public static string? DefaultLabelClasses;
public static string? DefaultLabelStyle = "margin: 0";

[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public string? ContainerId { get; set; }
[Parameter] public string? ContainerClasses { get; set; }
[Parameter] public string? ContainerStyle_0 { get; set; } = DefaultContainerStyle;
[Parameter] public string? ContainerStyle { get; set; }
[Parameter] public string? InputId { get; set; }
[Parameter] public string? InputClasses_0 { get; set; } = DefaultInputClasses;
[Parameter] public string? InputClasses { get; set; }
[Parameter] public string? InputStyle_0 { get; set; } = DefaultInputStyle;
[Parameter] public string? InputStyle { get; set; }
[Parameter] public string? LabelId { get; set; }
[Parameter] public string? LabelClasses_0 { get; set; } = DefaultLabelClasses;
[Parameter] public string? LabelClasses { get; set; }
[Parameter] public string? LabelStyle_0 { get; set; } = DefaultLabelStyle;
[Parameter] public string? LabelStyle { get; set; }
[Parameter] public string? Title { get; set; }
[Parameter] public string? AccessKey { get; set; }
[Parameter] public int? TabIndex { get; set; }
[Parameter] public bool Enabled { get; set; } = true;
[Parameter] public bool InitialValue { get; set; }
[Parameter] public bool ToggleOnEnterKey { get; set; } = true;

[Parameter] public Action? ON_SetValue { get; set; }
[Parameter] public Action? ON_Input { get; set; }
[Parameter] public Action? ON_Click { get; set; }
[Parameter] public Action<KeyboardEventArgs>? ON_KeyDown { get; set; }

[Parameter] public EventCallback ON_SetValue_A { get; set; }
[Parameter] public EventCallback ON_Input_A { get; set; }
[Parameter] public EventCallback ON_Click_A { get; set; }
[Parameter] public EventCallback<KeyboardEventArgs> ON_KeyDown_A { get; set; }

[Parameter(CaptureUnmatchedValues=true)]
public Dictionary<string,object>? Attributes { get; set; }

//--------------------------------------------------------------------------------------------------

public bool Value {
   get => _Value_ = GetValue();
   set => SetValue( value );
}
bool GetValue() =>
   JS.Invoke<bool?>( "ACheckBox_GetValue", InputElement ) ?? false;
void DoSetValue(bool value) =>
   JS.Invoke( "ACheckBox_SetValue", InputElement, _Value_ = value );

//==================================================================================================

public bool SetValue(bool value)
{
   bool previousValue = GetValue();
   DoSetValue( value );
   OnSetValue_Invoke();
   return value;
}

public void Reset() =>
   SetValue( false );

public bool Toggle()
{
   bool newValue = !GetValue();
   DoSetValue( newValue );
   OnSetValue_Invoke();
   return newValue;
}

//--------------------------------------------------------------------------------------------------

public bool Focus() =>
   Enabled ? InputElement.Focus() : false;

public bool DeferredFocus() =>
   Enabled ? InputElement.DeferredFocus() : false;
public bool DeferredFocus(int milliseconds) =>
   Enabled ? InputElement.DeferredFocus( milliseconds ) : false;

//==================================================================================================

protected bool FlagValue => _Value_;

//--------------------------------------------------------------------------------------------------

protected string InputElement_EDClass =>
   Enabled ? "a_checkbox_EnabledINPUT" : "a_checkbox_DisabledINPUT";
protected string LabelElement_EDClass =>
   Enabled ? "a_checkbox_EnabledInputLABEL" : "a_checkbox_DisabledInputLABEL";

//--------------------------------------------------------------------------------------------------

protected override void On_FirstParametersSet() =>
   _Value_ = InitialValue;

//==================================================================================================

void InputElement_OnInput() =>
go_nt(()=>{
   HandleInputChanged();
   OnInput_Invoke();
});

void InputElement_OnClick(MouseEventArgs e) =>
go_nt(()=>{
   if ( Enabled )
      OnClick_Invoke( e );
});

void InputElement_OnKeyDown(KeyboardEventArgs e) =>
go_nt(()=>{
   if ( !Enabled )
      return;
   if ( UInput.IsPureKey( e, "+" ) )
      SetManually();
   else
   if ( UInput.IsPureKey( e, "-" ) ||
        UInput.IsPureKey( e, "Delete", "Del" ) )
      ResetManually();
   else
   if ( UInput.IsPureKey( e, "*" ) ||
        UInput.IsPureEnterKey( e ) && ToggleOnEnterKey )
      ToggleManually();
   OnKeyDown_Invoke( e );
});

//--------------------------------------------------------------------------------------------------

void HandleInputChanged()
{
   bool value = Value;
   OnSetValue_Invoke();
}

//--------------------------------------------------------------------------------------------------

void SetManually()
{
   bool previousValue = GetValue();
   SetValue( true );
   if ( previousValue != _Value_ )
      OnInput_Invoke();
}

void ResetManually()
{
   bool previousValue = GetValue();
   Reset();
   if ( previousValue != _Value_ )
      OnInput_Invoke();
}

void ToggleManually()
{
   Toggle();   
   OnInput_Invoke();
}

//==================================================================================================

public override bool IsEnabled =>
   Enabled && InputElement.IsEnabled();

//--------------------------------------------------------------------------------------------------

public override ElementReference? MainElement { get => InputElement; }
public override ElementReference? AdditionalElement { get => LabelElement; }

//==================================================================================================

public override bool Interop_Focus() =>
   Focus();
public override bool Interop_DeferredFocus() =>
   DeferredFocus();

//==================================================================================================

void OnSetValue_Invoke()
{
   ON_SetValue?.Invoke();
   ON_SetValue_A.InvokeAsync( null );
}
void OnInput_Invoke()
{
   ON_Input?.Invoke();
   ON_Input_A.InvokeAsync( null );
}
void OnClick_Invoke(MouseEventArgs e)
{
   ON_Click?.Invoke();
   ON_Click_A.InvokeAsync( e );
}
void OnKeyDown_Invoke(KeyboardEventArgs e)
{
   ON_KeyDown?.Invoke( e );
   ON_KeyDown_A.InvokeAsync( e );
}

//==================================================================================================

bool _Value_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // ACheckBox
//**************************************************************************************************

} // BookRegistry.Client.Shared
