using System;
using System.Collections.Generic;
using MultiWheelC.TrajectoryPlanning.Utils;

namespace MultiWheelC.TrajectoryPlanning.Mapping;

/// <summary>规划地图创建的终止状态。</summary>
public enum PlanningMapBuildStatus
{
    /// <summary>已成功创建可用的不可变地图快照。</summary>
    Success,
    /// <summary>输入、来源或地图构建失败。</summary>
    Failed,
    /// <summary>调用方在地图创建期间取消了操作。</summary>
    Cancelled,
    /// <summary>地图创建消耗了整次规划操作的总超时预算。</summary>
    TimedOut,
}

/// <summary>本次地图创建使用的缓存层级，反映快照或占据数组的复用方式。</summary>
public enum PlanningMapCacheHit
{
    /// <summary>未命中缓存；本次重新创建了占据图和距离场。</summary>
    None,
    /// <summary>完整输入命中；返回与上次完全相同的不可变地图对象。</summary>
    Input,
    /// <summary>占据内容命中；复用占据和距离数组，但生成新的快照元数据。</summary>
    Occupancy,
}

/// <summary>
/// 规划地图创建的最终结果。
///
/// 返回：
/// - Succeeded 为 true 时 Map 可用；false 时通过 FailureReason 获取原因。
/// - SourceResults 始终保留已处理来源的投影状态，便于诊断。
/// </summary>
public sealed class PlanningMapBuildResult
{
    private PlanningMapBuildResult(PlanningMapBuildStatus status, string failureReason, IReadOnlyList<ObstacleProjectionResult> sourceResults, PlanningMapCacheHit cacheHit, PlanningGridMap map)
    {
        Status = status; FailureReason = failureReason ?? string.Empty; SourceResults = sourceResults ?? Array.Empty<ObstacleProjectionResult>(); CacheHit = cacheHit; Map = map;
    }
    /// <summary>本次建图的显式终止状态；取消和超时不提供地图快照。</summary>
    public PlanningMapBuildStatus Status { get; }
    /// <summary>本次建图是否成功。true 表示 Status 为 Success 且 Map 不为空；false 时读取 FailureReason。</summary>
    public bool Succeeded { get { return Status == PlanningMapBuildStatus.Success; } }
    /// <summary>建图失败的可读诊断。成功时为空字符串。</summary>
    public string FailureReason { get; }
    /// <summary>每个障碍物来源的投影结果，按建图器排序后的来源顺序排列。</summary>
    public IReadOnlyList<ObstacleProjectionResult> SourceResults { get; }
    /// <summary>本次调用的缓存复用层级，用于性能诊断，不影响地图正确性。</summary>
    public PlanningMapCacheHit CacheHit { get; }
    /// <summary>成功时返回的不可变规划地图；失败时为 null。</summary>
    public PlanningGridMap Map { get; }
    internal static PlanningMapBuildResult Success(PlanningGridMap map, IReadOnlyList<ObstacleProjectionResult> sourceResults, PlanningMapCacheHit cacheHit) { return new PlanningMapBuildResult(PlanningMapBuildStatus.Success, null, sourceResults, cacheHit, map); }
    internal static PlanningMapBuildResult Failure(string reason, IReadOnlyList<ObstacleProjectionResult> sourceResults) { return new PlanningMapBuildResult(PlanningMapBuildStatus.Failed, reason, sourceResults, PlanningMapCacheHit.None, null); }
    internal static PlanningMapBuildResult Stopped(PlanningOperationStopReason stopReason, IReadOnlyList<ObstacleProjectionResult> sourceResults)
    {
        if (stopReason == PlanningOperationStopReason.Cancelled)
            return new PlanningMapBuildResult(PlanningMapBuildStatus.Cancelled, "地图创建已取消。", sourceResults, PlanningMapCacheHit.None, null);
        if (stopReason == PlanningOperationStopReason.TimedOut)
            return new PlanningMapBuildResult(PlanningMapBuildStatus.TimedOut, "地图创建已超时。", sourceResults, PlanningMapCacheHit.None, null);
        throw new ArgumentOutOfRangeException(nameof(stopReason));
    }
}
