using System;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using System.IO;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Progressive
{
    /// 
    /// Class BaseProgressiveStreamingService
    /// 
    public abstract class BaseProgressiveStreamingService : BaseStreamingService
    {
        protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) : 
            base(appPaths, userManager, libraryManager, isoManager)
        {
        }
        /// 
        /// Gets the output file extension.
        /// 
        /// The state.
        /// System.String.
        protected override string GetOutputFileExtension(StreamState state)
        {
            var ext = base.GetOutputFileExtension(state);
            if (!string.IsNullOrEmpty(ext))
            {
                return ext;
            }
            var videoRequest = state.Request as VideoStreamRequest;
            // Try to infer based on the desired video codec
            if (videoRequest != null && videoRequest.VideoCodec.HasValue)
            {
                var video = state.Item as Video;
                if (video != null)
                {
                    switch (videoRequest.VideoCodec.Value)
                    {
                        case VideoCodecs.H264:
                            return ".ts";
                        case VideoCodecs.Theora:
                            return ".ogv";
                        case VideoCodecs.Vpx:
                            return ".webm";
                        case VideoCodecs.Wmv:
                            return ".asf";
                    }
                }
            }
            // Try to infer based on the desired audio codec
            if (state.Request.AudioCodec.HasValue)
            {
                var audio = state.Item as Audio;
                if (audio != null)
                {
                    switch (state.Request.AudioCodec.Value)
                    {
                        case AudioCodecs.Aac:
                            return ".aac";
                        case AudioCodecs.Mp3:
                            return ".mp3";
                        case AudioCodecs.Vorbis:
                            return ".ogg";
                        case AudioCodecs.Wma:
                            return ".wma";
                    }
                }
            }
            return null;
        }
        /// 
        /// Adds the dlna headers.
        /// 
        private bool AddDlnaHeaders(StreamState state)
        {
            var timeSeek = RequestContext.GetHeader("TimeSeekRange.dlna.org");
            if (!string.IsNullOrEmpty(timeSeek))
            {
                Response.StatusCode = 406;
                return false;
            }
            var transferMode = RequestContext.GetHeader("transferMode.dlna.org");
            Response.AddHeader("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode);
            var contentFeatures = string.Empty;
            var extension = GetOutputFileExtension(state);
            if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".aac", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".wma", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".avi", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".mp4", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=MPEG4_P2_SP_AAC;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".mpeg", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000";
            }
            else if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
            {
                contentFeatures = "DLNA.ORG_OP=01;DLNA.ORG_CI=0";
            }
            if (!string.IsNullOrEmpty(contentFeatures))
            {
                Response.AddHeader("ContentFeatures.DLNA.ORG", contentFeatures);
            }
            return true;
        }
        /// 
        /// Gets the type of the transcoding job.
        /// 
        /// The type of the transcoding job.
        protected override TranscodingJobType TranscodingJobType
        {
            get { return TranscodingJobType.Progressive; }
        }
        /// 
        /// Processes the request.
        /// 
        /// The request.
        /// if set to true [is head request].
        /// Task.
        protected object ProcessRequest(StreamRequest request, bool isHeadRequest)
        {
            var state = GetState(request);
            if (!AddDlnaHeaders(state))
            {
                return null;
            }
            if (request.Static)
            {
                return ToStaticFileResult(state.Item.Path, isHeadRequest);
            }
            var outputPath = GetOutputFilePath(state);
            if (File.Exists(outputPath) && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive))
            {
                return ToStaticFileResult(outputPath, isHeadRequest);
            }
            Response.AddHeader("Accept-Ranges", "none");
            return GetStreamResult(state, isHeadRequest).Result;
        }
        /// 
        /// Gets the stream result.
        /// 
        /// The state.
        /// if set to true [is head request].
        /// Task{System.Object}.
        private async Task GetStreamResult(StreamState state, bool isHeadRequest)
        {
            // Use the command line args with a dummy playlist path
            var outputPath = GetOutputFilePath(state);
            Response.ContentType = MimeTypes.GetMimeType(outputPath);
            // Headers only
            if (isHeadRequest)
            {
                return null;
            }
            if (!File.Exists(outputPath))
            {
                await StartFFMpeg(state, outputPath).ConfigureAwait(false);
            }
            else
            {
                ApiEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
            }
            return new ProgressiveStreamWriter(outputPath, state, Logger);
        }
        /// 
        /// Deletes the partial stream files.
        /// 
        /// The output file path.
        protected override void DeletePartialStreamFiles(string outputFilePath)
        {
            File.Delete(outputFilePath);
        }
    }
}