using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Comparison;

/// <summary>原始基线或一种平滑方法的不可变比较条目。</summary>
public sealed class PathSmoothingComparisonEntry
{
    /// <summary>为测试、离线分析和排序创建不携带路径几何的候选条目。</summary>
    public PathSmoothingComparisonEntry(
        SmoothingMethod method,
        PathSmoothingStatus status,
        PathQualityMetrics metrics,
        SmoothingTimingSummary timing,
        string stableGeometryDigest,
        string diagnostic)
        : this(method, false, status, metrics, timing, stableGeometryDigest, diagnostic, Empty<SmoothedPathPoint>(), Empty<SmoothedPathSegment>())
    {
    }

    private PathSmoothingComparisonEntry(
        SmoothingMethod? method,
        bool isRawPathBaseline,
        PathSmoothingStatus status,
        PathQualityMetrics metrics,
        SmoothingTimingSummary timing,
        string stableGeometryDigest,
        string diagnostic,
        IReadOnlyList<SmoothedPathPoint> path,
        IReadOnlyList<SmoothedPathSegment> segments)
    {
        Method = method;
        IsRawPathBaseline = isRawPathBaseline;
        Status = status;
        Metrics = metrics ?? new PathQualityMetrics();
        Timing = timing ?? new SmoothingTimingSummary(new double[] { 0d, 0d, 0d, 0d, 0d }, false, "未提供计时结果。");
        StableGeometryDigest = stableGeometryDigest ?? string.Empty;
        Diagnostic = diagnostic ?? string.Empty;
        Path = CopyReadOnly(path);
        Segments = CopyReadOnly(segments);
    }

    /// <summary>候选所代表的方法；原始粗路径基线为空。</summary>
    public SmoothingMethod? Method { get; }

    /// <summary>是否为单独分析的原始粗路径基线。</summary>
    public bool IsRawPathBaseline { get; }

    /// <summary>本条目的最终状态。</summary>
    public PathSmoothingStatus Status { get; }

    /// <summary>使用原始基线规范化后的质量指标。</summary>
    public PathQualityMetrics Metrics { get; }

    /// <summary>方法的五次测量计时；基线不参与计时排名。</summary>
    public SmoothingTimingSummary Timing { get; }

    /// <summary>由状态、分段元数据和完整路径 IEEE 754 位模式生成的 SHA-256 摘要。</summary>
    public string StableGeometryDigest { get; }

    /// <summary>面向报告和诊断的稳定说明。</summary>
    public string Diagnostic { get; }

    /// <summary>仅供比较与报告读取的正式路径；失败时为空。</summary>
    public IReadOnlyList<SmoothedPathPoint> Path { get; }

    /// <summary>覆盖 <see cref="Path"/> 的方向段；失败时为空。</summary>
    public IReadOnlyList<SmoothedPathSegment> Segments { get; }

    /// <summary>条目能否参与方法推荐。</summary>
    public bool IsEligibleForRecommendation =>
        !IsRawPathBaseline &&
        Status == PathSmoothingStatus.Success &&
        Metrics.IsFeasible &&
        Timing.IsDeterministic;

    internal static PathSmoothingComparisonEntry CreateCandidate(
        SmoothingMethod method,
        PathSmoothingStatus status,
        PathQualityMetrics metrics,
        SmoothingTimingSummary timing,
        string stableGeometryDigest,
        string diagnostic,
        IReadOnlyList<SmoothedPathPoint> path,
        IReadOnlyList<SmoothedPathSegment> segments)
    {
        return new PathSmoothingComparisonEntry(
            method, false, status, metrics, timing, stableGeometryDigest, diagnostic, path, segments);
    }

    internal static PathSmoothingComparisonEntry CreateRawPathBaseline(
        PathSmoothingStatus status,
        PathQualityMetrics metrics,
        string stableGeometryDigest,
        string diagnostic,
        IReadOnlyList<SmoothedPathPoint> path,
        IReadOnlyList<SmoothedPathSegment> segments)
    {
        return new PathSmoothingComparisonEntry(
            null, true, status, metrics,
            new SmoothingTimingSummary(new double[] { 0d, 0d, 0d, 0d, 0d }, true, string.Empty),
            stableGeometryDigest, diagnostic, path, segments);
    }

    private static IReadOnlyList<T> Empty<T>()
    {
        return new ReadOnlyCollection<T>(new List<T>());
    }

    private static IReadOnlyList<T> CopyReadOnly<T>(IReadOnlyList<T> source)
    {
        var copy = new List<T>(source == null ? 0 : source.Count);
        if (source != null)
        {
            for (int index = 0; index < source.Count; index++) copy.Add(source[index]);
        }
        return new ReadOnlyCollection<T>(copy);
    }
}
