using MultiWheelC.TrajectoryPlanning.Utils;

namespace MultiWheelC.TrajectoryPlanning.Mapping;

/// <summary>
/// TwoLeg 检测时刻的纯输入快照。
///
/// 单位：位置和两腿局部坐标均为 mm，航向为弧度。该对象不读取检测器或定位模块，确保投影可重复。
/// </summary>
public sealed class TwoLegProjectionInput
{
    /// <summary>
    /// 创建 TwoLeg 投影快照。
    ///
    /// 参数：hasDetection 表示当前是否检测到目标；detectionWorldX/Y 为检测坐标系原点的世界 mm 坐标；detectionHeadingRadians 为其相对世界坐标系的航向；firstLocalX/Y、secondLocalX/Y 为两腿在检测局部坐标系中的 mm 坐标；radiusMm 为每条腿投影圆半径；diagnostic 为可选诊断文本。
    /// 注意：hasDetection 为 false 时其余几何参数不会参与有效性校验。
    /// </summary>
    public TwoLegProjectionInput(bool hasDetection, float detectionWorldX, float detectionWorldY,
        double detectionHeadingRadians, float firstLocalX, float firstLocalY,
        float secondLocalX, float secondLocalY, float radiusMm, string diagnostic = null)
    {
        HasDetection = hasDetection; DetectionWorldX = detectionWorldX; DetectionWorldY = detectionWorldY;
        DetectionHeadingRadians = detectionHeadingRadians; FirstLocalX = firstLocalX; FirstLocalY = firstLocalY;
        SecondLocalX = secondLocalX; SecondLocalY = secondLocalY; RadiusMm = radiusMm; Diagnostic = diagnostic ?? string.Empty;
    }
    /// <summary>检测是否存在。false 时投影结果为 Empty。</summary>
    public bool HasDetection { get; }
    /// <summary>检测局部坐标系原点的世界 X 坐标，单位 mm。</summary>
    public float DetectionWorldX { get; }
    /// <summary>检测局部坐标系原点的世界 Y 坐标，单位 mm。</summary>
    public float DetectionWorldY { get; }
    /// <summary>检测局部坐标系相对世界坐标系的航向，单位弧度。</summary>
    public double DetectionHeadingRadians { get; }
    /// <summary>第一条腿在检测局部坐标系的 X 坐标，单位 mm。</summary>
    public float FirstLocalX { get; }
    /// <summary>第一条腿在检测局部坐标系的 Y 坐标，单位 mm。</summary>
    public float FirstLocalY { get; }
    /// <summary>第二条腿在检测局部坐标系的 X 坐标，单位 mm。</summary>
    public float SecondLocalX { get; }
    /// <summary>第二条腿在检测局部坐标系的 Y 坐标，单位 mm。</summary>
    public float SecondLocalY { get; }
    /// <summary>投影为圆形障碍物时的半径，单位 mm。</summary>
    public float RadiusMm { get; }
    /// <summary>上游检测阶段提供的可选诊断文本；未提供时为空字符串。</summary>
    public string Diagnostic { get; }
    /// <summary>未检测到目标时为 true；检测到目标时，所有数值有限且半径非负才为 true。</summary>
    public bool IsValid
    {
        get { return !HasDetection || (NumericGuard.IsFinite(DetectionWorldX) && NumericGuard.IsFinite(DetectionWorldY) && NumericGuard.IsFinite(DetectionHeadingRadians) && NumericGuard.IsFinite(FirstLocalX) && NumericGuard.IsFinite(FirstLocalY) && NumericGuard.IsFinite(SecondLocalX) && NumericGuard.IsFinite(SecondLocalY) && NumericGuard.IsFinite(RadiusMm) && RadiusMm >= 0f); }
    }
}
