namespace Voile;

/// <summary>
/// Represents a rectangle. Used to determine widget confines for UI layout.
/// </summary>
public class Rect(float width = 0.0f, float height = 0.0f)
{
    public float Width { get; set; } = width;
    public float Height { get; set; } = height;
    public static Rect Zero => new Rect(0.0f, 0.0f);
    public float Area => Width * Height;

    public int CompareTo(Rect other) => Area.CompareTo(other.Area);

    public static bool operator >(Rect left, Rect right) => left.CompareTo(right) > 0;
    public static bool operator <(Rect left, Rect right) => left.CompareTo(right) < 0;
    public static bool operator >=(Rect left, Rect right) => left.CompareTo(right) >= 0;
    public static bool operator <=(Rect left, Rect right) => left.CompareTo(right) <= 0;

    /// <summary>
    /// Returns the rectangle with the smallest width.
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static Rect MinWidth(Rect a, Rect b)
    {
        if (a < b)
        {
            return a;
        }
        else if (a > b)
        {
            return b;
        }

        return a;
    }

    public static Rect MaxWidth(Rect a, Rect b)
    {
        if (a > b)
        {
            return a;
        }

        if (a < b)
        {
            return b;
        }

        return a;
    }

    public static Rect operator +(Rect left, Rect right)
    {
        var width = left.Width + right.Width;
        var height = left.Height + right.Height;
        return new(width, height);
    }
}

/// <summary>
/// Represents the size offsets applied around a rectangle.
/// </summary>
public struct Size : IEquatable<Size>
{
    public float Left;
    public float Right;
    public float Top;
    public float Bottom;

    public static Size Zero => new Size(0.0f);

    public Size(float uniform)
    {
        Left = Right = Top = Bottom = uniform;
    }

    public Size(float horizontal, float vertical)
    {
        Left = Right = horizontal;
        Top = Bottom = vertical;
    }

    public Size(float left, float right, float top, float bottom)
    {
        Left = left;
        Right = right;
        Top = top;
        Bottom = bottom;
    }

    public static Rect operator +(Size margin, Rect rect) =>
        new Rect(rect.Width + margin.Left + margin.Right,
                 rect.Height + margin.Top + margin.Bottom);

    public static Rect operator +(Rect rect, Size margin) =>
        margin + rect;


    public static bool operator ==(Size a, Size b) =>
a.Equals(b);

    public static bool operator !=(Size a, Size b) =>
        !a.Equals(b);

    public bool Equals(Size other) =>
        Left == other.Left &&
        Right == other.Right &&
        Top == other.Top &&
        Bottom == other.Bottom;

    public override bool Equals(object? obj) =>
        obj is Size other && Equals(other);

    public override int GetHashCode() =>
        HashCode.Combine(Left, Right, Top, Bottom);
}