using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Resolvers
{
    /// 
    /// Class EntityResolutionHelper
    /// 
    public static class EntityResolutionHelper
    {
        /// 
        /// Any folder named in this list will be ignored - can be added to at runtime for extensibility
        /// 
        public static readonly List IgnoreFolders = new List
        {
                "metadata",
                "ps3_update",
                "ps3_vprm",
                "extrafanart",
                "extrathumbs",
                ".actors",
                ".wd_tv"
        };
        private static readonly Regex MultiFileRegex = new Regex(
            @"(.*?)([ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck]|d)[ _.-]*[0-9]+)(.*?)(\.[^.]+)$",
            RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private static readonly Regex MultiFolderRegex = new Regex(
            @"(.*?)([ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck]|d)[ _.-]*[0-9]+)$",
            RegexOptions.Compiled | RegexOptions.IgnoreCase);
        /// 
        /// Determines whether [is multi part file] [the specified path].
        /// 
        /// The path.
        /// true if [is multi part file] [the specified path]; otherwise, false.
        public static bool IsMultiPartFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            path = Path.GetFileName(path);
            return MultiFileRegex.Match(path).Success;
        }
        public static bool IsMultiPartFolder(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            path = Path.GetFileName(path);
            return MultiFolderRegex.Match(path).Success;
        }
        /// 
        /// The audio file extensions
        /// 
        public static readonly string[] AudioFileExtensions =
        {
            ".mp3",
            ".flac",
            ".wma",
            ".aac",
            ".acc",
            ".m4a",
            ".m4b",
            ".wav",
            ".ape",
            ".ogg",
            ".oga"
            //".asf",
            //".mp4"
        };
        private static readonly Dictionary AudioFileExtensionsDictionary = AudioFileExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
        /// 
        /// Determines whether [is audio file] [the specified args].
        /// 
        /// The path.
        /// true if [is audio file] [the specified args]; otherwise, false.
        public static bool IsAudioFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            var extension = Path.GetExtension(path);
            if (string.IsNullOrEmpty(extension))
            {
                return false;
            }
            return AudioFileExtensionsDictionary.ContainsKey(extension);
        }
        /// 
        /// Determines whether [is video file] [the specified path].
        /// 
        /// The path.
        /// true if [is video file] [the specified path]; otherwise, false.
        public static bool IsVideoFile(string path)
        {
            return MimeTypes.IsVideoFile(path);
        }
        /// 
        /// Determines whether [is place holder] [the specified path].
        /// 
        /// The path.
        /// true if [is place holder] [the specified path]; otherwise, false.
        /// path
        public static bool IsVideoPlaceHolder(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            var extension = Path.GetExtension(path);
            return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase);
        }
        /// 
        /// Determines whether [is multi disc album folder] [the specified path].
        /// 
        /// The path.
        /// true if [is multi disc album folder] [the specified path]; otherwise, false.
        public static bool IsMultiDiscAlbumFolder(string path)
        {
            var filename = Path.GetFileName(path);
            if (string.IsNullOrWhiteSpace(filename))
            {
                return false;
            }
            // Normalize
            // Remove whitespace
            filename = filename.Replace("-", " ");
            filename = filename.Replace(".", " ");
            filename = filename.Replace("(", " ");
            filename = filename.Replace(")", " ");
            filename = Regex.Replace(filename, @"\s+", " ");
            var prefixes = new[] { "disc", "cd", "disk", "vol", "volume" };
            filename = filename.TrimStart();
            foreach (var prefix in prefixes)
            {
                if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    var tmp = filename.Substring(prefix.Length);
                    tmp = tmp.Trim().Split(' ').FirstOrDefault() ?? string.Empty;
                    int val;
                    if (int.TryParse(tmp, NumberStyles.Any, CultureInfo.InvariantCulture, out val))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// 
        /// Ensures DateCreated and DateModified have values
        /// 
        /// The file system.
        /// The item.
        /// The args.
        /// if set to true [include creation time].
        public static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args, bool includeCreationTime)
        {
            if (fileSystem == null)
            {
                throw new ArgumentNullException("fileSystem");
            }
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            // See if a different path came out of the resolver than what went in
            if (!string.Equals(args.Path, item.Path, StringComparison.OrdinalIgnoreCase))
            {
                var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null;
                if (childData != null)
                {
                    if (includeCreationTime)
                    {
                        SetDateCreated(item, fileSystem, childData);
                    }
                    item.DateModified = fileSystem.GetLastWriteTimeUtc(childData);
                }
                else
                {
                    var fileData = fileSystem.GetFileSystemInfo(item.Path);
                    if (fileData.Exists)
                    {
                        if (includeCreationTime)
                        {
                            SetDateCreated(item, fileSystem, fileData);
                        }
                        item.DateModified = fileSystem.GetLastWriteTimeUtc(fileData);
                    }
                }
            }
            else
            {
                if (includeCreationTime)
                {
                    SetDateCreated(item, fileSystem, args.FileInfo);
                }
                item.DateModified = fileSystem.GetLastWriteTimeUtc(args.FileInfo);
            }
        }
        private static void SetDateCreated(BaseItem item, IFileSystem fileSystem, FileSystemInfo info)
        {
            var config = BaseItem.ConfigurationManager.GetMetadataConfiguration();
            if (config.UseFileCreationTimeForDateAdded)
            {
                item.DateCreated = fileSystem.GetCreationTimeUtc(info);
            }
            else
            {
                item.DateCreated = DateTime.UtcNow;
            }
        }
    }
}