using System.Numerics;
using Voile.Input;

namespace Voile.UI;

/// <summary>
/// Input information for UI elements.
/// </summary>
public class UIInputContext
{
    /// <summary>
    /// Current action handled by this <see cref="UIElement"/>.
    /// </summary>
    public IInputAction Action { get; }
    /// <summary>
    /// Current mouse position.
    /// </summary>
    public Vector2 MousePosition { get; }
    /// <summary>
    /// Determines if a left mouse button was pressed.
    /// </summary>
    public bool MousePressed { get; set; }
    /// <summary>
    /// Determines if a left mouse button was released.
    /// </summary>
    public bool MouseReleased { get; set; }
    /// <summary>
    /// Determines if a left mouse button is currently held.
    /// </summary>
    public bool MouseDown { get; set; }
    /// <summary>
    /// Name of the current <see cref="IInputAction"/>.
    /// </summary>
    public string ActionName { get; }
    /// <summary>
    /// Keycode of a currently pressed character.
    /// </summary>
    public int CharPressed { get; }

    /// <summary>
    /// Determines if the current input action corresponds to a cancel operation (ESC on the keyboard, B on the Xbox controller, etc.)
    /// </summary>
    public bool IsCancel => ActionName == "cancel";
    /// <summary>
    /// Determines if the current input action corresponds to a backspace operation. Used for text inputs.
    /// </summary>
    public bool IsBackspace => ActionName == "backspace";
    /// <summary>
    /// Determines if the current input action corresponds to an accept/submit operation (ENTER on the keyboard, A on the Xbox controller, etc.)
    /// </summary>
    public bool IsAccept => ActionName == "accept";

    public bool IsLeft => ActionName == "left";
    public bool IsRight => ActionName == "right";
    public bool IsUp => ActionName == "up";
    public bool IsDown => ActionName == "down";

    public float DeltaTime { get; init; }

    /// <summary>
    /// Determines if control key is pressed.
    /// </summary>
    public bool Control { get; set; }

    /// <summary>
    /// Determines if this <see cref="UIInputContext"/> registered any character input from keyboard.
    /// </summary>
    public bool HasCharInput => CharPressed != 0;

    /// <summary>
    /// Determines if this context's input was already handled and no longer needs to be processed.
    /// </summary>
    public bool Handled => _handled;

    /// <summary>
    /// Marks this context as handled, meaning next elements that will receive it should discard it.
    /// </summary>
    public void SetHandled() => _handled = true;

    public UIInputContext(IInputAction action, Vector2 mousePosition, string actionName, int charPressed = 0)
    {
        Action = action;
        MousePosition = mousePosition;
        ActionName = actionName;
        CharPressed = charPressed;
    }

    private bool _handled;
}