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

namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Visualization;

/// <summary>单张 SVG/PNG 共享的不可变绘图视图。</summary>
public sealed class SmoothingFigureDefinition
{
    internal SmoothingFigureDefinition(
        SmoothingFigureKind kind,
        string fileStem,
        string title,
        SmoothingFigureModel model,
        bool showsMapContext,
        IReadOnlyList<SmoothingFigureSeriesView> series,
        double worldXMinMeters,
        double worldXMaxMeters,
        double worldYMinMeters,
        double worldYMaxMeters,
        IReadOnlyList<double> xTicks,
        IReadOnlyList<double> yTicks,
        double curvatureArcLengthMaximumMeters,
        double curvatureMinimumPerMeter,
        double curvatureMaximumPerMeter,
        IReadOnlyList<double> curvatureArcLengthTicks,
        IReadOnlyList<double> curvatureTicks)
    {
        Kind = kind;
        FileStem = fileStem ?? string.Empty;
        Title = title ?? string.Empty;
        Model = model ?? throw new ArgumentNullException(nameof(model));
        ShowsMapContext = showsMapContext;
        Series = Copy(series);
        WorldXMinMeters = worldXMinMeters;
        WorldXMaxMeters = worldXMaxMeters;
        WorldYMinMeters = worldYMinMeters;
        WorldYMaxMeters = worldYMaxMeters;
        XTicks = Copy(xTicks);
        YTicks = Copy(yTicks);
        CurvatureArcLengthMaximumMeters = curvatureArcLengthMaximumMeters;
        CurvatureMinimumPerMeter = curvatureMinimumPerMeter;
        CurvatureMaximumPerMeter = curvatureMaximumPerMeter;
        CurvatureArcLengthTicks = Copy(curvatureArcLengthTicks);
        CurvatureTicks = Copy(curvatureTicks);
    }

    public SmoothingFigureKind Kind { get; }
    public string FileStem { get; }
    public string Title { get; }
    public SmoothingFigureModel Model { get; }
    public bool ShowsMapContext { get; }
    public bool IsCurvatureFigure => Kind == SmoothingFigureKind.CurvatureComparison;
    public double FigureWidthPoints => Model.FigureWidthPoints;
    public double FigureHeightPoints => Model.FigureHeightPoints;
    public double PlotXPoints => 68d;
    public double PlotYPoints => 44d;
    public double PlotWidthPoints => 400d;
    public double PlotHeightPoints => 245d;
    public double LegendYPoints => 340d;
    public IReadOnlyList<SmoothingFigureSeriesView> Series { get; }
    public IReadOnlyList<SmoothingFigureLegendEntry> LegendEntries => BuildLegend(Series);
    public double WorldXMinMeters { get; }
    public double WorldXMaxMeters { get; }
    public double WorldYMinMeters { get; }
    public double WorldYMaxMeters { get; }
    public double WorldScalePointsPerMeter => Math.Min(PlotWidthPoints / (WorldXMaxMeters - WorldXMinMeters), PlotHeightPoints / (WorldYMaxMeters - WorldYMinMeters));
    public IReadOnlyList<double> XTicks { get; }
    public IReadOnlyList<double> YTicks { get; }
    public double CurvatureArcLengthMaximumMeters { get; }
    public double CurvatureMinimumPerMeter { get; }
    public double CurvatureMaximumPerMeter { get; }
    public IReadOnlyList<double> CurvatureArcLengthTicks { get; }
    public IReadOnlyList<double> CurvatureTicks { get; }

    private static IReadOnlyList<T> Copy<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);
    }

    private static IReadOnlyList<SmoothingFigureLegendEntry> BuildLegend(IReadOnlyList<SmoothingFigureSeriesView> views)
    {
        var entries = new List<SmoothingFigureLegendEntry>(views == null ? 0 : views.Count);
        if (views != null)
        {
            for (int index = 0; index < views.Count; index++)
            {
                SmoothingFigureSeries series = views[index].Series;
                entries.Add(new SmoothingFigureLegendEntry(series.Label + " (" + series.Status + ")", series.Color, string.Empty));
            }
        }
        return new ReadOnlyCollection<SmoothingFigureLegendEntry>(entries);
    }
}

/// <summary>某条路径在特定图中的显示透明度。</summary>
public sealed class SmoothingFigureSeriesView
{
    internal SmoothingFigureSeriesView(SmoothingFigureSeries series, double opacity)
    {
        Series = series ?? throw new ArgumentNullException(nameof(series));
        Opacity = opacity < 0d ? 0d : (opacity > 1d ? 1d : opacity);
    }

    public SmoothingFigureSeries Series { get; }
    public double Opacity { get; }
}
