using System;
using System.Collections.Generic;

namespace TrajectoryPlanningVisualization;

public sealed class PlanningVisualizationStaticSnapshot
{
    public PlanningVisualizationStaticSnapshot(string sessionNameChinese, VisualizationBounds worldBounds,
        VisualizationOccupancyGrid occupancyGrid, IReadOnlyList<VisualizationPolyline> staticPolylines,
        IReadOnlyList<VisualizationMarker> staticMarkers,
        IReadOnlyList<VisualizationDirectionSegment> directionSegments,
        IReadOnlyList<VisualizationConfigurationGroup> configurationGroups)
    {
        SessionNameChinese = VisualizationContract.RequireText(sessionNameChinese, nameof(sessionNameChinese));
        WorldBounds = worldBounds ?? throw new ArgumentNullException(nameof(worldBounds));
        OccupancyGrid = occupancyGrid;
        StaticPolylines = VisualizationContract.Copy(staticPolylines, nameof(staticPolylines));
        StaticMarkers = VisualizationContract.Copy(staticMarkers, nameof(staticMarkers));
        DirectionSegments = VisualizationContract.Copy(directionSegments, nameof(directionSegments));
        ConfigurationGroups = VisualizationContract.Copy(configurationGroups, nameof(configurationGroups));
    }

    public string SessionNameChinese { get; }
    public VisualizationBounds WorldBounds { get; }
    public VisualizationOccupancyGrid OccupancyGrid { get; }
    public IReadOnlyList<VisualizationPolyline> StaticPolylines { get; }
    public IReadOnlyList<VisualizationMarker> StaticMarkers { get; }
    public IReadOnlyList<VisualizationDirectionSegment> DirectionSegments { get; }
    public IReadOnlyList<VisualizationConfigurationGroup> ConfigurationGroups { get; }
}

public sealed class PlanningVisualizationDynamicSnapshot
{
    public PlanningVisualizationDynamicSnapshot(long sequence, DateTimeOffset observedAtUtc,
        string sessionStateChinese, int activeSegmentIndex, string activeDirection,
        VisualizationPose vehiclePose, IReadOnlyList<VisualizationPolyline> dynamicPolylines,
        IReadOnlyList<VisualizationMarker> dynamicMarkers, IReadOnlyList<VisualizationChart> charts,
        IReadOnlyList<VisualizationValue> statusValues, VisualizationCycleSummary cycleSummary)
    {
        Sequence = sequence;
        ObservedAtUtc = observedAtUtc;
        SessionStateChinese = VisualizationContract.RequireText(sessionStateChinese, nameof(sessionStateChinese));
        ActiveSegmentIndex = activeSegmentIndex;
        ActiveDirection = VisualizationContract.RequireText(activeDirection, nameof(activeDirection));
        VehiclePose = vehiclePose ?? throw new ArgumentNullException(nameof(vehiclePose));
        DynamicPolylines = VisualizationContract.Copy(dynamicPolylines, nameof(dynamicPolylines));
        DynamicMarkers = VisualizationContract.Copy(dynamicMarkers, nameof(dynamicMarkers));
        Charts = VisualizationContract.Copy(charts, nameof(charts));
        StatusValues = VisualizationContract.Copy(statusValues, nameof(statusValues));
        CycleSummary = cycleSummary ?? throw new ArgumentNullException(nameof(cycleSummary));
    }

    public long Sequence { get; }
    public DateTimeOffset ObservedAtUtc { get; }
    public string SessionStateChinese { get; }
    public int ActiveSegmentIndex { get; }
    public string ActiveDirection { get; }
    public VisualizationPose VehiclePose { get; }
    public IReadOnlyList<VisualizationPolyline> DynamicPolylines { get; }
    public IReadOnlyList<VisualizationMarker> DynamicMarkers { get; }
    public IReadOnlyList<VisualizationChart> Charts { get; }
    public IReadOnlyList<VisualizationValue> StatusValues { get; }
    public VisualizationCycleSummary CycleSummary { get; }
}

public sealed class VisualizationCycleSummary
{
    public VisualizationCycleSummary(long cycleVersion, DateTimeOffset occurredAtUtc, string status, bool published,
        double planningElapsedMilliseconds, int segmentIndex, string direction, string longitudinalMode,
        string terminalType, double? terminalVelocity, double? terminalAcceleration, string failureReason)
    {
        VisualizationContract.RequireFinite(planningElapsedMilliseconds, nameof(planningElapsedMilliseconds));
        VisualizationContract.RequireFinite(terminalVelocity, nameof(terminalVelocity));
        VisualizationContract.RequireFinite(terminalAcceleration, nameof(terminalAcceleration));
        CycleVersion = cycleVersion;
        OccurredAtUtc = occurredAtUtc;
        Status = VisualizationContract.RequireText(status, nameof(status));
        Published = published;
        PlanningElapsedMilliseconds = planningElapsedMilliseconds;
        SegmentIndex = segmentIndex;
        Direction = VisualizationContract.RequireText(direction, nameof(direction));
        LongitudinalMode = VisualizationContract.RequireText(longitudinalMode, nameof(longitudinalMode));
        TerminalType = VisualizationContract.RequireText(terminalType, nameof(terminalType));
        TerminalVelocity = terminalVelocity;
        TerminalAcceleration = terminalAcceleration;
        FailureReason = VisualizationContract.RequireText(failureReason, nameof(failureReason));
    }

    public long CycleVersion { get; }
    public DateTimeOffset OccurredAtUtc { get; }
    public string Status { get; }
    public bool Published { get; }
    public double PlanningElapsedMilliseconds { get; }
    public int SegmentIndex { get; }
    public string Direction { get; }
    public string LongitudinalMode { get; }
    public string TerminalType { get; }
    public double? TerminalVelocity { get; }
    public double? TerminalAcceleration { get; }
    public string FailureReason { get; }
}
