using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers.Movies;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
///
/// Class MovieResolver
///
public class MovieResolver : BaseVideoResolver
{
private IServerApplicationPaths ApplicationPaths { get; set; }
public MovieResolver(IServerApplicationPaths appPaths)
{
ApplicationPaths = appPaths;
}
///
/// Gets the priority.
///
/// The priority.
public override ResolverPriority Priority
{
get
{
// Give plugins a chance to catch iso's first
// Also since we have to loop through child files looking for videos,
// see if we can avoid some of that by letting other resolvers claim folders first
return ResolverPriority.Second;
}
}
///
/// Resolves the specified args.
///
/// The args.
/// Movie.
protected override Movie Resolve(ItemResolveArgs args)
{
// Must be a directory and under a 'Movies' VF
if (args.IsDirectory)
{
// Avoid expensive tests against VF's and all their children by not allowing this
if (args.Parent == null || args.Parent.IsRoot)
{
return null;
}
// If the parent is not a boxset, the only other allowed parent type is Folder
if (!(args.Parent is BoxSet))
{
if (args.Parent.GetType() != typeof(Folder))
{
return null;
}
}
// Optimization to avoid running all these tests against Top folders
if (args.Parent != null && args.Parent.IsRoot)
{
return null;
}
// The movie must be a video file
return FindMovie(args);
}
return null;
}
///
/// Sets the initial item values.
///
/// The item.
/// The args.
protected override void SetInitialItemValues(Movie item, ItemResolveArgs args)
{
base.SetInitialItemValues(item, args);
SetProviderIdFromPath(item);
}
///
/// Sets the provider id from path.
///
/// The item.
private void SetProviderIdFromPath(Movie item)
{
//we need to only look at the name of this actual item (not parents)
var justName = Path.GetFileName(item.Path);
var id = justName.GetAttributeValue("tmdbid");
if (!string.IsNullOrEmpty(id))
{
item.SetProviderId(MetadataProviders.Tmdb, id);
}
}
///
/// Finds a movie based on a child file system entries
///
/// The args.
/// Movie.
private Movie FindMovie(ItemResolveArgs args)
{
// Since the looping is expensive, this is an optimization to help us avoid it
if (args.ContainsMetaFileByName("series.xml") || args.Path.IndexOf("[tvdbid", StringComparison.OrdinalIgnoreCase) != -1)
{
return null;
}
// Optimization to avoid having to resolve every file
bool? isKnownMovie = null;
var movies = new List();
// Loop through each child file/folder and see if we find a video
foreach (var child in args.FileSystemChildren)
{
if (child.Attributes.HasFlag(FileAttributes.Directory))
{
if (IsDvdDirectory(child.Name))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.Dvd
};
}
if (IsBluRayDirectory(child.Name))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.BluRay
};
}
if (IsHdDvdDirectory(child.Name))
{
return new Movie
{
Path = args.Path,
VideoType = VideoType.HdDvd
};
}
continue;
}
// Don't misidentify xbmc trailers as a movie
if (child.Name.IndexOf(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) != -1)
{
continue;
}
var childArgs = new ItemResolveArgs(ApplicationPaths)
{
FileInfo = child,
Path = child.FullName
};
var item = base.Resolve(childArgs);
if (item != null)
{
// If we already know it's a movie, we can stop looping
if (!isKnownMovie.HasValue)
{
isKnownMovie = args.ContainsMetaFileByName("movie.xml") || args.ContainsMetaFileByName(MovieDbProvider.LocalMetaFileName) || args.Path.IndexOf("[tmdbid", StringComparison.OrdinalIgnoreCase) != -1;
}
if (isKnownMovie.Value)
{
return item;
}
movies.Add(item);
}
}
// If there are multiple video files, return null, and let the VideoResolver catch them later as plain videos
return movies.Count == 1 ? movies[0] : null;
}
///
/// Determines whether [is DVD directory] [the specified directory name].
///
/// Name of the directory.
/// true if [is DVD directory] [the specified directory name]; otherwise, false.
private bool IsDvdDirectory(string directoryName)
{
return directoryName.Equals("video_ts", StringComparison.OrdinalIgnoreCase);
}
///
/// Determines whether [is hd DVD directory] [the specified directory name].
///
/// Name of the directory.
/// true if [is hd DVD directory] [the specified directory name]; otherwise, false.
private bool IsHdDvdDirectory(string directoryName)
{
return directoryName.Equals("hvdvd_ts", StringComparison.OrdinalIgnoreCase);
}
///
/// Determines whether [is blu ray directory] [the specified directory name].
///
/// Name of the directory.
/// true if [is blu ray directory] [the specified directory name]; otherwise, false.
private bool IsBluRayDirectory(string directoryName)
{
return directoryName.Equals("bdmv", StringComparison.OrdinalIgnoreCase);
}
}
}