using System.Windows.Controls;
using System.Windows.Input;
using ConeCalorimeter.ViewModels;

namespace ConeCalorimeter.Views;

public partial class TestPageView : UserControl
{
    private readonly HashSet<string> _runningMomentaryActions = [];

    public TestPageView()
    {
        InitializeComponent();
    }

    private void DeviceActionButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (StartMomentaryAction(sender))
        {
            if (sender is Button button)
            {
                button.CaptureMouse();
            }

            e.Handled = true;
        }
    }

    private void DeviceActionButton_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (StopMomentaryAction(sender))
        {
            ReleaseInputCapture(sender);
            e.Handled = true;
        }
    }

    private void DeviceActionButton_MouseLeave(object sender, MouseEventArgs e)
    {
        if (StopMomentaryAction(sender))
        {
            ReleaseInputCapture(sender);
        }
    }

    private void DeviceActionButton_LostMouseCapture(object sender, MouseEventArgs e)
    {
        StopMomentaryAction(sender);
    }

    private void DeviceActionButton_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (StopMomentaryAction(sender))
        {
            ReleaseInputCapture(sender);
        }
    }

    private void DeviceActionButton_TouchDown(object sender, TouchEventArgs e)
    {
        if (StartMomentaryAction(sender))
        {
            if (sender is Button button)
            {
                button.CaptureTouch(e.TouchDevice);
            }

            e.Handled = true;
        }
    }

    private void DeviceActionButton_TouchUp(object sender, TouchEventArgs e)
    {
        if (StopMomentaryAction(sender))
        {
            ReleaseInputCapture(sender);
            e.Handled = true;
        }
    }

    private void DeviceActionButton_TouchLeave(object sender, TouchEventArgs e)
    {
        if (StopMomentaryAction(sender))
        {
            ReleaseInputCapture(sender);
        }
    }

    private void DeviceActionButton_LostTouchCapture(object sender, TouchEventArgs e)
    {
        StopMomentaryAction(sender);
    }

    private bool StartMomentaryAction(object sender)
    {
        if (!TryGetDeviceAction(sender, out var label, out var viewModel))
        {
            return false;
        }

        if (_runningMomentaryActions.Contains(label))
        {
            return true;
        }

        if (!viewModel.StartMomentaryDeviceAction(label))
        {
            return false;
        }

        _runningMomentaryActions.Add(label);
        return true;
    }

    private bool StopMomentaryAction(object sender)
    {
        if (!TryGetDeviceAction(sender, out var label, out var viewModel)
            || !_runningMomentaryActions.Remove(label))
        {
            return false;
        }

        return viewModel.StopMomentaryDeviceAction(label);
    }

    private bool TryGetDeviceAction(
        object sender,
        out string label,
        out TestPageViewModel viewModel)
    {
        label = string.Empty;
        viewModel = null!;

        if (sender is not Button { DataContext: DeviceActionViewModel action }
            || DataContext is not TestPageViewModel testPageViewModel)
        {
            return false;
        }

        label = action.Label;
        viewModel = testPageViewModel;
        return true;
    }

    private static void ReleaseInputCapture(object sender)
    {
        if (sender is not Button button)
        {
            return;
        }

        if (button.IsMouseCaptured)
        {
            button.ReleaseMouseCapture();
        }

        button.ReleaseAllTouchCaptures();
    }
}
