using ErsatzTV.FFmpeg.OutputFormat;

namespace ErsatzTV.FFmpeg;

public record FFmpegState(
    bool SaveReport,
    HardwareAccelerationMode DecoderHardwareAccelerationMode,
    HardwareAccelerationMode EncoderHardwareAccelerationMode,
    Option<string> VaapiDriver,
    Option<string> VaapiDevice,
    Option<TimeSpan> Start,
    Option<TimeSpan> Finish,
    bool DoNotMapMetadata,
    Option<string> MetadataServiceProvider,
    Option<string> MetadataServiceName,
    Option<string> MetadataAudioLanguage,
    Option<string> MetadataSubtitleLanguage,
    Option<string> MetadataSubtitleTitle,
    OutputFormatKind OutputFormat,
    Option<string> HlsPlaylistPath,
    Option<string> HlsSegmentTemplate,
    Option<string> HlsInitTemplate,
    Option<string> HlsSegmentOptions,
    TimeSpan PtsOffset,
    Option<int> ThreadCount,
    Option<int> MaybeQsvExtraHardwareFrames,
    bool IsSongWithProgress,
    bool IsHdrTonemap,
    string TonemapAlgorithm,
    bool IsTroubleshooting,
    bool QsvPreferNativeDecoder = false)
{
    // the QSV upload pool needs headroom for the frames in flight through the filter graph.
    // extra_hw_frames=0 leaves none, so any input that is not throttled exhausts it: the graph
    // fails with -12 (Cannot allocate memory), h264_qsv reports "Could not open encoder before
    // EOF", and the output file gets no packets at all. Input throttling was the only thing
    // hiding it — a work-ahead start (no -readrate) and #350's cold-start burst both remove that
    // throttle, so the channel simply dies. A stored 0 is therefore treated as "no pool
    // configured" rather than honored literally (ersatztv#529)
    public const int MinimumQsvExtraHardwareFrames = 64;

    public int QsvExtraHardwareFrames =>
        Math.Max(MaybeQsvExtraHardwareFrames.IfNone(MinimumQsvExtraHardwareFrames), MinimumQsvExtraHardwareFrames);

    public static FFmpegState Concat(bool saveReport, string channelName) =>
        new(
            saveReport,
            HardwareAccelerationMode.None,
            HardwareAccelerationMode.None,
            Option<string>.None,
            Option<string>.None,
            Option<TimeSpan>.None,
            Option<TimeSpan>.None,
            true, // do not map metadata
            "ErsatzTV",
            channelName,
            Option<string>.None,
            Option<string>.None,
            Option<string>.None,
            OutputFormatKind.MpegTs,
            Option<string>.None,
            Option<string>.None,
            Option<string>.None,
            Option<string>.None,
            TimeSpan.Zero,
            Option<int>.None,
            Option<int>.None,
            false,
            false,
            "linear",
            false);
}
