@using Sandbox
@using Sandbox.UI
@inherits Panel

@namespace MenuProject.Settings

<root class="@(Rebinding ? "rebinding" : "") @(!string.IsNullOrEmpty(TargetKey) ? "with-highlight" : "")">
    @{
        var str = MenuUtility.Input.GetBind( BindGroup, Action.Name, Slot, out var isDefault );

        // First slot should always be assigned
        if ( str == null && Slot == 0 )
        {
            str = Action.KeyboardCode;
            isDefault = true;
        }
    }

    @if ( !string.IsNullOrEmpty( str ) )
    {
        var keys = GetGlyphKeys( str ).ToList();
        @for ( int i = 0; i < keys.Count; i++ )
        {
            <Image Texture="@Input.Keyboard.GetGlyph( keys[i], InputGlyphSize.Medium, false )" />
            @if ( i < keys.Count - 1 )
            {
                <label class="plus">+</label>
            }
        }
    }
    else
    {
        <label>Not Set</label>
    }
</root>

@code {
    [Parameter]
    public InputAction Action { get; set; }

    [Parameter]
    public string BindGroup { get; set; }

    [Parameter]
    public int Slot { get; set; }

    private bool Rebinding { get; set; }
    private string TargetKey { get; set; }

    /// Utility method to split the A + X + F string into a container
    public IEnumerable<string> GetGlyphKeys( string input )
    {
        if ( string.IsNullOrEmpty( input ) )
            yield break;

        var keys = input.Split( new[] { " + " }, StringSplitOptions.RemoveEmptyEntries );
        foreach ( var key in keys )
        {
            yield return key.Trim();
        }
    }

    protected override int BuildHash()
    {
        return HashCode.Combine( TargetKey );
    }

    protected override void OnMouseUp( MousePanelEvent e )
    {
        if ( e.MouseButton == MouseButtons.Left )
        {
            Rebinding = true;
            TargetKey = null;
            StateHasChanged();

            MenuUtility.Input.TrapButtons( (buttons) =>
            {
                if ( buttons.Contains( "escape", StringComparer.OrdinalIgnoreCase ) )
                {
                    Cancel();
                    return;
                }

                TargetKey = string.Join( " + ", buttons.OrderBy( x => x ) );
                Apply();
            });
        }

        if ( e.MouseButton == MouseButtons.Right )
        {
            MenuUtility.Input.SetBind( BindGroup, Action.Name, null, Slot );
            TargetKey = null;
            CreateEvent( "onchange" );
            StateHasChanged();
        }
    }

    public void Apply()
    {
        if ( string.IsNullOrEmpty( TargetKey ) )
            return;

        MenuUtility.Input.SetBind( BindGroup, Action.Name, TargetKey, Slot );

        TargetKey = null;
        Rebinding = false;

        CreateEvent( "onchange" );
        StateHasChanged();
    }

    public void Cancel()
    {
        Rebinding = false;
        TargetKey = null;
        CreateEvent( "onchange" );
        StateHasChanged();
    }
}
