namespace DragonISO.Engine.Domain;

public sealed record FrameProcessingSettings(
    TargetFramerate Framerate,
    TargetResolution Resolution,
    AspectMode Aspect,
    AudioMode Audio)
{
    public static readonly FrameProcessingSettings Default =
        new(TargetFramerate.Fps59_94, TargetResolution.R1080p, AspectMode.Pillarbox, AudioMode.Auto);

    /// <summary>Returns the framerate enum value as a numeric frames-per-second.</summary>
    public double FramerateHz => Framerate switch
    {
        TargetFramerate.Fps23_976 => 24000.0 / 1001.0,
        TargetFramerate.Fps24     => 24.0,
        TargetFramerate.Fps25     => 25.0,
        TargetFramerate.Fps29_97  => 30000.0 / 1001.0,
        TargetFramerate.Fps30     => 30.0,
        TargetFramerate.Fps50     => 50.0,
        TargetFramerate.Fps59_94  => 60000.0 / 1001.0,
        TargetFramerate.Fps60     => 60.0,
        _ => throw new InvalidOperationException($"Unknown framerate: {Framerate}")
    };

    /// <summary>
    /// Returns the framerate as an exact rational (numerator / denominator), as
    /// required by the NDI sender's <c>frame_rate_N</c> / <c>frame_rate_D</c> and
    /// by container muxers. The broadcast fractional rates are 1000/1001 pulldowns
    /// of their integer parents (e.g. 59.94 = 60000/1001), so we must carry the
    /// rational rather than a rounded <see cref="FramerateHz"/> double — advertising
    /// 60/1 for a 59.94 stream causes drift and A/V desync downstream.
    /// </summary>
    public (int Numerator, int Denominator) FrameRate => Framerate switch
    {
        TargetFramerate.Fps23_976 => (24000, 1001),
        TargetFramerate.Fps24     => (24, 1),
        TargetFramerate.Fps25     => (25, 1),
        TargetFramerate.Fps29_97  => (30000, 1001),
        TargetFramerate.Fps30     => (30, 1),
        TargetFramerate.Fps50     => (50, 1),
        TargetFramerate.Fps59_94  => (60000, 1001),
        TargetFramerate.Fps60     => (60, 1),
        _ => throw new InvalidOperationException($"Unknown framerate: {Framerate}")
    };

    /// <summary>Returns the resolution as (width, height).</summary>
    public (int Width, int Height) ResolutionSize => Resolution switch
    {
        TargetResolution.R720p  => (1280, 720),
        TargetResolution.R1080p => (1920, 1080),
        TargetResolution.R4K    => (3840, 2160),
        _ => throw new InvalidOperationException($"Unknown resolution: {Resolution}")
    };
}
