internal static void RemoveMovieFromWatchlist(TraktMovie movie)
        {
            if (_WatchListMovies == null || movie.Ids == null)
                return;

            var watchlistMovies = _WatchListMovies.ToList();
            watchlistMovies.RemoveAll(m => ((m.Movie.Ids.Trakt == movie.Ids.Trakt) && m.Movie.Ids.Trakt != null) ||
                                           ((m.Movie.Ids.Imdb == movie.Ids.Imdb) && m.Movie.Ids.Imdb.ToNullIfEmpty() != null) ||
                                           ((m.Movie.Ids.Tmdb == movie.Ids.Tmdb) && m.Movie.Ids.Tmdb != null));

            // remove using Title + Year
            if (movie.Ids.Trakt == null && movie.Ids.Imdb.ToNullIfEmpty() == null && movie.Ids.Tmdb == null)
            {
                watchlistMovies.RemoveAll(m => m.Movie.Title.ToLowerInvariant() == movie.Title.ToLower() && m.Movie.Year == movie.Year);
            }

            _WatchListMovies = watchlistMovies;
        }
        internal static bool RateMovie(TraktMovie movie)
        {
            TraktRateMovie rateObject = new TraktRateMovie
            {
                IMDBID = movie.IMDBID,
                TMDBID = movie.TMDBID,
                Title = movie.Title,
                Year = movie.Year,
                Rating = movie.RatingAdvanced.ToString(),
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password
            };

            int prevRating = movie.RatingAdvanced;
            int newRating = int.Parse(GUIUtils.ShowRateDialog<TraktRateMovie>(rateObject));
            if (newRating == -1) return false;

            // If previous rating not equal to current rating then
            // update skin properties to reflect changes
            // This is not really needed but saves waiting for response
            // from server to calculate fields...we can do it ourselves

            if (prevRating != newRating)
            {
                movie.RatingAdvanced = newRating;

                // if not rated previously bump up the votes
                if (prevRating == 0)
                {
                    movie.Ratings.Votes++;
                    if (movie.RatingAdvanced > 5)
                    {
                        movie.Rating = "love";
                        movie.Ratings.LovedCount++;
                    }
                    else
                    {
                        movie.Rating = "hate";
                        movie.Ratings.HatedCount++;
                    }
                }

                if (prevRating != 0 && prevRating > 5 && newRating <= 5)
                {
                    movie.Rating = "hate";
                    movie.Ratings.LovedCount--;
                    movie.Ratings.HatedCount++;
                }

                if (prevRating != 0 && prevRating <= 5 && newRating > 5)
                {
                    movie.Rating = "love";
                    movie.Ratings.LovedCount++;
                    movie.Ratings.HatedCount--;
                }

                if (newRating == 0)
                {
                    if (prevRating <= 5) movie.Ratings.HatedCount++;
                    movie.Ratings.Votes--;
                    movie.Rating = "false";
                }

                // Could be in-accurate, best guess
                if (prevRating == 0)
                {
                    movie.Ratings.Percentage = (int)Math.Round(((movie.Ratings.Percentage * (movie.Ratings.Votes - 1)) + (10 * newRating)) / (float)movie.Ratings.Votes);
                }
                else
                {
                    movie.Ratings.Percentage = (int)Math.Round(((movie.Ratings.Percentage * (movie.Ratings.Votes)) + (10 * newRating) - (10 * prevRating)) / (float)movie.Ratings.Votes);
                }

                return true;
            }

            return false;
        }
        public static void CheckAndPlayMovie(bool jumpTo, TraktMovie movie)
        {
            if (movie == null) return;

            string title = movie.Title;
            string imdbid = movie.IMDBID;
            string trailer = movie.Trailer;
            int year = Convert.ToInt32(movie.Year);

            CheckAndPlayMovie(jumpTo, title, year, imdbid, trailer);
        }
        private void RemoveMovieFromWatchList(TraktMovie movie)
        {
            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(obj as TraktMovie), TraktSyncModes.unwatchlist);
            })
            {
                IsBackground = true,
                Name = "RemoveWatchList"
            };

            syncThread.Start(movie);
        }
        private TraktSyncAll GetSyncItems(TraktListItem listItem)
        {
            var syncItems = new TraktSyncAll();

            switch (listItem.Type)
            {
                case "movie":
                    var movie = new TraktMovie
                    {
                        Ids = new TraktMovieId { Trakt = listItem.Movie.Ids.Trakt }
                    };
                    syncItems.Movies = new List<TraktMovie>();
                    syncItems.Movies.Add(movie);
                    break;

                case "show":
                    var show = new TraktShow
                    {
                        Ids = new TraktShowId { Trakt = listItem.Show.Ids.Trakt }
                    };
                    syncItems.Shows = new List<TraktShow>();
                    syncItems.Shows.Add(show);
                    break;

                case "season":
                    var season = new TraktSeason
                    {
                        Ids = new TraktSeasonId { Trakt = listItem.Season.Ids.Trakt }
                    };
                    syncItems.Seasons = new List<TraktSeason>();
                    syncItems.Seasons.Add(season);
                    break;

                case "episode":
                    var episode = new TraktEpisode
                    {
                        Ids = new TraktEpisodeId { Trakt = listItem.Episode.Ids.Trakt }
                    };
                    syncItems.Episodes = new List<TraktEpisode>();
                    syncItems.Episodes.Add(episode);
                    break;

                case "person":
                    var person = new TraktPerson
                    {
                        Ids = new TraktPersonId { Trakt = listItem.Person.Ids.Trakt }
                    };
                    syncItems.People = new List<TraktPerson>();
                    syncItems.People.Add(person);
                    break;
            }

            return syncItems;
        }
        private TraktMovieSync CreateSyncData(TraktMovie movie)
        {
            if (movie == null) return null;

            List<TraktMovieSync.Movie> movies = new List<TraktMovieSync.Movie>();

            TraktMovieSync.Movie syncMovie = new TraktMovieSync.Movie
            {
                IMDBID = movie.IMDBID,
                Title = movie.Title,
                Year = movie.Year
            };
            movies.Add(syncMovie);

            TraktMovieSync syncData = new TraktMovieSync
            {
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password,
                MovieList = movies
            };

            return syncData;
        }
        private void MarkMovieAsWatched(TraktMovie movie)
        {
            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(obj as TraktMovie), TraktSyncModes.seen);
            })
            {
                IsBackground = true,
                Name = "MarkWatched"
            };

            syncThread.Start(movie);
        }
        private bool RateMovie(TraktMovie movie)
        {
            // init since its not part of the API
            movie.Rating = "false";
            bool ratingChanged = false;

            // default rating to love if not already set
            TraktRateMovie rateObject = new TraktRateMovie
            {
                IMDBID = movie.Imdb,
                Title = movie.Title,
                Year = movie.Year,
                Rating = movie.Rating,
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password
            };

            string prevRating = movie.Rating;
            movie.Rating = GUIUtils.ShowRateDialog<TraktRateMovie>(rateObject);

            if (prevRating != movie.Rating)
            {
                ratingChanged = true;
            }

            return ratingChanged;
        }
        private void ShowTrailersMenu(TraktMovie movie)
        {
            IDialogbox dlg = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU);
            dlg.Reset();
            dlg.SetHeading(Translation.Trailer);

            foreach (TrailerSite site in Enum.GetValues(typeof(TrailerSite)))
            {
                string menuItem = Enum.GetName(typeof(TrailerSite), site);
                GUIListItem pItem = new GUIListItem(menuItem);
                dlg.Add(pItem);
            }

            dlg.DoModal(GUIWindowManager.ActiveWindow);

            if (dlg.SelectedLabel >= 0)
            {
                string siteUtil = string.Empty;
                string searchParam = string.Empty;

                switch (dlg.SelectedLabelText)
                {
                    case ("IMDb"):
                        siteUtil = "IMDb Movie Trailers";
                        if (!string.IsNullOrEmpty(movie.Imdb))
                            // Exact search
                            searchParam = movie.Imdb;
                        else
                            searchParam = movie.Title;
                        break;

                    case ("iTunes"):
                        siteUtil = "iTunes Movie Trailers";
                        searchParam = movie.Title;
                        break;

                    case ("YouTube"):
                        siteUtil = "YouTube";
                        searchParam = movie.Title;
                        break;
                }

                string loadingParam = string.Format("site:{0}|search:{1}|return:Locked", siteUtil, searchParam);
                // Launch OnlineVideos Trailer search
                GUIWindowManager.ActivateWindow((int)ExternalPluginWindows.OnlineVideos, loadingParam);
            }
        }
        public static TraktSyncResponse AddMovieToWatchlist(TraktMovie movie)
        {
            var movies = new TraktSyncMovies
            {
                Movies = new List<TraktMovie>() { movie }
            };

            return AddMoviesToWatchlist(movies);
        }
 private void PublishMovieSkinProperties(TraktMovie movie)
 {
     SetProperty("#Trakt.Movie.Imdb", movie.Imdb);
     SetProperty("#Trakt.Movie.Certification", movie.Certification);
     SetProperty("#Trakt.Movie.Overview", string.IsNullOrEmpty(movie.Overview) ? Translation.NoMovieSummary : movie.Overview);
     SetProperty("#Trakt.Movie.Released", movie.Released.FromEpoch().ToShortDateString());
     SetProperty("#Trakt.Movie.Runtime", movie.Runtime.ToString());
     SetProperty("#Trakt.Movie.Tagline", movie.Tagline);
     SetProperty("#Trakt.Movie.Title", movie.Title);
     SetProperty("#Trakt.Movie.Tmdb", movie.Tmdb);
     SetProperty("#Trakt.Movie.Trailer", movie.Trailer);
     SetProperty("#Trakt.Movie.Url", movie.Url);
     SetProperty("#Trakt.Movie.Year", movie.Year);
     SetProperty("#Trakt.Movie.PosterImageFilename", movie.Images.PosterImageFilename);
     SetProperty("#Trakt.Movie.FanartImageFilename", movie.Images.PosterImageFilename);
     SetProperty("#Trakt.Movie.InCollection", movie.InCollection.ToString());
     SetProperty("#Trakt.Movie.InWatchList", movie.InWatchList.ToString());
     SetProperty("#Trakt.Movie.Rating", movie.Rating);
     SetProperty("#Trakt.Movie.Ratings.Icon", (movie.Ratings.LovedCount > movie.Ratings.HatedCount) ? "love" : "hate");
     SetProperty("#Trakt.Movie.Ratings.HatedCount", movie.Ratings.HatedCount.ToString());
     SetProperty("#Trakt.Movie.Ratings.LovedCount", movie.Ratings.LovedCount.ToString());
     SetProperty("#Trakt.Movie.Ratings.Percentage", movie.Ratings.Percentage.ToString());
     SetProperty("#Trakt.Movie.Ratings.Votes", movie.Ratings.Votes.ToString());
 }
        public static TraktSyncResponse RemoveMovieFromWatchlist(TraktMovie movie)
        {
            var movies = new TraktSyncMovies
            {
                Movies = new List<TraktMovie>() { movie }
            };

            return RemoveMoviesFromWatchlist(movies);
        }
        /// <summary>
        /// UnRate a single movie on trakt.tv
        /// </summary>
        public static TraktSyncResponse RemoveMovieFromRatings(TraktMovie movie)
        {
            var movies = new TraktSyncMovies
            {
                Movies = new List<TraktMovie>() { new TraktMovie { Ids = movie.Ids } }
            };

            return RemoveMoviesFromRatings(movies);
        }
        public static TraktSyncResponse RemoveMovieFromCollection(TraktMovie movie)
        {
            var movies = new TraktSyncMovies
            {
                Movies = new List<TraktMovie>() { movie }
            };

            return RemoveMoviesFromCollecton(movies);
        }
        private TraktMovieSync CreateMovieSyncData(TraktMovie movie)
        {
            if (movie == null) return null;

            TraktMovieSync.Movie syncMovie = new TraktMovieSync.Movie
            {
                IMDBID = movie.Imdb,
                Title = movie.Title,
                Year = movie.Year
            };

            TraktMovieSync syncData = new TraktMovieSync
            {
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password,
                MovieList = new List<TraktMovieSync.Movie> { syncMovie }
            };

            return syncData;
        }
        private bool MovieMatch(MFMovie mfMovie, TraktMovie traktMovie)
        {
            // IMDb comparison
            if (!string.IsNullOrEmpty(traktMovie.Ids.Imdb) && !string.IsNullOrEmpty(BasicHandler.GetProperImdbId(mfMovie.IMDBNumber)))
            {
                return string.Compare(BasicHandler.GetProperImdbId(mfMovie.IMDBNumber), traktMovie.Ids.Imdb, true) == 0;
            }

            // TMDb comparison
            if (!string.IsNullOrEmpty(mfMovie.TMDBNumber) && traktMovie.Ids.Tmdb.HasValue)
            {
                return string.Compare(mfMovie.TMDBNumber, traktMovie.Ids.Tmdb.ToString(), true) == 0;
            }

            // Title & Year comparison
            return string.Compare(mfMovie.Title, traktMovie.Title, true) == 0 && mfMovie.Year.ToString() == traktMovie.Year.ToString();
        }
        private void AddMovieToLibrary(TraktMovie movie)
        {
            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(obj as TraktMovie), TraktSyncModes.library);
            })
            {
                IsBackground = true,
                Name = "AddLibrary"
            };

            syncThread.Start(movie);
        }
        private void OnToggleWatched(MFMovie movie, bool watched, int count)
        {
            TraktLogger.Info("Received togglewatched event from My Films. Title = '{0}', Year = '{1}', IMDb ID = '{2}', TMDb ID = '{3}'", movie.Title, movie.Year, movie.IMDBNumber ?? "<empty>", movie.TMDBNumber ?? "<empty>");

            if (TraktSettings.AccountStatus != ConnectionState.Connected) return;

            // don't do anything if movie is blocked
            if (TraktSettings.BlockedFilenames.Contains(movie.File) || TraktSettings.BlockedFolders.Any(f => movie.File.ToLowerInvariant().Contains(f.ToLowerInvariant())))
            {
                TraktLogger.Info("Movie {0} is on the blocked list so we didn't update Trakt", movie.Title);
                return;
            }

            var toggleWatchedThread = new Thread((o) =>
            {
                var tMovie = o as MFMovie;

                if (!watched)
                {
                    var traktMovie = new TraktMovie
                    {
                        Ids = new TraktMovieId { Imdb = tMovie.IMDBNumber, Tmdb = movie.TMDBNumber.ToNullableInt32() },
                        Title = tMovie.Title,
                        Year = tMovie.Year
                    };

                    // update local cache
                    TraktCache.RemoveMovieFromWatchHistory(traktMovie);

                    var response = TraktAPI.TraktAPI.RemoveMovieFromWatchedHistory(traktMovie);
                    TraktLogger.LogTraktResponse(response);
                }
                else
                {
                    // no longer need movie in recommendations or watchlist
                    RemoveMovieFromRecommendations(tMovie);
                    RemoveMovieFromWatchlist(tMovie);

                    var traktMovie = new TraktSyncMovieWatched
                    {
                        Ids = new TraktMovieId { Imdb = tMovie.IMDBNumber, Tmdb = movie.TMDBNumber.ToNullableInt32() },
                        Title = tMovie.Title,
                        Year = tMovie.Year,
                        WatchedAt = DateTime.UtcNow.ToISO8601()
                    };

                    var response = TraktAPI.TraktAPI.AddMovieToWatchedHistory(traktMovie);
                    TraktLogger.LogTraktResponse(response);

                    if (response != null && response.NotFound != null && response.NotFound.Movies.Count == 0)
                    {
                        // update local cache
                        TraktCache.AddMovieToWatchHistory(traktMovie);
                    }
                }
            })
            {
                IsBackground = true,
                Name = "ToggleWatched"
            };

            toggleWatchedThread.Start(movie);
        }
        private void DismissRecommendation(TraktMovie movie)
        {
            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktMovie dismissMovie = obj as TraktMovie;

                TraktMovieSlug syncMovie = new TraktMovieSlug
                {
                    UserName = TraktSettings.Username,
                    Password = TraktSettings.Password,
                    IMDbId = dismissMovie.IMDBID,
                    TMDbId = dismissMovie.TMDBID,
                    Title = dismissMovie.Title,
                    Year = dismissMovie.Year
                };

                TraktResponse response = TraktAPI.TraktAPI.DismissMovieRecommendation(syncMovie);
                TraktAPI.TraktAPI.LogTraktResponse<TraktResponse>(response);
                if (response != null && response.Status == "success")
                {
                    TraktHandlers.MovingPictures.UpdateCategoriesAndFilters();
                }
            })
            {
                IsBackground = true,
                Name = "DismissRecommendation"
            };

            syncThread.Start(movie);
        }
        private void DismissRecommendation(TraktMovie movie)
        {
            var syncThread = new Thread(obj =>
            {
                TraktMovie dismissMovie = obj as TraktMovie;

                var response = TraktAPI.TraktAPI.DismissRecommendedMovie(dismissMovie.Ids.Trakt.ToString());
                if (response)
                {
                    TraktHandlers.MovingPictures.RemoveMovieCriteriaFromRecommendationsNode(movie.Ids.Imdb);
                }
            })
            {
                IsBackground = true,
                Name = "DismissRecommendation"
            };

            syncThread.Start(movie);
        }
 private void PublishMovieSkinProperties(TraktMovie movie)
 {
     GUICommon.SetMovieProperties(movie);
 }
        private void AddMovieToWatchList(TraktMovie movie)
        {
            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(obj as TraktMovie), TraktSyncModes.watchlist);
            })
            {
                IsBackground = true,
                Name = "Adding Movie to Watch List"
            };

            syncThread.Start(movie);
        }
        private bool MovieMatch(IMDBMovie localMovie, TraktMovie traktMovie)
        {
            // IMDb comparison
            if (!string.IsNullOrEmpty(traktMovie.Ids.Imdb) && !string.IsNullOrEmpty(BasicHandler.GetProperImdbId(localMovie.IMDBNumber)))
            {
                return string.Compare(BasicHandler.GetProperImdbId(localMovie.IMDBNumber), traktMovie.Ids.Imdb, true) == 0;
            }

            // Title & Year comparison
            return string.Compare(localMovie.Title, traktMovie.Title, true) == 0 && localMovie.Year.ToString() == traktMovie.Year.ToString();
        }
        /// <summary>
        /// Fired when an object is removed from the MovingPictures Database
        /// </summary>
        private void DatabaseManager_ObjectDeleted(DatabaseTable obj)
        {
            // only remove from collection if the user wants us to
            if (!TraktSettings.KeepTraktLibraryClean || !TraktSettings.SyncLibrary)
                return;

            // check connection state
            if (TraktSettings.AccountStatus != ConnectionState.Connected)
                return;

            // if we have removed a movie from MovingPictures we want to update Trakt library
            if (obj.GetType() != typeof(DBMovieInfo))
                return;

            var syncThread = new Thread((objMovie) =>
            {
                var movie = objMovie as DBMovieInfo;

                var traktMovie = new TraktMovie
                {
                    Ids = new TraktMovieId { Imdb = movie.ImdbID, Tmdb = GetTmdbID(movie).ToNullableInt32() },
                    Title = movie.Title,
                    Year = movie.Year
                };

                TraktLogger.Info("Removing movie from trakt.tv collection, Title = '{0}', Year = '{1}', IMDB ID = '{2}', TMDb ID = '{3}'", movie.Title, movie.Year, movie.ImdbID ?? "<empty>", GetTmdbID(movie) ?? "<empty>");

                if (TraktSettings.SkipMoviesWithNoIdsOnSync)
                {
                    traktMovie.Title = null;
                    traktMovie.Year = null;
                    if (!BasicHandler.IsValidImdb(traktMovie.Ids.Imdb) && traktMovie.Ids.Tmdb == null)
                    {
                        TraktLogger.Info("Skipping movie removal from trakt.tv collection, movie has no valid online ID's.");
                        return;
                    }
                }

                // update local cache
                TraktCache.RemoveMovieFromCollection(traktMovie);

                var response = TraktAPI.TraktAPI.RemoveMovieFromCollection(traktMovie);
                TraktLogger.LogTraktResponse(response);
            })
            {
                IsBackground = true,
                Name = "Sync"
            };

            syncThread.Start(obj);
        }
        internal static void CreateTrendingMoviesContextMenu(ref IDialogbox dlg, TraktMovie movie, bool dashboard)
        {
            GUIListItem listItem = null;

            // Mark As Watched
            if (!movie.Watched)
            {
                listItem = new GUIListItem(Translation.MarkAsWatched);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.MarkAsWatched;
            }

            // Mark As UnWatched
            if (movie.Watched)
            {
                listItem = new GUIListItem(Translation.MarkAsUnWatched);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.MarkAsUnWatched;
            }

            // Add/Remove Watch List
            if (!movie.InWatchList)
            {
                listItem = new GUIListItem(Translation.AddToWatchList);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.AddToWatchList;
            }
            else
            {
                listItem = new GUIListItem(Translation.RemoveFromWatchList);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.RemoveFromWatchList;
            }

            // Add to Custom list
            listItem = new GUIListItem(Translation.AddToList + "...");
            dlg.Add(listItem);
            listItem.ItemId = (int)TrendingContextMenuItem.AddToList;

            // Add to Library
            // Don't allow if it will be removed again on next sync
            // movie could be part of a DVD collection
            if (!movie.InCollection && !TraktSettings.KeepTraktLibraryClean)
            {
                listItem = new GUIListItem(Translation.AddToLibrary);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.AddToLibrary;
            }

            if (movie.InCollection)
            {
                listItem = new GUIListItem(Translation.RemoveFromLibrary);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.RemoveFromLibrary;
            }

            // Filters
            if (!dashboard)
            {
                listItem = new GUIListItem(Translation.Filters + "...");
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.Filters;
            }

            // Related Movies
            listItem = new GUIListItem(Translation.RelatedMovies + "...");
            dlg.Add(listItem);
            listItem.ItemId = (int)TrendingContextMenuItem.Related;

            // Rate Movie
            listItem = new GUIListItem(Translation.RateMovie);
            dlg.Add(listItem);
            listItem.ItemId = (int)TrendingContextMenuItem.Rate;

            // Shouts
            listItem = new GUIListItem(Translation.Shouts + "...");
            dlg.Add(listItem);
            listItem.ItemId = (int)TrendingContextMenuItem.Shouts;

            // Trailers
            if (TraktHelper.IsOnlineVideosAvailableAndEnabled)
            {
                listItem = new GUIListItem(Translation.Trailers);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.Trailers;
            }

            // Change Layout
            if (GUIWindowManager.ActiveWindow == (int)TraktGUIWindows.TrendingMovies)
            {
                listItem = new GUIListItem(Translation.ChangeLayout);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.ChangeLayout;
            }

            if (!movie.InCollection && TraktHelper.IsMpNZBAvailableAndEnabled)
            {
                // Search for movie with mpNZB
                listItem = new GUIListItem(Translation.SearchWithMpNZB);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.SearchWithMpNZB;
            }

            if (!movie.InCollection && TraktHelper.IsMyTorrentsAvailableAndEnabled)
            {
                // Search for movie with MyTorrents
                listItem = new GUIListItem(Translation.SearchTorrent);
                dlg.Add(listItem);
                listItem.ItemId = (int)TrendingContextMenuItem.SearchTorrent;
            }
        }
        /// <summary>
        /// Fired when an object is updated in the Moving Pictures Database
        /// </summary>
        /// <param name="obj"></param>
        private void DatabaseManager_ObjectUpdatedEx(DatabaseTable dbObject, TableUpdateInfo ui)
        {
            // check connection state
            if (TraktSettings.AccountStatus != ConnectionState.Connected)
                return;

            // If it is user settings for a movie
            if (dbObject.GetType() != typeof(DBUserMovieSettings))
                return;

            // if we are syncing, we maybe manually setting state from trakt
            // in this case we dont want to resend to trakt
            if (SyncLibraryInProgress) return;

            DBUserMovieSettings userMovieSettings = (DBUserMovieSettings)dbObject;
            DBMovieInfo movie = userMovieSettings.AttachedMovies[0];

            // don't do anything if movie is blocked
            if (TraktSettings.BlockedFilenames.Contains(movie.LocalMedia[0].FullPath) || TraktSettings.BlockedFolders.Any(f => movie.LocalMedia[0].FullPath.ToLowerInvariant().Contains(f.ToLowerInvariant())))
            {
                TraktLogger.Info("Movie is on the blocked list so we didn't update trakt.tv. Title = '{0}', Year = '{1}', IMDB ID = '{2}', TMDb ID = '{3}'", movie.Title, movie.Year, movie.ImdbID ?? "<empty>", GetTmdbID(movie) ?? "<empty>");
                return;
            }

            // we check the watched flag and update Trakt respectfully
            // ignore if movie is the current movie being scrobbled, this will be set to watched automatically
            if (ui.WatchedCountChanged() && movie != currentMovie)
            {
                if (userMovieSettings.WatchedCount == 0)
                {
                    #region Unwatched Event
                    TraktLogger.Info("Received Un-Watched event in MovingPictures for movie. Title = '{0}', Year = '{1}', IMDB ID = '{2}', TMDb ID = '{3}'", movie.Title, movie.Year, movie.ImdbID ?? "<empty>", GetTmdbID(movie) ?? "<empty>");

                    var syncThread = new Thread((objMovie) =>
                    {
                        var tMovie = objMovie as DBMovieInfo;

                        var traktMovie = new TraktMovie
                        {
                            Ids = new TraktMovieId { Imdb = tMovie.ImdbID, Tmdb = GetTmdbID(tMovie).ToNullableInt32() },
                            Title = tMovie.Title,
                            Year = tMovie.Year
                        };

                        // update local cache
                        TraktCache.RemoveMovieFromWatchHistory(traktMovie);

                        var response = TraktAPI.TraktAPI.RemoveMovieFromWatchedHistory(traktMovie);
                        TraktLogger.LogTraktResponse(response);
                    })
                    {
                        IsBackground = true,
                        Name = "Sync"
                    };

                    syncThread.Start(movie);
                    #endregion
                }
                else
                {
                    #region Watched Event
                    TraktLogger.Info("Received Watched event in MovingPictures for movie. Title = '{0}', Year = '{1}', IMDB ID = '{2}', TMDb ID = '{3}'", movie.Title, movie.Year, movie.ImdbID ?? "<empty>", GetTmdbID(movie) ?? "<empty>");
                    if (!g_Player.IsVideo)
                    {
                        var syncThread = new Thread((objMovie) =>
                        {
                            var tMovie = objMovie as DBMovieInfo;

                            var traktMovie = new TraktSyncMovieWatched
                            {
                                Ids = new TraktMovieId { Imdb = tMovie.ImdbID, Tmdb = GetTmdbID(tMovie).ToNullableInt32() },
                                Title = tMovie.Title,
                                Year = tMovie.Year,
                                WatchedAt = DateTime.UtcNow.ToISO8601()
                            };

                            var response = TraktAPI.TraktAPI.AddMovieToWatchedHistory(traktMovie);
                            TraktLogger.LogTraktResponse(response);

                            if (response != null && response.NotFound != null && response.NotFound.Movies.Count == 0)
                            {
                                // update internal cache
                                TraktCache.AddMovieToWatchHistory(traktMovie);
                            }

                            // don't need to keep this movie anymore in categories/filter menu if it's watched
                            RemoveMovieCriteriaFromRecommendationsNode(tMovie.ImdbID);
                            RemoveMovieCriteriaFromWatchlistNode(tMovie.ImdbID);
                        })
                        {
                            IsBackground = true,
                            Name = "Sync"
                        };

                        syncThread.Start(movie);
                    }
                    #endregion
                }
            }

            // we will update the Trakt rating of the Movie
            // ignore if we rated using trakt rate dialog
            if (ui.RatingChanged() && userMovieSettings.UserRating > 0 && !TraktRateSent)
            {
                TraktLogger.Info("Received Rate event in MovingPictures for movie. Rating = '{0}/5', Title = '{1}', Year = '{2}', IMDB ID = '{3}', TMDb ID = '{4}'", userMovieSettings.UserRating, movie.Title, movie.Year, movie.ImdbID ?? "<empty>", GetTmdbID(movie) ?? "<empty>");

                var syncThread = new Thread((objMovie) =>
                {
                    var tMovie = objMovie as DBMovieInfo;

                    var traktMovie = new TraktSyncMovieRated
                    {
                        Ids = new TraktMovieId { Imdb = tMovie.ImdbID, Tmdb = GetTmdbID(tMovie).ToNullableInt32() },
                        Title = tMovie.Title,
                        Year = tMovie.Year,
                        RatedAt = DateTime.UtcNow.ToISO8601(),
                        Rating = (int)userMovieSettings.UserRating * 2
                    };

                    var response = TraktAPI.TraktAPI.AddMovieToRatings(traktMovie);
                    TraktLogger.LogTraktResponse(response);
                })
                {
                    IsBackground = true,
                    Name = "Sync"
                };
                syncThread.Start(movie);
            }
        }
        internal static void SetMovieProperties(TraktMovie movie)
        {
            if (movie == null) return;

            SetProperty("#Trakt.Movie.Imdb", movie.IMDBID);
            SetProperty("#Trakt.Movie.Certification", movie.Certification);
            SetProperty("#Trakt.Movie.Overview", string.IsNullOrEmpty(movie.Overview) ? Translation.NoMovieSummary : movie.Overview.RemapHighOrderChars());
            SetProperty("#Trakt.Movie.Released", movie.Released.FromEpoch().ToShortDateString());
            SetProperty("#Trakt.Movie.Runtime", movie.Runtime.ToString());
            SetProperty("#Trakt.Movie.Tagline", movie.Tagline);
            SetProperty("#Trakt.Movie.Title", movie.Title.RemapHighOrderChars());
            SetProperty("#Trakt.Movie.Tmdb", movie.TMDBID);
            SetProperty("#Trakt.Movie.Trailer", movie.Trailer);
            SetProperty("#Trakt.Movie.Url", movie.Url);
            SetProperty("#Trakt.Movie.Year", movie.Year);
            SetProperty("#Trakt.Movie.Genres", string.Join(", ", movie.Genres.ToArray()));
            SetProperty("#Trakt.Movie.PosterImageFilename", movie.Images.PosterImageFilename);
            SetProperty("#Trakt.Movie.FanartImageFilename", movie.Images.FanartImageFilename);
            SetProperty("#Trakt.Movie.InCollection", movie.InCollection.ToString());
            SetProperty("#Trakt.Movie.InWatchList", movie.InWatchList.ToString());
            SetProperty("#Trakt.Movie.Plays", movie.Plays.ToString());
            SetProperty("#Trakt.Movie.Watched", movie.Watched.ToString());
            SetProperty("#Trakt.Movie.Rating", movie.Rating);
            SetProperty("#Trakt.Movie.RatingAdvanced", movie.RatingAdvanced.ToString());
            SetProperty("#Trakt.Movie.Ratings.Icon", (movie.Ratings.LovedCount > movie.Ratings.HatedCount) ? "love" : "hate");
            SetProperty("#Trakt.Movie.Ratings.HatedCount", movie.Ratings.HatedCount.ToString());
            SetProperty("#Trakt.Movie.Ratings.LovedCount", movie.Ratings.LovedCount.ToString());
            SetProperty("#Trakt.Movie.Ratings.Percentage", movie.Ratings.Percentage.ToString());
            SetProperty("#Trakt.Movie.Ratings.Votes", movie.Ratings.Votes.ToString());
        }
        /// <summary>
        /// Checks if a local movie is the same as an online movie
        /// </summary>
        private bool MovieMatch(DBMovieInfo movPicsMovie, TraktMovie traktMovie)
        {
            // IMDb comparison
            if (!string.IsNullOrEmpty(traktMovie.Ids.Imdb) && !string.IsNullOrEmpty(BasicHandler.GetProperImdbId(movPicsMovie.ImdbID)))
            {
                return string.Compare(BasicHandler.GetProperImdbId(movPicsMovie.ImdbID), traktMovie.Ids.Imdb, true) == 0;
            }

            // TMDb comparison
            if (!string.IsNullOrEmpty(GetTmdbID(movPicsMovie)) && traktMovie.Ids.Tmdb.HasValue)
            {
                return string.Compare(GetTmdbID(movPicsMovie), traktMovie.Ids.Tmdb.ToString(), true) == 0;
            }

            // Title & Year comparison
            return string.Compare(movPicsMovie.Title, traktMovie.Title, true) == 0 && movPicsMovie.Year.ToString() == traktMovie.Year.ToString();
        }
        public static void ShowMovieTrailersMenu(TraktMovie movie)
        {
            IDialogbox dlg = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU);
            dlg.Reset();
            dlg.SetHeading(Translation.Trailer);

            if (!string.IsNullOrEmpty(movie.Trailer))
            {
                // trailer can be played without searching
                GUIListItem pItem = new GUIListItem(Translation.PlayTrailer);
                dlg.Add(pItem);
            }

            foreach (TrailerSiteMovies site in Enum.GetValues(typeof(TrailerSiteMovies)))
            {
                string menuItem = Enum.GetName(typeof(TrailerSiteMovies), site);
                GUIListItem pItem = new GUIListItem(menuItem);
                dlg.Add(pItem);
            }

            dlg.DoModal(GUIWindowManager.ActiveWindow);

            if (dlg.SelectedLabel >= 0)
            {
                string siteUtil = string.Empty;
                string searchParam = string.Empty;

                switch (dlg.SelectedLabelText)
                {
                    case ("IMDb"):
                        siteUtil = "IMDb Movie Trailers";
                        if (!string.IsNullOrEmpty(movie.IMDBID))
                            // Exact search
                            searchParam = movie.IMDBID;
                        else
                            searchParam = movie.Title;
                        break;

                    case ("iTunes"):
                        siteUtil = "iTunes Movie Trailers";
                        searchParam = movie.Title;
                        break;

                    case ("YouTube"):
                        siteUtil = "YouTube";
                        searchParam = movie.Title;
                        break;

                    default:
                        if (TraktHelper.IsOnlineVideosAvailableAndEnabled)
                        {
                            TraktHandlers.OnlineVideos.Play(movie.Trailer);
                        }
                        return;
                }

                string loadingParam = string.Format("site:{0}|search:{1}|return:Locked", siteUtil, searchParam);

                // Launch OnlineVideos Trailer search
                GUIWindowManager.ActivateWindow((int)ExternalPluginWindows.OnlineVideos, loadingParam);
            }
        }
        internal static void RemoveMovieFromPausedData(TraktMovie movie)
        {
            if (_PausedMovies == null || movie.Ids == null)
                return;

            var pausedMovies = _PausedMovies.ToList();
            pausedMovies.RemoveAll(m => ((m.Movie.Ids.Trakt == movie.Ids.Trakt) && m.Movie.Ids.Trakt != null) ||
                                        ((m.Movie.Ids.Imdb == movie.Ids.Imdb) && m.Movie.Ids.Imdb.ToNullIfEmpty() != null) ||
                                        ((m.Movie.Ids.Tmdb == movie.Ids.Tmdb) && m.Movie.Ids.Tmdb != null));

            // remove using Title + Year
            if (movie.Ids.Trakt == null && movie.Ids.Imdb.ToNullIfEmpty() == null && movie.Ids.Tmdb == null)
            {
                pausedMovies.RemoveAll(m => m.Movie.Title.ToLowerInvariant() == movie.Title.ToLower() && m.Movie.Year == movie.Year);
            }

            _PausedMovies = pausedMovies;
        }