using System.Numerics;

namespace Voile.UI;

/// <summary>
/// Specifies predefined anchor points used to position UI elements relative to their parent container.
/// </summary>
public enum Anchor
{
    /// <summary>
    /// Anchors the element to the top-left corner of the parent.
    /// </summary>
    TopLeft,

    /// <summary>
    /// Anchors the element to the top-center of the parent.
    /// </summary>
    TopCenter,

    /// <summary>
    /// Anchors the element to the top-right corner of the parent.
    /// </summary>
    TopRight,

    /// <summary>
    /// Anchors the element to the center-left edge of the parent.
    /// </summary>
    CenterLeft,

    /// <summary>
    /// Anchors the element to the exact center of the parent.
    /// </summary>
    Center,

    /// <summary>
    /// Anchors the element to the center-right edge of the parent.
    /// </summary>
    CenterRight,

    /// <summary>
    /// Anchors the element to the bottom-left corner of the parent.
    /// </summary>
    BottomLeft,

    /// <summary>
    /// Anchors the element to the bottom-center of the parent.
    /// </summary>
    BottomCenter,

    /// <summary>
    /// Anchors the element to the bottom-right corner of the parent.
    /// </summary>
    BottomRight,
    Fill
}

/// <summary>
/// Provides extension methods for calculating anchored positions of UI elements.
/// </summary>
public static class AnchorExtensions
{
    /// <summary>
    /// Calculates the offset position for an element based on the specified <see cref="Anchor"/>.
    /// </summary>
    /// <param name="anchor">The anchor mode to use.</param>
    /// <param name="parentPosition">The absolute position of the parent container (top-left corner).</param>
    /// <param name="parentRect">The bounding rectangle of the parent container.</param>
    /// <param name="elementRect">The size of the element being anchored.</param>
    /// <returns>
    /// A <see cref="Vector2"/> representing the local offset position where the element should be placed inside the parent.
    /// </returns>
    /// <remarks>
    /// The result is the relative offset from the parent's origin, not a global position.
    /// </remarks>
    public static Vector2 Calculate(this Anchor anchor, Vector2 parentPosition, Rect parentRect, Rect elementRect)
    {
        var size = new Vector2(elementRect.Width, elementRect.Height);
        var parentSize = new Vector2(parentRect.Width, parentRect.Height);

        return anchor switch
        {
            Anchor.TopLeft => Vector2.Zero,
            Anchor.TopCenter => new Vector2((parentSize.X - size.X) / 2, 0),
            Anchor.TopRight => new Vector2(parentSize.X - size.X, 0),
            Anchor.CenterLeft => new Vector2(0, (parentSize.Y - size.Y) / 2),
            Anchor.Center => (parentSize - size) / 2,
            Anchor.CenterRight => new Vector2(parentSize.X - size.X, (parentSize.Y - size.Y) / 2),
            Anchor.BottomLeft => new Vector2(0, parentSize.Y - size.Y),
            Anchor.BottomCenter => new Vector2((parentSize.X - size.X) / 2, parentSize.Y - size.Y),
            Anchor.BottomRight => parentSize - size,
            _ => Vector2.Zero
        };
    }
}