using System;
using System.Collections.Generic;
using System.Linq;
using BDInfo;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.MediaEncoding.BdInfo;
/// 
/// Class BdInfoExaminer.
/// 
public class BdInfoExaminer : IBlurayExaminer
{
    private readonly IFileSystem _fileSystem;
    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// The filesystem.
    public BdInfoExaminer(IFileSystem fileSystem)
    {
        _fileSystem = fileSystem;
    }
    /// 
    /// Gets the disc info.
    /// 
    /// The path.
    /// BlurayDiscInfo.
    public BlurayDiscInfo GetDiscInfo(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
        {
            throw new ArgumentNullException(nameof(path));
        }
        var bdrom = new BDROM(BdInfoDirectoryInfo.FromFileSystemPath(_fileSystem, path));
        bdrom.Scan();
        // Get the longest playlist
        var playlist = bdrom.PlaylistFiles.Values.OrderByDescending(p => p.TotalLength).FirstOrDefault(p => p.IsValid);
        var outputStream = new BlurayDiscInfo
        {
            MediaStreams = Array.Empty()
        };
        if (playlist is null)
        {
            return outputStream;
        }
        outputStream.Chapters = playlist.Chapters.ToArray();
        outputStream.RunTimeTicks = TimeSpan.FromSeconds(playlist.TotalLength).Ticks;
        var sortedStreams = playlist.SortedStreams;
        var mediaStreams = new List(sortedStreams.Count);
        foreach (var stream in sortedStreams)
        {
            switch (stream)
            {
                case TSVideoStream videoStream:
                    AddVideoStream(mediaStreams, videoStream);
                    break;
                case TSAudioStream audioStream:
                    AddAudioStream(mediaStreams, audioStream);
                    break;
                case TSTextStream textStream:
                    AddSubtitleStream(mediaStreams, textStream);
                    break;
                case TSGraphicsStream graphicStream:
                    AddSubtitleStream(mediaStreams, graphicStream);
                    break;
            }
        }
        outputStream.MediaStreams = mediaStreams.ToArray();
        outputStream.PlaylistName = playlist.Name;
        if (playlist.StreamClips is not null && playlist.StreamClips.Count > 0)
        {
            // Get the files in the playlist
            outputStream.Files = playlist.StreamClips.Select(i => i.StreamFile.Name).ToArray();
        }
        return outputStream;
    }
    /// 
    /// Adds the video stream.
    /// 
    /// The streams.
    /// The video stream.
    private void AddVideoStream(List streams, TSVideoStream videoStream)
    {
        var mediaStream = new MediaStream
        {
            BitRate = Convert.ToInt32(videoStream.BitRate),
            Width = videoStream.Width,
            Height = videoStream.Height,
            Codec = videoStream.CodecShortName,
            IsInterlaced = videoStream.IsInterlaced,
            Type = MediaStreamType.Video,
            Index = streams.Count
        };
        if (videoStream.FrameRateDenominator > 0)
        {
            float frameRateEnumerator = videoStream.FrameRateEnumerator;
            float frameRateDenominator = videoStream.FrameRateDenominator;
            mediaStream.AverageFrameRate = mediaStream.RealFrameRate = frameRateEnumerator / frameRateDenominator;
        }
        streams.Add(mediaStream);
    }
    /// 
    /// Adds the audio stream.
    /// 
    /// The streams.
    /// The audio stream.
    private void AddAudioStream(List streams, TSAudioStream audioStream)
    {
        var stream = new MediaStream
        {
            Codec = audioStream.CodecShortName,
            Language = audioStream.LanguageCode,
            Channels = audioStream.ChannelCount,
            SampleRate = audioStream.SampleRate,
            Type = MediaStreamType.Audio,
            Index = streams.Count
        };
        var bitrate = Convert.ToInt32(audioStream.BitRate);
        if (bitrate > 0)
        {
            stream.BitRate = bitrate;
        }
        if (audioStream.LFE > 0)
        {
            stream.Channels = audioStream.ChannelCount + 1;
        }
        streams.Add(stream);
    }
    /// 
    /// Adds the subtitle stream.
    /// 
    /// The streams.
    /// The text stream.
    private void AddSubtitleStream(List streams, TSTextStream textStream)
    {
        streams.Add(new MediaStream
        {
            Language = textStream.LanguageCode,
            Codec = textStream.CodecShortName,
            Type = MediaStreamType.Subtitle,
            Index = streams.Count
        });
    }
    /// 
    /// Adds the subtitle stream.
    /// 
    /// The streams.
    /// The text stream.
    private void AddSubtitleStream(List streams, TSGraphicsStream textStream)
    {
        streams.Add(new MediaStream
        {
            Language = textStream.LanguageCode,
            Codec = textStream.CodecShortName,
            Type = MediaStreamType.Subtitle,
            Index = streams.Count
        });
    }
}