using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using MultiWheelC.TrajectoryPlanning.PathSmoothing.Processing;

namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Algorithms;

internal enum SmoothingCandidateStatus
{
    Success,
    RetryableInfeasible,
    Failed,
}

/// <summary>平滑方法产生的原始方向段候选，尚未经过统一几何或安全复核。</summary>
internal sealed class SmoothingCandidate
{
    private SmoothingCandidate(
        SmoothingCandidateStatus status,
        IReadOnlyList<PreparedDirectionSegment> segments,
        string reason)
    {
        Status = status;
        if (status == SmoothingCandidateStatus.Success)
        {
            if (segments == null || segments.Count == 0)
                throw new ArgumentException("A successful smoothing candidate requires direction segments.", nameof(segments));
            for (int index = 0; index < segments.Count; index++)
            {
                if (segments[index] == null || segments[index].Points == null || segments[index].Points.Count == 0)
                    throw new ArgumentException("A successful smoothing candidate requires complete direction segments.", nameof(segments));
            }
            Segments = CopyReadOnly(segments);
            Reason = string.Empty;
            return;
        }

        if (string.IsNullOrWhiteSpace(reason))
            throw new ArgumentException("An unsuccessful smoothing candidate requires a reason.", nameof(reason));
        Segments = CopyReadOnly<PreparedDirectionSegment>(null);
        Reason = reason;
    }

    /// <summary>候选是否成功产生有限的原始几何。</summary>
    internal bool Succeeded => Status == SmoothingCandidateStatus.Success;

    /// <summary>候选的可重试性和终止性状态。</summary>
    internal SmoothingCandidateStatus Status { get; }

    /// <summary>候选方向段；失败候选始终为空。</summary>
    internal IReadOnlyList<PreparedDirectionSegment> Segments { get; }

    /// <summary>失败或退化时的稳定说明；成功时为空。</summary>
    internal string Reason { get; }

    /// <summary>创建待统一分析和验证的成功候选。</summary>
    internal static SmoothingCandidate Success(IReadOnlyList<PreparedDirectionSegment> segments)
    {
        return new SmoothingCandidate(SmoothingCandidateStatus.Success, segments, string.Empty);
    }

    /// <summary>创建可由较低平滑强度重新尝试的不可行候选。</summary>
    internal static SmoothingCandidate RetryableInfeasible(string reason)
    {
        return new SmoothingCandidate(SmoothingCandidateStatus.RetryableInfeasible, null, reason);
    }

    /// <summary>创建不应重试的数值或构造失败候选。</summary>
    internal static SmoothingCandidate Failed(string reason)
    {
        return new SmoothingCandidate(SmoothingCandidateStatus.Failed, null, reason);
    }

    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);
    }
}
