using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;

namespace Minint.Controls;

/// <summary>
/// Shows a TextBlock by default; switches to an inline TextBox on double-click.
/// Commits on Enter or focus loss, cancels on Escape.
/// </summary>
public class EditableTextBlock : Control
{
    public static readonly StyledProperty<string> TextProperty =
        AvaloniaProperty.Register<EditableTextBlock, string>(nameof(Text), defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);

    public string Text
    {
        get => GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    private readonly TextBlock _display;
    private readonly TextBox _editor;
    private bool _isEditing;

    public EditableTextBlock()
    {
        _display = new TextBlock
        {
            VerticalAlignment = VerticalAlignment.Center,
            TextTrimming = TextTrimming.CharacterEllipsis,
        };

        _editor = new TextBox
        {
            VerticalAlignment = VerticalAlignment.Center,
            Padding = new Thickness(2, 0),
            BorderThickness = new Thickness(1),
            MinWidth = 40,
            IsVisible = false,
        };

        LogicalChildren.Add(_display);
        LogicalChildren.Add(_editor);
        VisualChildren.Add(_display);
        VisualChildren.Add(_editor);

        _display.Bind(TextBlock.TextProperty, this.GetObservable(TextProperty).ToBinding());
        _editor.Bind(TextBox.TextProperty, this.GetObservable(TextProperty).ToBinding());

        _editor.KeyDown += OnEditorKeyDown;
        _editor.LostFocus += OnEditorLostFocus;
    }

    protected override void OnPointerPressed(PointerPressedEventArgs e)
    {
        base.OnPointerPressed(e);
        if (e.ClickCount == 2 && !_isEditing)
        {
            BeginEdit();
            e.Handled = true;
        }
    }

    private void BeginEdit()
    {
        _isEditing = true;
        _editor.Text = Text;
        _display.IsVisible = false;
        _editor.IsVisible = true;
        _editor.Focus();
        _editor.SelectAll();
    }

    private void CommitEdit()
    {
        if (!_isEditing) return;
        _isEditing = false;
        Text = _editor.Text ?? string.Empty;
        _editor.IsVisible = false;
        _display.IsVisible = true;
    }

    private void CancelEdit()
    {
        if (!_isEditing) return;
        _isEditing = false;
        _editor.Text = Text;
        _editor.IsVisible = false;
        _display.IsVisible = true;
    }

    private void OnEditorKeyDown(object? sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            CommitEdit();
            e.Handled = true;
        }
        else if (e.Key == Key.Escape)
        {
            CancelEdit();
            e.Handled = true;
        }
    }

    private void OnEditorLostFocus(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
    {
        CommitEdit();
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        _display.Measure(availableSize);
        _editor.Measure(availableSize);
        return _isEditing ? _editor.DesiredSize : _display.DesiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        var rect = new Rect(finalSize);
        _display.Arrange(rect);
        _editor.Arrange(rect);
        return finalSize;
    }
}
