using System.Globalization;
using System.Text.RegularExpressions;

namespace AmiReel.Services;

public sealed record FfmpegOutputLine(string Line, TimeSpan? Time, double? FramesPerSecond, double? Speed, int? Frame);

/// <summary>
/// Parses a single line of FFmpeg stdout/stderr for the `time=`/`frame=`/`fps=`/`speed=`
/// progress fields FFmpeg prints while encoding.
/// </summary>
public static partial class FfmpegProgressParser
{
    public static FfmpegOutputLine Parse(string line)
    {
        TimeSpan? time = null;
        double? fps = null;
        double? speed = null;
        int? frame = null;

        Match timeMatch = TimeRegex().Match(line);
        if (timeMatch.Success && TimeSpan.TryParse(timeMatch.Groups[1].Value, CultureInfo.InvariantCulture, out TimeSpan parsedTime))
            time = parsedTime;

        Match frameMatch = FrameRegex().Match(line);
        if (frameMatch.Success)
        {
            if (int.TryParse(frameMatch.Groups["frame"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int parsedFrame))
                frame = parsedFrame;
            if (double.TryParse(frameMatch.Groups["fps"].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedFps))
                fps = parsedFps;
            if (double.TryParse(frameMatch.Groups["speed"].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double parsedSpeed))
                speed = parsedSpeed;
        }

        return new FfmpegOutputLine(line, time, fps, speed, frame);
    }

    [GeneratedRegex(@"time=(\d{2}:\d{2}:\d{2}(?:\.\d+)?)", RegexOptions.CultureInvariant)]
    private static partial Regex TimeRegex();

    [GeneratedRegex(@"frame=\s*(?<frame>\d+).*?fps=\s*(?<fps>\d+(?:\.\d+)?).*?speed=\s*(?<speed>\d+(?:\.\d+)?)x", RegexOptions.CultureInvariant)]
    private static partial Regex FrameRegex();
}
