using System;
using System.Globalization;

using Swan;

namespace Unosquare.RaspberryIO.Camera {
  /// <summary>
  /// Defines the Raspberry Pi camera's sensor ROI (Region of Interest).
  /// </summary>
  public struct CameraRect {
    /// <summary>
    /// The default ROI which is the entire area.
    /// </summary>
    public static readonly CameraRect Default = new CameraRect { X = 0M, Y = 0M, W = 1.0M, H = 1.0M };

    /// <summary>
    /// Gets or sets the x in relative coordinates. (0.0 to 1.0).
    /// </summary>
    /// <value>
    /// The x.
    /// </value>
    public Decimal X {
      get; set;
    }

    /// <summary>
    /// Gets or sets the y location in relative coordinates.  (0.0 to 1.0).
    /// </summary>
    /// <value>
    /// The y.
    /// </value>
    public Decimal Y {
      get; set;
    }

    /// <summary>
    /// Gets or sets the width in relative coordinates.  (0.0 to 1.0).
    /// </summary>
    /// <value>
    /// The w.
    /// </value>
    public Decimal W {
      get; set;
    }

    /// <summary>
    /// Gets or sets the height in relative coordinates.  (0.0 to 1.0).
    /// </summary>
    /// <value>
    /// The h.
    /// </value>
    public Decimal H {
      get; set;
    }

    /// <summary>
    /// Gets a value indicating whether this instance is equal to the default (The entire area).
    /// </summary>
    /// <value>
    /// <c>true</c> if this instance is default; otherwise, <c>false</c>.
    /// </value>
    public Boolean IsDefault {
      get {
        this.Clamp();
        return this.X == Default.X && this.Y == Default.Y && this.W == Default.W && this.H == Default.H;
      }
    }

    /// <summary>
    /// Clamps the members of this ROI to their minimum and maximum values.
    /// </summary>
    public void Clamp() {
      this.X = this.X.Clamp(0M, 1M);
      this.Y = this.Y.Clamp(0M, 1M);
      this.W = this.W.Clamp(0M, 1M - this.X);
      this.H = this.H.Clamp(0M, 1M - this.Y);
    }

    /// <summary>
    /// Returns a <see cref="String" /> that represents this instance.
    /// </summary>
    /// <returns>
    /// A <see cref="String" /> that represents this instance.
    /// </returns>
    public override String ToString() => $"{this.X.ToString(CultureInfo.InvariantCulture)},{this.Y.ToString(CultureInfo.InvariantCulture)},{this.W.ToString(CultureInfo.InvariantCulture)},{this.H.ToString(CultureInfo.InvariantCulture)}";
  }
}