using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Common.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Library
{
    public class ItemController
    {
        //private BaseItem ResolveItem(ItemResolveEventArgs args)
        //{
        //    // Try first priority resolvers
        //    for (int i = 0; i < Kernel.Instance.EntityResolvers.Length; i++)
        //    {
        //        var item = Kernel.Instance.EntityResolvers[i].ResolvePath(args);
        //        if (item != null)
        //        {
        //            return item;
        //        }
        //    }
        //    return null;
        //}
        /// 
        /// Resolves a path into a BaseItem
        /// 
        public async Task GetItem(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null, bool allowInternetProviders = true)
        {
            var args = new ItemResolveEventArgs
            {
                FileInfo = fileInfo ?? FileData.GetFileData(path),
                Parent = parent,
                Cancel = false,
                Path = path
            };
            // Gather child folder and files
            if (args.IsDirectory)
            {
                args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray();
                bool isVirtualFolder = parent != null && parent.IsRoot;
                args = FileSystemHelper.FilterChildFileSystemEntries(args, isVirtualFolder);
            }
            else
            {
                args.FileSystemChildren = new WIN32_FIND_DATA[] { };
            }
            // Fire BeginResolvePath to see if anyone wants to cancel this operation
            if (!EntityResolutionHelper.ShouldResolvePathContents(args))
            {
                return null;
            }
            BaseItem item = Kernel.Instance.ResolveItem(args);
            return item;
        }
        ///// 
        ///// Finds child BaseItems for a given Folder
        ///// 
        //private Task[] GetChildren(Folder folder, WIN32_FIND_DATA[] fileSystemChildren, bool allowInternetProviders)
        //{
        //    Task[] tasks = new Task[fileSystemChildren.Length];
        //    for (int i = 0; i < fileSystemChildren.Length; i++)
        //    {
        //        var child = fileSystemChildren[i];
        //        tasks[i] = GetItem(child.Path, folder, child, allowInternetProviders: allowInternetProviders);
        //    }
        //    return tasks;
        //}
        ///// 
        ///// Transforms shortcuts into their actual paths
        ///// 
        //private WIN32_FIND_DATA[] FilterChildFileSystemEntries(WIN32_FIND_DATA[] fileSystemChildren, bool flattenShortcuts)
        //{
        //    WIN32_FIND_DATA[] returnArray = new WIN32_FIND_DATA[fileSystemChildren.Length];
        //    List resolvedShortcuts = new List();
        //    for (int i = 0; i < fileSystemChildren.Length; i++)
        //    {
        //        WIN32_FIND_DATA file = fileSystemChildren[i];
        //        // If it's a shortcut, resolve it
        //        if (Shortcut.IsShortcut(file.Path))
        //        {
        //            string newPath = Shortcut.ResolveShortcut(file.Path);
        //            WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath);
        //            // Find out if the shortcut is pointing to a directory or file
        //            if (newPathData.IsDirectory)
        //            {
        //                // If we're flattening then get the shortcut's children
        //                if (flattenShortcuts)
        //                {
        //                    returnArray[i] = file;
        //                    WIN32_FIND_DATA[] newChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray();
        //                    resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newChildren, false));
        //                }
        //                else
        //                {
        //                    returnArray[i] = newPathData;
        //                }
        //            }
        //            else
        //            {
        //                returnArray[i] = newPathData;
        //            }
        //        }
        //        else
        //        {
        //            returnArray[i] = file;
        //        }
        //    }
        //    if (resolvedShortcuts.Count > 0)
        //    {
        //        resolvedShortcuts.InsertRange(0, returnArray);
        //        return resolvedShortcuts.ToArray();
        //    }
        //    else
        //    {
        //        return returnArray;
        //    }
        //}
        /// 
        /// Gets a Person
        /// 
        public Task GetPerson(string name)
        {
            return GetImagesByNameItem(Kernel.Instance.ApplicationPaths.PeoplePath, name);
        }
        /// 
        /// Gets a Studio
        /// 
        public Task GetStudio(string name)
        {
            return GetImagesByNameItem(Kernel.Instance.ApplicationPaths.StudioPath, name);
        }
        /// 
        /// Gets a Genre
        /// 
        public Task GetGenre(string name)
        {
            return GetImagesByNameItem(Kernel.Instance.ApplicationPaths.GenrePath, name);
        }
        /// 
        /// Gets a Year
        /// 
        public Task GetYear(int value)
        {
            return GetImagesByNameItem(Kernel.Instance.ApplicationPaths.YearPath, value.ToString());
        }
        private readonly ConcurrentDictionary ImagesByNameItemCache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
        /// 
        /// Generically retrieves an IBN item
        /// 
        private Task GetImagesByNameItem(string path, string name)
            where T : BaseEntity, new()
        {
            name = FileData.GetValidFilename(name);
            path = Path.Combine(path, name);
            // Look for it in the cache, if it's not there, create it
            if (!ImagesByNameItemCache.ContainsKey(path))
            {
                ImagesByNameItemCache[path] = CreateImagesByNameItem(path, name);
            }
            return ImagesByNameItemCache[path] as Task;
        }
        /// 
        /// Creates an IBN item based on a given path
        /// 
        private async Task CreateImagesByNameItem(string path, string name)
            where T : BaseEntity, new()
        {
            var item = new T { };
            item.Name = name;
            item.Id = path.GetMD5();
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            item.DateCreated = Directory.GetCreationTimeUtc(path);
            item.DateModified = Directory.GetLastWriteTimeUtc(path);
            var args = new ItemResolveEventArgs { };
            args.FileInfo = FileData.GetFileData(path);
            args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray();
            await Kernel.Instance.ExecuteMetadataProviders(item).ConfigureAwait(false);
            return item;
        }
    }
}