/// <summary>
        /// Creates a new VideoInfo object using an instance of an IMDb TitleReference
        /// </summary>
        /// <param name="movie"></param>
        /// <returns></returns>
        private VideoInfo createVideoInfoFromTitleReference(TitleReference title)
        {
            VideoInfo video = new VideoInfo();
            video.Other = title;
            video.Title = title.Title;
            video.Thumb = getResizedImage(title.Image);
            video.Description = title.Principals.Select(p => p.Name).ToList().ToCommaSeperatedString();
            video.VideoUrl = title.ID;

            return video;
        }
        /// <summary>
        /// Searches for titles and names matching the given keywords.
        /// </summary>
        /// <param name="session">a session instance.</param>
        /// <param name="query">the search query keywords.</param>
        /// <returns></returns>
        public static SearchResults Search(Session session, string query)
        {
            var d = new Dictionary<string, string>();
            d.Add("q", query);

            string uri = string.Format(session.Settings.BaseUriMobile, session.Settings.SearchMobile, "?{0}");
            HtmlNode root = GetResponseFromSite(session, uri, d);

            SearchResults results = new SearchResults();
            List<TitleReference> titles = new List<TitleReference>();

            HtmlNodeCollection nodes = root.SelectNodes("//div[@class='poster ']");
            foreach(HtmlNode node in nodes) {
                
                HtmlNode titleNode = node.SelectSingleNode("div[@class='label']/div[@class='title']/a[contains(@href,'title')]");
                if (titleNode == null) 
                {
                    continue;
                }
                
                TitleReference title = new TitleReference();
                title.session = session;
                title.ID = titleNode.Attributes["href"].Value.Replace("/title/", "").Replace("/", "");
               
                ParseDisplayStringToTitleBase(title, titleNode.ParentNode.InnerText);

                HtmlNode detailNode = node.SelectSingleNode("div[@class='label']/div[@class='detail']");
                if (detailNode != null)
                {
                    string[] actors = detailNode.InnerText.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string actor in actors)
                    {
                        // todo: the name reference is missing an id
                        title.Principals.Add(new NameReference { Name = actor });
                    }
                }

                HtmlNode imageNode = node.DescendantNodes().Where(x => x.Name == "img").FirstOrDefault();
                if (imageNode != null) {
                    Match match = imdbImageExpression.Match(imageNode.Attributes["src"].Value);
                    if (match.Success)
                    {
                        title.Image = HttpUtility.UrlDecode(match.Groups["filename"].Value + match.Groups["ext"].Value);
                    }
                }

                titles.Add(title);
            }
            
            // todo: this is abuse, need to split the title results using the h1 headers later
            results.Titles[ResultType.Exact] = titles;

            return results;
        }
        /// <summary>
        /// Common method to get a list of titles from an IMDb trailer JSON feed
        /// </summary>
        /// <param name="session"></param>
        /// <param name="path">path to JSON feed</param>
        /// <returns>a collection of titles</returns>
        internal static List<TitleReference> GetTrailers(Session session, string uri, int token)
        {
            string url = (token > 0) ? uri + "&token=" + token : uri;
            
            List<TitleReference> titles = new List<TitleReference>();
            string response = session.MakeRequest(url);
            //JObject parsedResults = JObject.Parse(response);

            
            var imdbResponse = JsonConvert.DeserializeObject<OnlineVideos.Sites.apondman.IMDb.DTO.IMDbResponse>(response);

            HashSet<string> duplicateFilter = new HashSet<string>();
            foreach (var item in imdbResponse.model.items)
            {
                var titleId = item.display.titleId;
                if (duplicateFilter.Contains(titleId))
                {
                    continue;
                }

                duplicateFilter.Add(titleId);
                
                TitleReference title = new TitleReference();
                title.session = session;
                title.FillFrom(item);

                titles.Add(title);
            }

            return titles;
        }
        /// <summary>
        /// Browse the full length movies in a specific category.
        /// </summary>
        /// <param name="session">session to use</param>
        /// <param name="index">a single character in the range: # and A-Z</param>
        /// <returns></returns>
        public static List<TitleReference> GetFullLengthMovies(Session session, string index)
        {
            List<TitleReference> titles = new List<TitleReference>();
            
            string uri = string.Format(session.Settings.FullLengthMovies, index);
            HtmlNode data = GetResponseFromSite(session, uri);

            HtmlNodeCollection nodes = data.SelectNodes("//a[contains(@href,'title/tt')]");

            foreach (HtmlNode node in nodes)
            {
                string href = node.Attributes["href"].Value;
                string tt = ParseTitleConst(href);

                if (tt != null)
                {
                    TitleReference title = new TitleReference();
                    title.Type = TitleType.Movie;
                    title.session = session;
                    title.ID = tt;
                    title.Title = node.InnerText;
                    titles.Add(title);
                }
            }

            return titles;
        }
        /// <summary>
        /// Common method to get a list of titles from the IMDb app interface (JSON)
        /// </summary>
        /// <param name="session"></param>
        /// <param name="chart">name of the chart</param>
        /// <returns>a collection of titles</returns>
        internal static List<TitleReference> GetChart(Session session, string chart)
        {
            List<TitleReference> titles = new List<TitleReference>();

            string data = GetResponseFromEndpoint(session, chart);
            IMDbResponse<IMDbSingleList<IMDbList<IMDbTitle>>> response = JsonConvert.DeserializeObject<IMDbResponse<IMDbSingleList<IMDbList<IMDbTitle>>>>(data);
            foreach (IMDbTitle item in response.Data.List.Items)
            {
                TitleReference title = new TitleReference();
                title.session = session;
                title.FillFrom(item);

                titles.Add(title);
            }

            return titles;
        }
        /// <summary>
        /// Common method to get a list of titles from an IMDb mobile JSON feed
        /// </summary>
        /// <param name="session"></param>
        /// <param name="path">path to JSON feed</param>
        /// <returns>a collection of titles</returns>
        internal static List<TitleReference> GetList(Session session, string path)
        {
            List<TitleReference> titles = new List<TitleReference>();

            string data = GetResponseFromEndpoint(session, path);

            IMDbMobileResponse<List<IMDbTitleMobile>> response = JsonConvert.DeserializeObject<IMDbMobileResponse<List<IMDbTitleMobile>>>(data);

            DateTime releaseDateHeader = DateTime.MinValue;
            foreach (IMDbTitleMobile item in response.Data)
            {
                if (item.URL == null)
                {
                    if (item.ReleaseDate > DateTime.MinValue)
                    {
                        releaseDateHeader = item.ReleaseDate;
                    }
                    continue;
                }
                TitleReference title = new TitleReference();
                title.session = session;
                title.FillFrom(item);
                title.ReleaseDate = releaseDateHeader;

                titles.Add(title);
            }

            return titles;
        }