public override void Fetch()
        {
            var movie = Item as IMovie;
            Debug.Assert(movie != null);

            string mfile = XmlLocation();
            string location = Path.GetDirectoryName(mfile);
            if (File.Exists(mfile))
            {

                DateTime modTime = new FileInfo(mfile).LastWriteTimeUtc;
                lastWriteTime = modTime;
                myMovieFile = mfile;
                XmlDocument doc = new XmlDocument();
                doc.Load(mfile);

                string s = doc.SafeGetString("Title/LocalTitle");
                if ((s == null) || (s == ""))
                    s = doc.SafeGetString("Title/OriginalTitle");
                movie.Name = s;
                movie.SortName = doc.SafeGetString("Title/SortTitle");

                movie.Overview = doc.SafeGetString("Title/Description");
                if (movie.Overview != null)
                    movie.Overview = movie.Overview.Replace("\n\n", "\n");

                movie.TagLine = doc.SafeGetString("Title/TagLine");
                movie.Plot = doc.SafeGetString("Title/Plot");

                //if added date is in xml override the file/folder date - this isn't gonna work cuz it's already filled in...
                DateTime added = DateTime.MinValue;
                DateTime.TryParse(doc.SafeGetString("Title/Added"), out added);
                if (added > DateTime.MinValue) movie.DateCreated = added;


                string front = doc.SafeGetString("Title/Covers/Front");
                if ((front != null) && (front.Length > 0))
                {
                    front = Path.Combine(location, front);
                    if (File.Exists(front))
                        Item.PrimaryImagePath = front;
                }

                if (string.IsNullOrEmpty(movie.DisplayMediaType))
                {
                    movie.DisplayMediaType = doc.SafeGetString("Title/Type", "");
                    switch (movie.DisplayMediaType.ToLower())
                    {
                        case "blu-ray":
                            movie.DisplayMediaType = MediaType.BluRay.ToString();
                            break;
                        case "dvd":
                            movie.DisplayMediaType = MediaType.DVD.ToString();
                            break;
                        case "hd dvd":
                            movie.DisplayMediaType = MediaType.HDDVD.ToString();
                            break;
                        case "":
                            movie.DisplayMediaType = null;
                            break;
                    }
                }
                if (movie.ProductionYear == null)
                {
                    int y = doc.SafeGetInt32("Title/ProductionYear", 0);
                    if (y > 1850)
                        movie.ProductionYear = y;
                }
                if (movie.ImdbRating == null)
                {
                    float i = doc.SafeGetSingle("Title/IMDBrating", (float)-1, (float)10);
                    if (i >= 0)
                        movie.ImdbRating = i;
                }
                if (movie.ImdbID == null)
                {
                    if (!string.IsNullOrEmpty(doc.SafeGetString("Title/IMDB")))
                    {
                        movie.ImdbID = doc.SafeGetString("Title/IMDB");
                    }
                    else
                    {
                        movie.ImdbID = doc.SafeGetString("Title/IMDbId");
                    }
                }
                if (movie.TmdbID == null)
                {
                    movie.TmdbID = doc.SafeGetString("Title/TMDbId");
                }

                foreach (XmlNode node in doc.SelectNodes("Title/Persons/Person[Type='Actor']"))
                {
                    try
                    {
                        if (movie.Actors == null)
                            movie.Actors = new List<Actor>();

                        var name = node.SelectSingleNode("Name").InnerText;
                        var role = node.SafeGetString("Role", "");
                        var actor = new Actor() { Name = name, Role = role };

                        movie.Actors.Add(actor);
                    }
                    catch
                    {
                        // fall through i dont care, one less actor
                    }
                }


                foreach (XmlNode node in doc.SelectNodes("Title/Persons/Person[Type='Director']"))
                {
                    try
                    {
                        if (movie.Directors == null)
                            movie.Directors = new List<string>();
                        movie.Directors.Add(node.SelectSingleNode("Name").InnerText);
                    }
                    catch
                    {
                        // fall through i dont care, one less director
                    }
                }


                foreach (XmlNode node in doc.SelectNodes("Title/Genres/Genre"))
                {
                    try
                    {
                        if (movie.Genres == null)
                            movie.Genres = new List<string>();
                        movie.Genres.Add(node.InnerText);
                    }
                    catch
                    {
                        // fall through i dont care, one less genre
                    }
                }


                foreach (XmlNode node in doc.SelectNodes("Title/Studios/Studio"))
                {
                    try
                    {
                        if (movie.Studios == null)
                            movie.Studios = new List<string>();
                        movie.Studios.Add(node.InnerText);
                        //movie.Studios.Add(new Studio { Name = node.InnerText });                        
                    }
                    catch
                    {
                        // fall through i dont care, one less actor
                    }
                }

                if (movie.TrailerPath == null)
                    movie.TrailerPath = doc.SafeGetString("Title/LocalTrailer/URL");

                if (movie.MpaaRating == null)
                    movie.MpaaRating = doc.SafeGetString("Title/MPAARating");

                if (movie.MpaaRating == null)
                {
                    int i = doc.SafeGetInt32("Title/ParentalRating/Value", (int)7);
                    switch (i)
                    {
                        case -1:
                            movie.MpaaRating = "NR";
                            break;
                        case 0:
                            movie.MpaaRating = "UR";
                            break;
                        case 1:
                            movie.MpaaRating = "G";
                            break;
                        case 3:
                            movie.MpaaRating = "PG";
                            break;
                        case 4:
                            movie.MpaaRating = "PG-13";
                            break;
                        case 5:
                            movie.MpaaRating = "NC-17";
                            break;
                        case 6:
                            movie.MpaaRating = "R";
                            break;
                        default:
                            movie.MpaaRating = null;
                            break;
                    }
                }
                //if there is a custom rating - use it (if not rating will be filled with MPAARating)
                if (movie.CustomRating == null)
                    movie.CustomRating = doc.SafeGetString("Title/CustomRating");

                if (movie.CustomPIN == null)
                    movie.CustomPIN = doc.SafeGetString("Title/CustomPIN");

                if (movie.AspectRatio == null)
                    movie.AspectRatio = doc.SafeGetString("Title/AspectRatio");

                //MetaBrowser Custom MediaInfo Support
                if (movie.MediaInfo == null) movie.MediaInfo = new MediaInfoData();
                //we need to decode metabrowser strings to format and profile
                string audio = doc.SafeGetString("Title/MediaInfo/Audio/Codec", "");
                if (audio != "")
                {
                    switch (audio.ToLower())
                    {
                        case "dts-es":
                        case "dts-es matrix":
                        case "dts-es discrete":
                            movie.MediaInfo.OverrideData.AudioFormat = "DTS";
                            movie.MediaInfo.OverrideData.AudioProfile = "ES";
                            break;
                        case "dts-hd hra":
                        case "dts-hd high resolution":
                            movie.MediaInfo.OverrideData.AudioFormat = "DTS";
                            movie.MediaInfo.OverrideData.AudioProfile = "HRA";
                            break;
                        case "dts-hd ma":
                        case "dts-hd master":
                            movie.MediaInfo.OverrideData.AudioFormat = "DTS";
                            movie.MediaInfo.OverrideData.AudioProfile = "MA";
                            break;
                        case "dolby digital":
                        case "dolby digital surround ex":
                        case "dolby surround":
                            movie.MediaInfo.OverrideData.AudioFormat = "AC-3";
                            break;
                        case "dolby digital plus":
                            movie.MediaInfo.OverrideData.AudioFormat = "E-AC-3";
                            break;
                        case "dolby truehd":
                            movie.MediaInfo.OverrideData.AudioFormat = "AC-3";
                            movie.MediaInfo.OverrideData.AudioProfile = "TrueHD";
                            break;
                        case "mp2":
                            movie.MediaInfo.OverrideData.AudioFormat = "MPEG Audio";
                            movie.MediaInfo.OverrideData.AudioProfile = "Layer 2";
                            break;
                        case "other":
                            break;
                        default:
                            movie.MediaInfo.OverrideData.AudioFormat = audio;
                            break;
                    }
                }
                movie.MediaInfo.OverrideData.AudioStreamCount = doc.SelectNodes("Title/MediaInfo/Audio/Codec[text() != '']").Count;
                movie.MediaInfo.OverrideData.AudioChannelCount = doc.SafeGetString("Title/MediaInfo/Audio/Channels", "");
                movie.MediaInfo.OverrideData.AudioBitRate = doc.SafeGetInt32("Title/MediaInfo/Audio/BitRate");
                string video = doc.SafeGetString("Title/MediaInfo/Video/Codec", "");
                if (video != "")
                {
                    switch (video.ToLower())
                    {
                        case "sorenson h.263":
                            movie.MediaInfo.OverrideData.VideoCodec = "Sorenson H263";
                            break;
                        case "h.262":
                            movie.MediaInfo.OverrideData.VideoCodec = "MPEG-2 Video";
                            break;
                        case "h.264":
                            movie.MediaInfo.OverrideData.VideoCodec = "AVC";
                            break;
                        default:
                            movie.MediaInfo.OverrideData.VideoCodec = video;
                            break;
                    }
                }
                movie.MediaInfo.OverrideData.VideoBitRate = doc.SafeGetInt32("Title/MediaInfo/Video/BitRate");
                movie.MediaInfo.OverrideData.Height = doc.SafeGetInt32("Title/MediaInfo/Video/Height");
                movie.MediaInfo.OverrideData.Width = doc.SafeGetInt32("Title/MediaInfo/Video/Width");
                movie.MediaInfo.OverrideData.ScanType = doc.SafeGetString("Title/MediaInfo/Video/ScanType", "");
                movie.MediaInfo.OverrideData.VideoFPS = doc.SafeGetString("Title/MediaInfo/Video/FrameRate", "");
                int rt = doc.SafeGetInt32("Title/MediaInfo/Video/Duration", 0);
                if (rt > 0)
                    movie.MediaInfo.OverrideData.RunTime = rt;
                else
                    movie.MediaInfo.OverrideData.RunTime = doc.SafeGetInt32("Title/RunningTime", 0);
                if (movie.MediaInfo.RunTime > 0) movie.RunningTime = movie.MediaInfo.RunTime;

                XmlNodeList nodes = doc.SelectNodes("Title/MediaInfo/Audio/Language");
                List<string> Langs = new List<string>();
                foreach (XmlNode node in nodes)
                {
                    string m = node.InnerText;
                    if (!string.IsNullOrEmpty(m))
                        Langs.Add(m);
                }
                if (Langs.Count > 1)
                {
                    movie.MediaInfo.OverrideData.AudioLanguages = String.Join(" / ", Langs.ToArray());
                }
                else
                {
                    movie.MediaInfo.OverrideData.AudioLanguages = doc.SafeGetString("Title/MediaInfo/Audio/Language", "");
                }
                nodes = doc.SelectNodes("Title/MediaInfo/Subtitle/Language");
                List<string> Subs = new List<string>();
                foreach (XmlNode node in nodes)
                {
                    string n = node.InnerText;
                    if (!string.IsNullOrEmpty(n))
                        Subs.Add(n);
                }
                if (Subs.Count > 1)
                {
                    movie.MediaInfo.OverrideData.Subtitles = String.Join(" / ", Subs.ToArray());
                }
                else
                {
                    movie.MediaInfo.OverrideData.Subtitles = doc.SafeGetString("Title/MediaInfo/Subtitle/Language", "");
                }
            }
        }
        /// <summary>
        /// Fetches the episode data.
        /// </summary>
        /// <param name="seriesXml">The series XML.</param>
        /// <param name="episode">The episode.</param>
        /// <param name="seriesId">The series id.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task{System.Boolean}.</returns>
        private async Task<ProviderRefreshStatus> FetchEpisodeData(XmlDocument seriesXml, Episode episode, string seriesId, CancellationToken cancellationToken)
        {
            var status = ProviderRefreshStatus.Success;

            if (episode.IndexNumber == null)
            {
                return status;
            }

            var seasonNumber = episode.ParentIndexNumber ?? TVUtils.GetSeasonNumberFromEpisodeFile(episode.Path);

            if (seasonNumber == null)
            {
                return status;
            }

            var usingAbsoluteData = false;

            var episodeNode = seriesXml.SelectSingleNode("//Episode[EpisodeNumber='" + episode.IndexNumber.Value + "'][SeasonNumber='" + seasonNumber.Value + "']");

            if (episodeNode == null)
            {
                if (seasonNumber.Value == 1)
                {
                    episodeNode = seriesXml.SelectSingleNode("//Episode[absolute_number='" + episode.IndexNumber.Value + "']");
                    usingAbsoluteData = true;
                }
            }

            // If still null, nothing we can do
            if (episodeNode == null)
            {
                return status;
            }
            IEnumerable<XmlDocument> extraEpisodesNode = new XmlDocument[] { };

            if (episode.IndexNumberEnd.HasValue)
            {
                var seriesXDocument = XDocument.Load(new XmlNodeReader(seriesXml));
                if (usingAbsoluteData)
                {
                    extraEpisodesNode =
                        seriesXDocument.Descendants("Episode")
                                       .Where(
                                           x =>
                                           int.Parse(x.Element("absolute_number").Value) > episode.IndexNumber &&
                                           int.Parse(x.Element("absolute_number").Value) <= episode.IndexNumberEnd.Value).OrderBy(x => x.Element("absolute_number").Value).Select(x => x.ToXmlDocument());
                }
                else
                {
                    var all =
                        seriesXDocument.Descendants("Episode").Where(x => int.Parse(x.Element("SeasonNumber").Value) == seasonNumber.Value);

                    var xElements = all.Where(x => int.Parse(x.Element("EpisodeNumber").Value) > episode.IndexNumber && int.Parse(x.Element("EpisodeNumber").Value) <= episode.IndexNumberEnd.Value);
                    extraEpisodesNode = xElements.OrderBy(x => x.Element("EpisodeNumber").Value).Select(x => x.ToXmlDocument());
                }

            }
            var doc = new XmlDocument();
            doc.LoadXml(episodeNode.OuterXml);

            if (!episode.HasImage(ImageType.Primary))
            {
                var p = doc.SafeGetString("//filename");
                if (p != null)
                {
                    try
                    {
                        var url = TVUtils.BannerUrl + p;

                        await _providerManager.SaveImage(episode, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken)
                          .ConfigureAwait(false);
                    }
                    catch (HttpException)
                    {
                        status = ProviderRefreshStatus.CompletedWithErrors;
                    }
                }
            }
            if (!episode.LockedFields.Contains(MetadataFields.Overview))
            {
                var extraOverview = extraEpisodesNode.Aggregate("", (current, xmlDocument) => current + ("\r\n\r\n" + xmlDocument.SafeGetString("//Overview")));
                episode.Overview = doc.SafeGetString("//Overview") + extraOverview;
            }
            if (usingAbsoluteData)
                episode.IndexNumber = doc.SafeGetInt32("//absolute_number", -1);
            if (episode.IndexNumber < 0)
                episode.IndexNumber = doc.SafeGetInt32("//EpisodeNumber");
            if (!episode.LockedFields.Contains(MetadataFields.Name))
            {
                var extraNames = extraEpisodesNode.Aggregate("", (current, xmlDocument) => current + (", " + xmlDocument.SafeGetString("//EpisodeName")));
                episode.Name = doc.SafeGetString("//EpisodeName") + extraNames;
            }
            episode.CommunityRating = doc.SafeGetSingle("//Rating", -1, 10);
            var firstAired = doc.SafeGetString("//FirstAired");
            DateTime airDate;
            if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
            {
                episode.PremiereDate = airDate.ToUniversalTime();
                episode.ProductionYear = airDate.Year;
            }
            if (!episode.LockedFields.Contains(MetadataFields.Cast))
            {
                episode.People.Clear();

                var actors = doc.SafeGetString("//GuestStars");
                if (actors != null)
                {
                    // Sometimes tvdb actors have leading spaces
                    //Regex Info:
                    //The first block are the posible delimitators (open-parentheses should be there cause if dont the next block will fail)
                    //The second block Allow the delimitators to be part of the text if they're inside parentheses
                    var persons = Regex.Matches(actors, @"(?<delimitators>([^|,(])|(?<ignoreinParentheses>\([^)]*\)*))+")
                        .Cast<Match>()
                        .Select(m => m.Value)
                        .Where(i => !string.IsNullOrWhiteSpace(i) && !string.IsNullOrEmpty(i));

                    foreach (var person in persons.Select(str =>
                    {
                        var nameGroup = str.Split(new[] { '(' }, 2, StringSplitOptions.RemoveEmptyEntries);
                        var name = nameGroup[0].Trim();
                        var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
                        if (roles != null)
                            roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
                        return new PersonInfo { Type = PersonType.GuestStar, Name = name, Role = roles };
                    }))
                    {
                        episode.AddPerson(person);
                    }
                }
                foreach (var xmlDocument in extraEpisodesNode)
                {
                    var extraActors = xmlDocument.SafeGetString("//GuestStars");
                    if (extraActors == null) continue;
                    // Sometimes tvdb actors have leading spaces
                    var persons = Regex.Matches(extraActors, @"(?<delimitators>([^|,(])|(?<ignoreinParentheses>\([^)]*\)*))+")
                        .Cast<Match>()
                        .Select(m => m.Value)
                        .Where(i => !string.IsNullOrWhiteSpace(i) && !string.IsNullOrEmpty(i));

                    foreach (var person in persons.Select(str =>
                    {
                        var nameGroup = str.Split(new[] { '(' }, 2, StringSplitOptions.RemoveEmptyEntries);
                        var name = nameGroup[0].Trim();
                        var roles = nameGroup.Count() > 1 ? nameGroup[1].Trim() : null;
                        if (roles != null)
                            roles = roles.EndsWith(")") ? roles.Substring(0, roles.Length - 1) : roles;
                        return new PersonInfo { Type = PersonType.GuestStar, Name = name, Role = roles };
                    }))
                    {
                        episode.AddPerson(person);
                    }
                }

                var directors = doc.SafeGetString("//Director");
                if (directors != null)
                {
                    // Sometimes tvdb actors have leading spaces
                    foreach (var person in directors.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                    .Where(i => !string.IsNullOrWhiteSpace(i))
                                                    .Select(str => new PersonInfo { Type = PersonType.Director, Name = str.Trim() }))
                    {
                        episode.AddPerson(person);
                    }
                }


                var writers = doc.SafeGetString("//Writer");
                if (writers != null)
                {
                    // Sometimes tvdb actors have leading spaces
                    foreach (var person in writers.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                  .Where(i => !string.IsNullOrWhiteSpace(i))
                                                  .Select(str => new PersonInfo { Type = PersonType.Writer, Name = str.Trim() }))
                    {
                        episode.AddPerson(person);
                    }
                }
            }

            return status;
        }
        public Item GetSeriesDetails(Item item)
        {
            DataProviderId dp = item.ProvidersId.Find(p => p.Name == this.Name);
            if (dp == null) return null;
            if (!LoadSeriesDetails(dp.Id))
                return null;
            Item series = new Item();
            series.ProvidersId = new List<DataProviderId> { dp };

            XmlDocument doc = new XmlDocument();
            doc.Load(Path.Combine(Path.Combine(XmlPath, dp.Id), lang + ".xml"));
            if (doc == null) return null;

            series.Title = series.SeriesName = doc.SafeGetString("//SeriesName");
            series.Overview = doc.SafeGetString("//Overview");
            series.Rating = doc.SafeGetSingle("//Rating", 0, 10);
            series.RunningTime = doc.SafeGetInt32("//Runtime");
            series.MPAARating = doc.SafeGetString("//ContentRating");

            string g = doc.SafeGetString("//Genre");
            if (g != null)
            {
                string[] genres = g.Trim('|').Split('|');
                if (g.Length > 0)
                {
                    series.Genres = new List<string>();
                    series.Genres.AddRange(genres);
                }
            }

            XmlDocument actorsDoc = new XmlDocument();
            actorsDoc.Load(Path.Combine(Path.Combine(XmlPath, dp.Id), "actors.xml"));
            if (actorsDoc != null)
            {
                series.Actors = new List<Actor>();
                foreach (XmlNode actorNode in actorsDoc.SelectNodes("//Actor"))
                {
                    string name = actorNode.SafeGetString("Name");
                    if (!string.IsNullOrEmpty(name))
                    {
                        Actor actor = new Actor();
                        actor.Name = name;
                        actor.Role = actorNode.SafeGetString("Role");
                        actor.ImagePath = BannerUrl + actorNode.SafeGetString("Image");
                        if (series.Actors == null) series.Actors = new List<Actor>();
                        series.Actors.Add(actor);
                    }
                }
            }
            else
            {
                string actors = doc.SafeGetString("//Actors");
                if (actors != null)
                {
                    string[] a = actors.Trim('|').Split('|');
                    if (a.Length > 0)
                    {
                        series.Actors = new List<Actor>();
                        series.Actors.AddRange(
                            a.Select(actor => new Actor { Name = actor }));
                    }
                }
            }

            XmlDocument banners = new XmlDocument();
            banners.Load(Path.Combine(Path.Combine(XmlPath, dp.Id), "banners.xml"));
            if (banners != null)
            {
                series.BackdropImagePaths = new List<Poster>();
                series.ImagesPaths = new List<Poster>();
                series.BannersPaths = new List<Poster>();
                foreach (XmlNode node in banners.SelectNodes("//Banner"))
                {
                    if (node.SafeGetString("BannerType") == "poster")
                    {
                        Poster poster = new Poster();
                        string path = node.SafeGetString("BannerPath");
                        string thumb = node.SafeGetString("ThumbnailPath");
                        if (!string.IsNullOrEmpty(thumb))
                            poster.Thumb = BannerUrl + thumb;
                        poster.Image = BannerUrl + path;

                        if (!string.IsNullOrEmpty(path))
                            series.ImagesPaths.Add(poster);
                    }
                    else if (node.SafeGetString("BannerType") == "fanart")
                    {
                        Poster poster = new Poster();
                        poster.Checked = false;
                        string path = node.SafeGetString("BannerPath");
                        string thumb = node.SafeGetString("ThumbnailPath");
                        string size = node.SafeGetString("BannerType2");
                        if (size.Contains("x"))
                        {
                            poster.width = size.Substring(0, size.IndexOf("x"));
                            poster.height = size.Substring(size.IndexOf("x") + 1);
                        }
                        if (!string.IsNullOrEmpty(thumb))
                            poster.Thumb = BannerUrl + thumb;
                        poster.Image = BannerUrl + path;
                        if (!string.IsNullOrEmpty(path))
                            series.BackdropImagePaths.Add(poster);
                    }
                    else if (node.SafeGetString("BannerType") == "series")
                    {
                        Poster poster = new Poster();
                        string path = node.SafeGetString("BannerPath");
                        poster.Image = BannerUrl + path;
                        if (!string.IsNullOrEmpty(path))
                            series.BannersPaths.Add(poster);
                    }
                }

            }

            return series;
        }
        public override void Fetch()
        {
            var movie = Item as Movie;
             Debug.Assert(movie != null);

            string mfile = XmlLocation();
            string location = Path.GetDirectoryName(mfile);
            if (File.Exists(mfile))
            {

                DateTime modTime = new FileInfo(mfile).LastWriteTimeUtc;
                lastWriteTime = modTime;
                myMovieFile = mfile;
                XmlDocument doc = new XmlDocument();
                doc.Load(mfile);

                string s = doc.SafeGetString("Title/LocalTitle");
                if ((s == null) || (s == ""))
                    s = doc.SafeGetString("Title/OriginalTitle");
                movie.Name = s;
                movie.SortName = doc.SafeGetString("Title/SortTitle");

                movie.Overview = doc.SafeGetString("Title/Description");
                if (movie.Overview != null)
                    movie.Overview = movie.Overview.Replace("\n\n", "\n");

                string front = doc.SafeGetString("Title/Covers/Front");
                if ((front != null) && (front.Length > 0))
                {
                    front = Path.Combine(location, front);
                    if (File.Exists(front))
                        Item.PrimaryImagePath = front;
                }

                string back = doc.SafeGetString("Title/Covers/Back");
                if ((back != null) && (back.Length > 0))
                {
                    back = Path.Combine(location, back);
                    if (File.Exists(back))
                        Item.SecondaryImagePath = back;
                }

                if (movie.RunningTime == null)
                {
                    int rt = doc.SafeGetInt32("Title/RunningTime",0);
                    if (rt > 0)
                        movie.RunningTime = rt;
                }
                if (movie.ProductionYear == null)
                {
                    int y = doc.SafeGetInt32("Title/ProductionYear",0);
                    if (y > 1900)
                        movie.ProductionYear = y;
                }
                if (movie.ImdbRating == null)
                {
                    float i = doc.SafeGetSingle("Title/IMDBrating", (float)-1, (float)10);
                    if (i >= 0)
                        movie.ImdbRating = i;
                }

                foreach (XmlNode node in doc.SelectNodes("Title/Persons/Person[Type='Actor']"))
                {
                    try
                    {
                        if (movie.Actors == null)
                            movie.Actors = new List<Actor>();
                        movie.Actors.Add(new Actor { Name = node.SelectSingleNode("Name").InnerText, Role = node.SelectSingleNode("Role").InnerText });
                    }
                    catch
                    {
                        // fall through i dont care, one less actor
                    }
                }

                foreach (XmlNode node in doc.SelectNodes("Title/Persons/Person[Type='Director']"))
                {
                    try
                    {
                        if (movie.Directors == null)
                            movie.Directors = new List<string>();
                        movie.Directors.Add(node.SelectSingleNode("Name").InnerText);
                    }
                    catch
                    {
                        // fall through i dont care, one less director
                    }
                }

                foreach (XmlNode node in doc.SelectNodes("Title/Genres/Genre"))
                {
                    try
                    {
                        if (movie.Genres == null)
                            movie.Genres = new List<string>();
                        movie.Genres.Add(node.InnerText);
                    }
                    catch
                    {
                        // fall through i dont care, one less genre
                    }
                }

                foreach (XmlNode node in doc.SelectNodes("Title/Studios/Studio"))
                {
                    try
                    {
                        if (movie.Studios == null)
                            movie.Studios = new List<string>();
                        movie.Studios.Add(node.InnerText);
                    }
                    catch
                    {
                        // fall through i dont care, one less actor
                    }
                }

                if (movie.TrailerPath == null)
                    movie.TrailerPath = doc.SafeGetString("Title/LocalTrailer/URL");

                if (movie.MpaaRating == null)
                    movie.MpaaRating = doc.SafeGetString("Title/MPAARating");

                if (movie.MpaaRating == null)
                {
                    int i = doc.SafeGetInt32("Title/ParentalRating/Value", (int)7);
                    switch (i) {
                        case -1:
                            movie.MpaaRating = "NR";
                            break;
                        case 0:
                            movie.MpaaRating = "NR";
                            break;
                        case 1:
                            movie.MpaaRating = "G";
                            break;
                        case 3:
                            movie.MpaaRating = "PG";
                            break;
                        case 4:
                            movie.MpaaRating = "PG-13";
                            break;
                        case 5:
                            movie.MpaaRating = "NC-17";
                            break;
                        case 6:
                            movie.MpaaRating = "R";
                            break;
                        default:
                            movie.MpaaRating = null;
                            break;
                    }
                }
            }
        }
        protected virtual void ProcessDocument(XmlDocument doc, bool ignoreImages)
        {
            Movie movie = Item as Movie;
            if (doc != null)
            {
                // This is problematic for foreign films we want to keep the alt title.
                //if (store.Name == null)
                //    store.Name = doc.SafeGetString("//movie/title");

                movie.Name = doc.SafeGetString("//movie/name");

                movie.Overview = doc.SafeGetString("//movie/overview");
                if (movie.Overview != null)
                    movie.Overview = movie.Overview.Replace("\n\n", "\n");

                movie.TagLine = doc.SafeGetString("//movie/tagline");
                movie.ImdbID = doc.SafeGetString("//movie/imdb_id");

                movie.ImdbRating = doc.SafeGetSingle("//movie/rating", -1, 10);

                string release = doc.SafeGetString("//movie/released");
                if (!string.IsNullOrEmpty(release))
                    movie.ProductionYear = Int32.Parse(release.Substring(0, 4));

                movie.RunningTime = doc.SafeGetInt32("//movie/runtime");
                if (movie.MediaInfo != null && movie.MediaInfo.RunTime > 0) movie.RunningTime = movie.MediaInfo.RunTime;

                movie.MpaaRating = doc.SafeGetString("//movie/certification");

                movie.Studios = null;
                foreach (XmlNode n in doc.SelectNodes("//studios/studio"))
                {
                    if (movie.Studios == null)
                        movie.Studios = new List<string>();
                    string name = n.SafeGetString("@name");
                    if (!string.IsNullOrEmpty(name))
                        movie.Studios.Add(name);
                }

                movie.Directors = null;
                foreach (XmlNode n in doc.SelectNodes("//cast/person[@job='Director']"))
                {
                    if (movie.Directors == null)
                        movie.Directors = new List<string>();
                    string name = n.SafeGetString("@name");
                    if (!string.IsNullOrEmpty(name))
                        movie.Directors.Add(name);
                }

                movie.Writers = null;
                foreach (XmlNode n in doc.SelectNodes("//cast/person[@job='Author']"))
                {
                    if (movie.Writers == null)
                        movie.Writers = new List<string>();
                    string name = n.SafeGetString("@name");
                    if (!string.IsNullOrEmpty(name))
                        movie.Writers.Add(name);
                }

                movie.Actors = null;
                foreach (XmlNode n in doc.SelectNodes("//cast/person[@job='Actor']"))
                {
                    if (movie.Actors == null)
                        movie.Actors = new List<Actor>();
                    string name = n.SafeGetString("@name");
                    string role = n.SafeGetString("@character");
                    if (!string.IsNullOrEmpty(name))
                        movie.Actors.Add(new Actor { Name = name, Role = role });
                }

                XmlNodeList nodes = doc.SelectNodes("//movie/categories/category[@type='genre']/@name");
                List<string> genres = new List<string>();
                foreach (XmlNode node in nodes)
                {
                    string n = MapGenre(node.InnerText);
                    if ((!string.IsNullOrEmpty(n)) && (!genres.Contains(n)))
                        genres.Add(n);
                }
                movie.Genres = genres;

                if (!ignoreImages)
                {
                    string img = doc.SafeGetString("//movie/images/image[@type='poster' and @size='" + Kernel.Instance.ConfigData.FetchedPosterSize + "']/@url");
                    if (img == null)
                    {
                        img = doc.SafeGetString("//movie/images/image[@type='poster' and @size='original']/@url"); //couldn't find preferred size
                    }
                    if (img != null)
                    {
                        if (Kernel.Instance.ConfigData.SaveLocalMeta)
                        {
                            //download and save locally
                            RemoteImage cover = new RemoteImage() { Path = img };
                            string ext = Path.GetExtension(img).ToLower();
                            string fn = (Path.Combine(Item.Path,"folder" + ext));
                            try
                            {
                                Kernel.IgnoreFileSystemMods = true;
                                cover.DownloadImage().Save(fn, ext == ".png" ? System.Drawing.Imaging.ImageFormat.Png : System.Drawing.Imaging.ImageFormat.Jpeg);
                                Kernel.IgnoreFileSystemMods = false;
                                movie.PrimaryImagePath = fn;
                            }
                            catch (Exception e)
                            {
                                Logger.ReportException("Error downloading and saving image " + fn, e);
                            }
                        }
                        else
                        {
                            movie.PrimaryImagePath = img;
                        }
                    }
                    movie.BackdropImagePaths = new List<string>();
                    int bdNo = 0;
                    RemoteImage bd;
                    foreach (XmlNode n in doc.SelectNodes("//movie/images/image[@type='backdrop' and @size='original']/@url"))
                    {
                        if (Kernel.Instance.ConfigData.SaveLocalMeta)
                        {
                            bd = new RemoteImage() { Path = n.InnerText };
                            string ext = Path.GetExtension(n.InnerText).ToLower();
                            string fn = Path.Combine(Item.Path,"backdrop" + (bdNo > 0 ? bdNo.ToString() : "") + ext);
                            try
                            {
                                Kernel.IgnoreFileSystemMods = true;
                                bd.DownloadImage().Save(fn, ext == ".png" ? System.Drawing.Imaging.ImageFormat.Png : System.Drawing.Imaging.ImageFormat.Jpeg);
                                Kernel.IgnoreFileSystemMods = false;
                                movie.BackdropImagePaths.Add(fn);
                            }
                            catch (Exception e)
                            {
                                Logger.ReportException("Error downloading/saving image " + n.InnerText, e);
                            }
                            bdNo++;
                            if (bdNo >= Kernel.Instance.ConfigData.MaxBackdrops) break;
                        }
                        else
                        {
                            movie.BackdropImagePaths.Add(n.InnerText);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Fetches the main info.
        /// </summary>
        /// <param name="series">The series.</param>
        /// <param name="doc">The doc.</param>
        private void FetchMainInfo(Series series, XmlDocument doc)
        {
            if (!series.LockedFields.Contains(MetadataFields.Name))
            {
                series.Name = doc.SafeGetString("//SeriesName");
            }
            if (!series.LockedFields.Contains(MetadataFields.Overview))
            {
                series.Overview = doc.SafeGetString("//Overview");
            }
            series.CommunityRating = doc.SafeGetSingle("//Rating", 0, 10);
            series.AirDays = TVUtils.GetAirDays(doc.SafeGetString("//Airs_DayOfWeek"));
            series.AirTime = doc.SafeGetString("//Airs_Time");
            SeriesStatus seriesStatus;
            if(Enum.TryParse(doc.SafeGetString("//Status"), true, out seriesStatus))
                series.Status = seriesStatus;
            series.PremiereDate = doc.SafeGetDateTime("//FirstAired");
            if (series.PremiereDate.HasValue)
                series.ProductionYear = series.PremiereDate.Value.Year;

            series.RunTimeTicks = TimeSpan.FromMinutes(doc.SafeGetInt32("//Runtime")).Ticks;

            if (!series.LockedFields.Contains(MetadataFields.Studios))
            {
                string s = doc.SafeGetString("//Network");

                if (!string.IsNullOrWhiteSpace(s))
                {
                    series.Studios.Clear();

                    foreach (var studio in s.Trim().Split('|'))
                    {
                        series.AddStudio(studio);
                    }
                }
            }
            series.OfficialRating = doc.SafeGetString("//ContentRating");
            if (!series.LockedFields.Contains(MetadataFields.Genres))
            {
                string g = doc.SafeGetString("//Genre");

                if (g != null)
                {
                    string[] genres = g.Trim('|').Split('|');
                    if (g.Length > 0)
                    {
                        series.Genres.Clear();

                        foreach (var genre in genres)
                        {
                            series.AddGenre(genre);
                        }
                    }
                }
            }
            if (series.Status == SeriesStatus.Ended) {
                
                var document = XDocument.Load(new XmlNodeReader(doc));
                var dates = document.Descendants("Episode").Where(x => {
                                                                      var seasonNumber = x.Element("SeasonNumber");
                                                                      var firstAired = x.Element("FirstAired");
                                                                      return firstAired != null && seasonNumber != null && (!string.IsNullOrEmpty(seasonNumber.Value) && seasonNumber.Value != "0") && !string.IsNullOrEmpty(firstAired.Value);
                                                                  }).Select(x => {
                                                                                DateTime? date = null;
                                                                                DateTime tempDate;
                                                                                var firstAired = x.Element("FirstAired");
                                                                                if (firstAired != null && DateTime.TryParse(firstAired.Value, out tempDate)) 
                                                                                {
                                                                                    date = tempDate;
                                                                                }
                                                                                return date;
                                                                            }).ToList();
                if(dates.Any(x=>x.HasValue))
                    series.EndDate = dates.Where(x => x.HasValue).Max();
            }
        }
        /// <summary>
        /// Fetches the episode data.
        /// </summary>
        /// <param name="seriesXml">The series XML.</param>
        /// <param name="episode">The episode.</param>
        /// <param name="seriesId">The series id.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task{System.Boolean}.</returns>
        private async Task<ProviderRefreshStatus> FetchEpisodeData(XmlDocument seriesXml, Episode episode, string seriesId, CancellationToken cancellationToken)
        {
            var status = ProviderRefreshStatus.Success;

            if (episode.IndexNumber == null)
            {
                return status;
            }

            var seasonNumber = episode.ParentIndexNumber ?? TVUtils.GetSeasonNumberFromEpisodeFile(episode.Path);

            if (seasonNumber == null)
            {
                return status;
            }

            var usingAbsoluteData = false;

            var episodeNode = seriesXml.SelectSingleNode("//Episode[EpisodeNumber='" + episode.IndexNumber.Value + "'][SeasonNumber='" + seasonNumber.Value + "']");

            if (episodeNode == null)
            {
                if (seasonNumber.Value == 1)
                {
                    episodeNode = seriesXml.SelectSingleNode("//Episode[absolute_number='" + episode.IndexNumber.Value + "']");
                    usingAbsoluteData = true;
                }
            }

            // If still null, nothing we can do
            if (episodeNode == null)
            {
                return status;
            }

            var doc = new XmlDocument();
            doc.LoadXml(episodeNode.OuterXml);

            if (!episode.HasImage(ImageType.Primary))
            {
                var p = doc.SafeGetString("//filename");
                if (p != null)
                {
                    if (!Directory.Exists(episode.MetaLocation)) Directory.CreateDirectory(episode.MetaLocation);

                    try
                    {
                        episode.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
                    }
                    catch (HttpException)
                    {
                        status = ProviderRefreshStatus.CompletedWithErrors;
                    }
                }
            }

            episode.Overview = doc.SafeGetString("//Overview");
            if (usingAbsoluteData)
                episode.IndexNumber = doc.SafeGetInt32("//absolute_number", -1);
            if (episode.IndexNumber < 0)
                episode.IndexNumber = doc.SafeGetInt32("//EpisodeNumber");

            episode.Name = doc.SafeGetString("//EpisodeName");
            episode.CommunityRating = doc.SafeGetSingle("//Rating", -1, 10);
            var firstAired = doc.SafeGetString("//FirstAired");
            DateTime airDate;
            if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
            {
                episode.PremiereDate = airDate.ToUniversalTime();
                episode.ProductionYear = airDate.Year;
            }

            episode.People.Clear();

            var actors = doc.SafeGetString("//GuestStars");
            if (actors != null)
            {
                foreach (var person in actors.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                    .Where(i => !string.IsNullOrWhiteSpace(i))
                    .Select(str => new PersonInfo { Type = PersonType.GuestStar, Name = str }))
                {
                    episode.AddPerson(person);
                }
            }


            var directors = doc.SafeGetString("//Director");
            if (directors != null)
            {
                foreach (var person in directors.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                    .Where(i => !string.IsNullOrWhiteSpace(i))
                    .Select(str => new PersonInfo { Type = PersonType.Director, Name = str }))
                {
                    episode.AddPerson(person);
                }
            }


            var writers = doc.SafeGetString("//Writer");
            if (writers != null)
            {
                foreach (var person in writers.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                     .Where(i => !string.IsNullOrWhiteSpace(i))
                   .Select(str => new PersonInfo { Type = PersonType.Writer, Name = str }))
                {
                    episode.AddPerson(person);
                }
            }

            if (ConfigurationManager.Configuration.SaveLocalMeta)
            {
                if (!Directory.Exists(episode.MetaLocation)) Directory.CreateDirectory(episode.MetaLocation);
                var ms = new MemoryStream();
                doc.Save(ms);

                await _providerManager.SaveToLibraryFilesystem(episode, Path.Combine(episode.MetaLocation, Path.GetFileNameWithoutExtension(episode.Path) + ".xml"), ms, cancellationToken).ConfigureAwait(false);
            }

            return status;
        }
        private static void FetchXmlMovie(Item movie)
        {
            string mfile = Path.Combine(location, videofilename + ".nfo");

            if (File.Exists(mfile))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(mfile);

                movie.Title = doc.SafeGetString("movie/title");
                movie.OriginalTitle = doc.SafeGetString("movie/originaltitle");
                movie.SortTitle = doc.SafeGetString("movie/sorttitle");
                DateTime added;
                DateTime.TryParse(doc.SafeGetString("movie/added"), out added);
                if (added != null) movie.DateAdded = added;

                int? y = doc.SafeGetInt32("movie/year", 0);
                if (y.IsValidYear()) movie.Year = y;

                int? rt = doc.SafeGetInt32("movie/runtime", 0);
                if (rt.IsValidRunningTime())  movie.RunningTime = rt;

                movie.Rating = doc.SafeGetSingle("movie/rating", (float)-1, (float)10);
                movie.MPAARating = doc.SafeGetString("movie/mpaa");
                movie.Overview = doc.SafeGetString("movie/plot");
                movie.Mediatype = doc.SafeGetString("movie/type");
                movie.AspectRatio = doc.SafeGetString("movie/aspectratio");

                foreach (XmlNode node in doc.SelectNodes("movie/actor"))
                {
                    if (movie.Actors == null)
                        movie.Actors = new List<Actor>();
                    Actor actor = new Actor();
                    actor.Name = node.SafeGetString("name");
                    actor.Role = node.SafeGetString("role");
                    actor.ImagePath = node.SafeGetString("thumb");
                    if (string.IsNullOrEmpty(actor.ImagePath) && Directory.Exists(PluginOptions.Instance.ActorsThumbPath))
                    {
                        string actorImage = Path.Combine(PluginOptions.Instance.ActorsThumbPath, actor.Name + ".tbn");
                        if (File.Exists(actorImage))
                            actor.ImagePath = actorImage;
                    }
                    movie.Actors.Add(actor);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/director"))
                {
                    if (movie.Crew == null) movie.Crew = new List<CrewMember>();
                    movie.Crew.Add(new CrewMember { Name = node.InnerText, Activity = "Director" });
                }

                foreach (XmlNode node in doc.SelectNodes("movie/genre"))
                {
                    if (movie.Genres == null) movie.Genres = new List<string>();
                    movie.Genres.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/studio"))
                {
                    if (movie.Studios == null) movie.Studios = new List<string>();
                    movie.Studios.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/country"))
                {
                    if (movie.Countries == null) movie.Countries = new List<string>();
                    movie.Countries.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/tagline"))
                {
                    if (movie.TagLines == null) movie.TagLines = new List<string>();
                    movie.TagLines.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/trailer"))
                {
                    if (movie.TrailerFiles == null) movie.TrailerFiles = new List<string>();
                    movie.TrailerFiles.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("movie/thumb"))
                {
                    if (movie.ImagesPaths == null) movie.ImagesPaths = new List<Poster>();
                    movie.ImagesPaths.AddDistinctPoster(new Poster { Image = node.InnerText });
                }

                foreach (XmlNode node in doc.SelectNodes("movie/fanart/thumb"))
                {
                    if (movie.BackdropImagePaths == null) movie.BackdropImagePaths = new List<Poster>();
                    movie.BackdropImagePaths.AddDistinctPoster(new Poster { Image = node.InnerText });
                }

            }
        }
        private static void FetchSeries(Item series)
        {
            string mfile = Path.Combine(location, "tvshow.nfo");

            if (File.Exists(mfile))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(mfile);

                series.SeriesName = series.Title = doc.SafeGetString("tvshow/title");
                series.Rating = doc.SafeGetSingle("tvshow/rating", (float)-1, (float)10);

                string id = doc.SafeGetString("tvshow/id");
                if (!string.IsNullOrEmpty(id))
                {
                    series.ProvidersId = new List<DataProviderId>();
                    series.ProvidersId.Add(new DataProviderId { Id = id, Name = "TheTVDB", Url = "http://thetvdb.com/?tab=series&id=" + id });
                }

                series.Overview = doc.SafeGetString("tvshow/overview");

                foreach (XmlNode node in doc.SelectNodes("tvshow/actor"))
                {
                    if (series.Actors == null)
                        series.Actors = new List<Actor>();
                    Actor actor = new Actor();
                    actor.Name = node.SafeGetString("name");
                    actor.Role = node.SafeGetString("role");
                    actor.ImagePath = node.SafeGetString("thumb");
                    if (string.IsNullOrEmpty(actor.ImagePath) && Directory.Exists(PluginOptions.Instance.ActorsThumbPath))
                    {
                        string actorImage = Path.Combine(PluginOptions.Instance.ActorsThumbPath, actor.Name + ".tbn");
                        if (File.Exists(actorImage))
                            actor.ImagePath = actorImage;
                    }
                    series.Actors.Add(actor);
                }

                foreach (XmlNode node in doc.SelectNodes("tvshow/genre"))
                {
                    if (series.Genres == null) series.Genres = new List<string>();
                    series.Genres.Add(node.InnerText);
                }

                series.MPAARating = doc.SafeGetString("mpaa");

                int? rt = doc.SafeGetInt32("tvshow/runtime", 0);
                if (rt.IsValidRunningTime()) series.RunningTime = rt;

                series.Rating = doc.SafeGetSingle("tvshow/rating", (float)-1, (float)10);

                foreach (XmlNode node in doc.SelectNodes("tvshow/studio"))
                {
                    if (series.Studios == null) series.Studios = new List<string>();
                    series.Studios.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("tvshow/tagline"))
                {
                    if (series.TagLines == null) series.TagLines = new List<string>();
                    series.TagLines.Add(node.InnerText);
                }

                foreach (XmlNode node in doc.SelectNodes("tvshow/thumb"))
                {
                    if (series.BannersPaths == null) series.BannersPaths = new List<Poster>();
                    series.BannersPaths.AddDistinctPoster(new Poster { Image = node.InnerText });
                }
            }
        }
        public override void Fetch() 
        {
            Episode episode = Episode;
            Debug.Assert(episode != null);

            // store the location so we do not fetch again 
            metadataFile = XmlLocation;
            // no data, do nothing
            if (metadataFile == null) return;

            metadataFileDate = new FileInfo(metadataFile).LastWriteTimeUtc;

            string metadataFolder = Path.GetDirectoryName(metadataFile);
            
            XmlDocument metadataDoc = new XmlDocument();
            metadataDoc.Load(metadataFile);

            var p = metadataDoc.SafeGetString("//filename");
            if (p != null && p.Length > 0)
            {
                string image = System.IO.Path.Combine(metadataFolder, System.IO.Path.GetFileName(p));
                if (File.Exists(image))
                    Item.PrimaryImagePath = image;
            }
            else
            {
                string primaryExt = ".jpg";
                string secondaryExt = ".png";

                if (Config.Instance.PNGTakesPrecedence)
                {
                    primaryExt = ".png";
                    secondaryExt = ".jpg";
                }

                string file = Path.GetFileNameWithoutExtension(Item.Path);
                string image = System.IO.Path.Combine(metadataFolder, file + primaryExt);
                if (File.Exists(image))
                {
                    Item.PrimaryImagePath = image;
                }
                else
                {
                    image = System.IO.Path.Combine(metadataFolder, file + secondaryExt);
                    if (File.Exists(image))
                        Item.PrimaryImagePath = image;
                }
            }

            //if added date is in xml override the file/folder date
            DateTime added = DateTime.MinValue;
            DateTime.TryParse(metadataDoc.SafeGetString("//Added"), out added);
            if (added > DateTime.MinValue) episode.DateCreated = added;
               

            episode.Overview = metadataDoc.SafeGetString("//Overview");
            episode.EpisodeNumber = metadataDoc.SafeGetString("//EpisodeNumber");
            episode.Name = episode.EpisodeNumber + " - " + metadataDoc.SafeGetString("//EpisodeName");
            episode.SeasonNumber = metadataDoc.SafeGetString("//SeasonNumber");
            episode.ImdbRating = metadataDoc.SafeGetSingle("//Rating", (float)-1, 10);
            episode.FirstAired = metadataDoc.SafeGetString("//FirstAired");
            DateTime airDate;
            int y = DateTime.TryParse(episode.FirstAired, out airDate) ? airDate.Year : -1;
            if (y > 1850) {
                episode.ProductionYear = y;
            }


            string writers = metadataDoc.SafeGetString("//Writer");
            if (writers != null)
                episode.Writers = new List<string>(writers.Trim('|').Split('|'));


            string directors = metadataDoc.SafeGetString("//Director");
            if (directors != null)
                episode.Directors = new List<string>(directors.Trim('|').Split('|'));


            var actors = ActorListFromString(metadataDoc.SafeGetString("//GuestStars"));
            if (actors != null) {
                if (episode.Actors == null)
                    episode.Actors = new List<Actor>();
                episode.Actors = actors;
            }

            if (string.IsNullOrEmpty(episode.DisplayMediaType))
            {
                episode.DisplayMediaType = metadataDoc.SafeGetString("//Type", "");
                switch (episode.DisplayMediaType.ToLower())
                {
                    case "blu-ray":
                        episode.DisplayMediaType = MediaType.BluRay.ToString();
                        break;
                    case "dvd":
                        episode.DisplayMediaType = MediaType.DVD.ToString();
                        break;
                    case "hd dvd":
                        episode.DisplayMediaType = MediaType.HDDVD.ToString();
                        break;
                    case "":
                        episode.DisplayMediaType = null;
                        break;
                }
            }
            if (episode.AspectRatio == null)
                episode.AspectRatio = metadataDoc.SafeGetString("//AspectRatio");

            if (episode.MediaInfo == null) episode.MediaInfo = new MediaInfoData();
            
                //we need to decode metabrowser strings to format and profile
                string audio = metadataDoc.SafeGetString("//MediaInfo/Audio/Codec", "");
                if (audio != "")
                {
                    switch (audio.ToLower())
                    {
                        case "dts-es":
                        case "dts-es matrix":
                        case "dts-es discrete":
                            episode.MediaInfo.OverrideData.AudioFormat = "DTS";
                            episode.MediaInfo.OverrideData.AudioProfile = "ES";
                            break;
                        case "dts-hd hra":
                        case "dts-hd high resolution":
                            episode.MediaInfo.OverrideData.AudioFormat = "DTS";
                            episode.MediaInfo.OverrideData.AudioProfile = "HRA";
                            break;
                        case "dts-hd ma":
                        case "dts-hd master":
                            episode.MediaInfo.OverrideData.AudioFormat = "DTS";
                            episode.MediaInfo.OverrideData.AudioProfile = "MA";
                            break;
                        case "dolby digital":
                        case "dolby digital surround ex":
                        case "dolby surround":
                            episode.MediaInfo.OverrideData.AudioFormat = "AC-3";
                            break;
                        case "dolby digital plus":
                            episode.MediaInfo.OverrideData.AudioFormat = "E-AC-3";
                            break;
                        case "dolby truehd":
                            episode.MediaInfo.OverrideData.AudioFormat = "AC-3";
                            episode.MediaInfo.OverrideData.AudioProfile = "TrueHD";
                            break;
                        case "mp2":
                            episode.MediaInfo.OverrideData.AudioFormat = "MPEG Audio";
                            episode.MediaInfo.OverrideData.AudioProfile = "Layer 2";
                            break;
                        case "other":
                            break;
                        default:
                            episode.MediaInfo.OverrideData.AudioFormat = audio;
                            break;
                    }
                }
            
            episode.MediaInfo.OverrideData.AudioStreamCount = metadataDoc.SelectNodes("//MediaInfo/Audio/Codec[text() != '']").Count;
            episode.MediaInfo.OverrideData.AudioChannelCount = metadataDoc.SafeGetString("//MediaInfo/Audio/Channels", "");
            episode.MediaInfo.OverrideData.AudioBitRate = metadataDoc.SafeGetInt32("//MediaInfo/Audio/BitRate");
            
                string video = metadataDoc.SafeGetString("Item/MediaInfo/Video/Codec", "");
                if (video != "")
                {
                    switch (video.ToLower())
                    {
                        case "sorenson h.263":
                            episode.MediaInfo.OverrideData.VideoCodec = "Sorenson H263";
                            break;
                        case "h.262":
                            episode.MediaInfo.OverrideData.VideoCodec = "MPEG-2 Video";
                            break;
                        case "h.264":
                            episode.MediaInfo.OverrideData.VideoCodec = "AVC";
                            break;
                        default:
                            episode.MediaInfo.OverrideData.VideoCodec = video;
                            break;
                    }
                }
            
            episode.MediaInfo.OverrideData.VideoBitRate = metadataDoc.SafeGetInt32("Item/MediaInfo/Video/BitRate");
            episode.MediaInfo.OverrideData.Height = metadataDoc.SafeGetInt32("Item/MediaInfo/Video/Height");
            episode.MediaInfo.OverrideData.Width = metadataDoc.SafeGetInt32("Item/MediaInfo/Video/Width");
            episode.MediaInfo.OverrideData.ScanType = metadataDoc.SafeGetString("Item/MediaInfo/Video/ScanType", "");
            episode.MediaInfo.OverrideData.VideoFPS = metadataDoc.SafeGetString("Item/MediaInfo/Video/FrameRate", "");
            episode.MediaInfo.OverrideData.RunTime = metadataDoc.SafeGetInt32("Item/MediaInfo/Video/Duration");
            if (episode.MediaInfo.RunTime > 0) episode.RunningTime = episode.MediaInfo.RunTime;
            
                XmlNodeList nodes = metadataDoc.SelectNodes("Item/MediaInfo/Audio/Language");
                List<string> Langs = new List<string>();
                foreach (XmlNode node in nodes)
                {
                    string m = node.InnerText;
                    if (!string.IsNullOrEmpty(m))
                        Langs.Add(m);
                }
                if (Langs.Count > 1)
                {
                    episode.MediaInfo.OverrideData.AudioLanguages = String.Join(" / ", Langs.ToArray());
                }
                else
                {
                    episode.MediaInfo.OverrideData.AudioLanguages = metadataDoc.SafeGetString("Item/MediaInfo/Audio/Language", "");
                }
                nodes = metadataDoc.SelectNodes("Item/MediaInfo/Subtitle/Language");
                List<string> Subs = new List<string>();
                foreach (XmlNode node in nodes)
                {
                    string n = node.InnerText;
                    if (!string.IsNullOrEmpty(n))
                        Subs.Add(n);
                }
                if (Subs.Count > 1)
                {
                    episode.MediaInfo.OverrideData.Subtitles = String.Join(" / ", Subs.ToArray());
                }
                else
                {
                    episode.MediaInfo.OverrideData.Subtitles = metadataDoc.SafeGetString("Item/MediaInfo/Subtitle/Language", "");
                }
            
        }