Click here to Skip to main content
15,882,114 members
Articles / Desktop Programming / WPF

Wrap Panel Virtualization

Rate me:
Please Sign up or sign in to vote.
4.95/5 (18 votes)
2 Jan 2012CPOL2 min read 53.1K   5.6K   41  
WrapPanel doesn't support virtualization. But we can improve the performance by simulating virtualization.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using MediaAssistant.Constants;
using MediaAssistant.Controls.AlternativeLocation;
using MediaAssistant.Controls.StatusMessageBar;
using MediaAssistant.DAL.Virtualization;
using MediaAssistant.EventArguments;
using MediaAssistant.Helper;
using MediaAssistant.Management;
using MediaAssistant.MusicDJ;
using MediaFS;
using MefBasic.Commans;
using MefBasic.Data;
using MefBasic.Extensions;
using MefBasic.Helper;
using MefBasic.Threading;
using Microsoft.Practices.Composite;
using Microsoft.Practices.Composite.Events;
using Microsoft.Win32;
using MediaAssistant.DAL;
using MediaAssistant.DAL.Constants;
using MediaAssistant.DAL.Helper;
using Newtonsoft.Json.Linq;

namespace MediaAssistant.Data
{
    [Serializable]
    [Export(typeof(LibraryDataSource))]
    public class LibraryDataSource : DependencyNotifyObject
    {
        public static readonly DependencyProperty SelectedLibraryItemProperty =
            DependencyProperty.Register("SelectedLibraryItem", typeof(LibraryItem), typeof(LibraryDataSource),
                                        new UIPropertyMetadata(null, OnPropertyChanged));

        [ImportingConstructor]
        public LibraryDataSource(IEventAggregator eventAggregator)
        {
            EventAggregator = eventAggregator;
            CurrentGenres = new ObservableCollection<string>();
            CurrentAlbums = new ObservableCollection<string>();
            CurrentArtists = new ObservableCollection<string>();
            CurrentComposers = new ObservableCollection<string>();
            ResultMusics = new ObservableCollection<Music>();
            ResultMovies = new ObservableCollection<Movie>();
            MusicPlayer = new MediaElement { LoadedBehavior = MediaState.Manual };
            PlayerUpdateTimer = new Timer(OnPlayerUpdateTimer, null, 0, 1000);
            Playlists = new ObservableCollection<LibraryItem>();

            PlayMovieCommand = new DelegateCommand(ExecutePlayMovie, CanExecutePlayMovie);
            ShowMovieInWindowsExplorerCommand = new DelegateCommand(ExecuteShowMovieInWindowsExplorer, CanExecuteShowMovieInWindowsExplorer);
            ShowMovieInIMDBCommand = new DelegateCommand(ExecuteShowMovieInIMDB, CanExecuteShowMovieInIMDB);
            SaveMovieStateCommand = new DelegateCommand(ExecuteSaveMovieState, CanExecuteSaveMovieState);
            ShowAlternativeLocationsCommand = new DelegateCommand(ExecuteShowAlternativeLocations);

            MarkeAsPendingCommand = new DelegateCommand(ExecuteMarkeAsPending, CanExecuteExecuteMarkeAsPending);
            SelectLibraryItemCommand = new DelegateCommand(ExecuteSelectLibraryItem);

            RootItems = new ObservableCollection<LibraryItem>();

        }

        [Import]
        private Lazy<LibraryManager> LibraryManager { get; set; }

        public DelegateCommand SelectLibraryItemCommand { get; set; }

        private void ExecuteSelectLibraryItem(object obj)
        {
            SelectedLibraryItem = (LibraryItem)obj;
        }


        private bool CanExecuteExecuteMarkeAsPending(object arg)
        {
            return SelectedMovie != null;
        }

        public DelegateCommand MarkeAsPendingCommand { get; set; }

        private void ExecuteMarkeAsPending(object obj)
        {
            DatabaseManager.Instance.MarkAsPending(SelectedMovie);
            DatabaseManager.Instance.UpdateProcessingMovies();
            DatabaseManager.Instance.UpdateProcessingTitle(ShowDrivesMoviesOnly);
        }

        public DelegateCommand ShowAlternativeLocationsCommand { get; set; }

        private void ExecuteShowAlternativeLocations(object obj)
        {
            Resolve<AlternativeLocationPresenter>().ShowAlternativeLocations(SelectedMovie);
        }


        private bool CanExecuteSaveMovieState(object arg)
        {
            return SelectedMovie != null;
        }

        private void ExecuteSaveMovieState(object obj)
        {
            lock (DatabaseManager.LockObject)
            {
                var profileMovie = DatabaseManager.Instance.GetOrCreateProfileMovie(SelectedProfile, SelectedMovie);
                if (IsFavoriteMovieChanged(profileMovie))
                {
                    WaitScreen.Show();
                    StatusMessageService.SetStatusMessage("Updating recommended movies...");
                    TasteKidService.Value.UpdateRecommendation(SelectedMovie);
                    StatusMessageService.SetStatusMessage(StatusMessages.Ready);
                    WaitScreen.Hide();
                }
                DatabaseManager.Instance.UpdateProfile(profileMovie, SelectedMovie.IsStarred ? 1 : 0, SelectedMovie.Watched, SelectedMovie.IsInWishList, SelectedMovie.IsNew);
                UpdateTitles();
            }
        }

        public void UpdateTitles()
        {
            DatabaseManager.Instance.UpdateTitles(ShowDrivesMoviesOnly, SelectedProfile);
        }


        private bool _showDrivesMoviesOnly;
        public bool ShowDrivesMoviesOnly
        {
            get { return _showDrivesMoviesOnly; }
            set
            {
                _showDrivesMoviesOnly = value;
                if (ResultMusics.Count > 0 || ResultMovies.Count > 0)
                    SynchronizationContextHelper.Instance.SendInBackground(d => RefreshResult(), null);
                if (SelectedProfile != null)
                    DatabaseManager.Instance.UpdateTitles(ShowDrivesMoviesOnly, SelectedProfile);
                OnPropertyChanged("ShowDrivesMoviesOnly");
            }
        }

        [Import]
        private Lazy<TasteKidService> TasteKidService { get; set; }


        private bool IsFavoriteMovieChanged(ProfileMovie profileMovie)
        {
            return profileMovie.Star > 0 != SelectedMovie.IsStarred || profileMovie.IsInWishList != SelectedMovie.IsInWishList;
        }

        public DelegateCommand SaveMovieStateCommand { get; set; }

        private bool CanExecuteShowMovieInIMDB(object arg)
        {
            return SelectedMovie != null && SelectedMovie.IMDBId != null;
        }

        private bool CanExecuteShowMovieInWindowsExplorer(object arg)
        {
            return SelectedMovie != null;
        }

        private bool CanExecutePlayMovie(object arg)
        {
            return SelectedMovie != null;
        }

        private void RaiseCanExecuteChanged()
        {
            PlayMovieCommand.RaiseCanExecuteChanged();
            ShowMovieInWindowsExplorerCommand.RaiseCanExecuteChanged();
            ShowMovieInIMDBCommand.RaiseCanExecuteChanged();
            SaveMovieStateCommand.RaiseCanExecuteChanged();
            ShowAlternativeLocationsCommand.RaiseCanExecuteChanged();
            MarkeAsPendingCommand.RaiseCanExecuteChanged();
            LibraryManager.Value.RaiseCanExecuteChanged();
        }

        public DelegateCommand ShowMovieInIMDBCommand { get; set; }

        private void ExecuteShowMovieInIMDB(object obj)
        {
            if (SelectedMovie.IMDBId != null)
            {
                var imdbUrl = String.Format("http://www.imdb.com/title/{0}/", SelectedMovie.IMDBId);
                SystemHelper.OpenUrl(imdbUrl);
            }
        }

        private void ExecutePlayMovie(object obj)
        {
            var selectedMovie = obj as Movie ?? SelectedMovie;
            if (selectedMovie != null && VerifyFileLocation(selectedMovie))
                Play(selectedMovie);
        }


        private int _recommendedMovieCount;
        public int RecommendedMovieCount
        {
            get { return _recommendedMovieCount; }
            set
            {
                _recommendedMovieCount = value;
                OnPropertyChanged("RecommendedMovieCount");
            }
        }


        public DelegateCommand ShowMovieInWindowsExplorerCommand { get; set; }

        private void ExecuteShowMovieInWindowsExplorer(object obj)
        {
            var selectedMovie = obj as Movie ?? SelectedMovie;
            if (selectedMovie != null && VerifyFileLocation(selectedMovie))
                SystemHelper.LocateInWndowsExplorer(selectedMovie.FullPath);
        }

        public DelegateCommand PlayMovieCommand { get; set; }


        private ObservableCollection<IMusicDJ> _musicDjs;

        [ImportMany(typeof(IMusicDJ))]
        public ObservableCollection<IMusicDJ> MusicDjs
        {
            get { return _musicDjs; }
            set
            {
                _musicDjs = value;
                OnPropertyChanged("MusicDjs");
            }
        }


        private IMusicDJ _selectedMusicDJ;
        public IMusicDJ SelectedMusicDJ
        {
            get { return _selectedMusicDJ; }
            set
            {
                _selectedMusicDJ = value;
                OnPropertyChanged("SelectedMusicDJ");
            }
        }

        private ObservableCollection<LibraryItem> _playlists;
        public ObservableCollection<LibraryItem> Playlists
        {
            get { return _playlists; }
            set
            {
                _playlists = value;
                OnPropertyChanged("Playlists");
            }
        }


        protected Timer PlayerUpdateTimer { get; set; }

        private void OnPlayerUpdateTimer(object state)
        {
            SynchronizationContextHelper.Instance.SendInBackground(UpdateTimer, state);
        }

        public Music PlayingMusic
        {
            get { return (Music)GetValue(PlayingMusicProperty); }
            set { SetValue(PlayingMusicProperty, value); }
        }

        public static readonly DependencyProperty PlayingMusicProperty =
            DependencyProperty.Register("PlayingMusic", typeof(Music), typeof(LibraryDataSource), new UIPropertyMetadata(null, OnPropertyChanged));


        public ObservableCollection<LibraryItem> RootItems
        {
            get { return (ObservableCollection<LibraryItem>)GetValue(RootItemsProperty); }
            set { SetValue(RootItemsProperty, value); }
        }

        public static readonly DependencyProperty RootItemsProperty =
            DependencyProperty.Register("RootItems", typeof(ObservableCollection<LibraryItem>), typeof(LibraryDataSource), new UIPropertyMetadata(null));


        private ObservableCollection<string> _currentArtists;
        public ObservableCollection<string> CurrentArtists
        {
            get { return _currentArtists; }
            set
            {
                _currentArtists = value;
                OnPropertyChanged("CurrentArtists");
            }
        }

        private ObservableCollection<string> _currentAlbums;
        public ObservableCollection<string> CurrentAlbums
        {
            get { return _currentAlbums; }
            set
            {
                _currentAlbums = value;
                OnPropertyChanged("CurrentAlbums");
            }
        }

        private ObservableCollection<string> _currentComposers;
        public ObservableCollection<string> CurrentComposers
        {
            get { return _currentComposers; }
            set
            {
                _currentComposers = value;
                OnPropertyChanged("CurrentComposers");
            }
        }

        private ObservableCollection<string> _currentGenres;
        public ObservableCollection<string> CurrentGenres
        {
            get { return _currentGenres; }
            set
            {
                _currentGenres = value;
                OnPropertyChanged("CurrentGenres");
            }
        }

        private ObservableCollection<Music> _resultMusics;
        public ObservableCollection<Music> ResultMusics
        {
            get { return _resultMusics; }
            set
            {
                _resultMusics = value;
                OnPropertyChanged("ResultMusics");
            }
        }

        private ObservableCollection<Movie> _resultMovies;
        public ObservableCollection<Movie> ResultMovies
        {
            get { return _resultMovies; }
            set
            {
                _resultMovies = value;
                OnPropertyChanged("ResultMovies");
            }
        }


        public LibraryItem SelectedLibraryItem
        {
            get { return (LibraryItem)GetValue(SelectedLibraryItemProperty); }
            set
            {
                if (value == SelectedLibraryItem)
                {
                    LoadSelectedItemResults();
                }
                SetValue(SelectedLibraryItemProperty, value);
            }
        }

        public IEventAggregator EventAggregator { get; private set; }

        public void LoadLibrary()
        {
            DatabaseManager.Instance.CreateFixedLibraryItems();
            foreach (var rootItem in DatabaseManager.Instance.GetRootLibraryItems())
            {
                SynchronizationContextHelper.Instance.Send(d => RootItems.Add((LibraryItem)d), rootItem);
            }
            RefreshOrderedLibraryItems();

            foreach (var musicDj in MusicDjs)
            {
                musicDj.DataSource = this;
            }
            SelectedMusicDJ = MusicDjs.FirstOrDefault(m => m.Name == MusicDJName.SmartDJ);
            Playlists.Clear();
            Playlists.AddRange(DatabaseManager.Instance.GetAllPlaylists());
            ShowDrivesMoviesOnly = RegistryHelper.ShowDrivesMoviesOnly;
        }

        public void RefreshOrderedLibraryItems()
        {
            var job = new Job(j =>
                                  {
                                      var rootItems = j.Store.GetObject<ObservableCollection<LibraryItem>>();
                                      var orderedLibraryItems = new VirtualizingCollection<LibraryItem>(new LibraryItemProvider(rootItems));
                                      j.Store.Add(orderedLibraryItems);
                                  });
            job.Store.Add(RootItems);
            job.JobCompleted+=(s,e)=> OrderedLibraryItems = job.Store.GetObject<VirtualizingCollection<LibraryItem>>();
            job.Start();
        }

        private IList<LibraryItem> _orderedLibraryItems;
        public IList<LibraryItem> OrderedLibraryItems
        {
            get { return _orderedLibraryItems; }
            set
            {
                _orderedLibraryItems = value;
                OnPropertyChanged("OrderedLibraryItems");
            }
        }

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var dataSource = (LibraryDataSource)d;
            dataSource.DoPropertyChanged(e);
        }

        public bool CanPlay
        {
            get { return (bool)GetValue(CanPlayProperty); }
            set { SetValue(CanPlayProperty, value); }
        }

        public static readonly DependencyProperty CanPlayProperty =
            DependencyProperty.Register("CanPlay", typeof(bool), typeof(LibraryDataSource), new UIPropertyMetadata(false));


        public void DoPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            switch (e.Property.Name)
            {
                case "SelectedLibraryItem":
                    LoadSelectedItemResults();
                    break;
                case "PlayingMusic":
                    MusicPlayer.Source = PlayingMusic != null ? GetPlayingMusicUri(PlayingMusic.FullPath) : null;
                    if (e.OldValue != null)
                    {
                        DatabaseManager.Instance.SetMusicStatus((Music)e.OldValue, PlayingMusic);
                    }
                    if (e.NewValue != null)
                    {
                        DatabaseManager.Instance.SetMusicStatus((Music)e.NewValue, PlayingMusic);
                    }
                    CanPlay = SelectedMusic != null || PlayingMusic != null;
                    EventAggregator.GetEvent<BaseEvent<PlayingMusicEventArgs>>().Publish(new PlayingMusicEventArgs { Sender = this, Music = PlayingMusic });
                    break;
                case "IsPlaying":
                    if (PlayingMusic == null && SelectedMusic != null)
                    {
                        WaitScreen.Show();
                        Play(SelectedMusic);
                        var job = new Job(j =>
                                              {
                                                  var playingMusic = j.Store.GetObject<Music>();
                                                  var resultMusics = j.Store.GetObject<ObservableCollection<Music>>();
                                                  DatabaseManager.Instance.SetNowPlayingPlaylist(resultMusics, resultMusics, playingMusic);
                                                  StartMusicDJ(playingMusic);

                                              });
                        job.Store.Add(PlayingMusic);
                        job.Store.Add(ResultMusics);
                        job.JobCompleted += (s, arg) => WaitScreen.Hide();
                        job.Start();
                    }
                    if (PlayingMusic != null)
                    {
                        if (IsPlaying)
                        {
                            MusicPlayer.Stop();
                            MusicPlayer.Close();
                            MusicPlayer.Play();
                            UpdateTimer(null);
                        }
                        else
                        {
                            MusicPlayer.Pause();
                        }
                    }
                    CanPlay = SelectedMusic != null || PlayingMusic != null;
                    break;
                case "SelectedMusic":
                    CanPlay = SelectedMusic != null || PlayingMusic != null;
                    break;
                case "SelectedMusicDJ":
                    if (PlayingMusic != null)
                    {
                        SelectedMusicDJ.Initialize(PlayingMusic);
                    }
                    break;
                case "MusicPlayer":
                    MusicPlayer.MediaEnded += HandleMediaEndedEvent;
                    MusicPlayer.MediaOpened += HandleMediaOpenedEvent;
                    MusicPlayer.MediaFailed += HandleMediaFailedEvent;
                    break;
                case "NaturalDuration":
                    DatabaseManager.Instance.UpdateDuration(PlayingMusic, NaturalDuration);
                    break;
                case "Position":
                    if (IsUpdatingTime == false)
                        MusicPlayer.Position = Position;
                    break;
                case "SelectedMovie":
                    if (e.NewValue != null)
                    {
                        var movie = ((Movie)e.NewValue);
                        movie.PropertyChanged += MoviePropertyChangedHandler;
                        if (SelectedProfile!=null && movie.IsNew)
                            DatabaseManager.Instance.MarkAsRead(movie,SelectedProfile);
                    }
                    if (e.OldValue != null)
                    {
                        ((Movie)e.OldValue).PropertyChanged -= MoviePropertyChangedHandler;
                    }
                    RaiseCanExecuteChanged();
                    break;
            }
        }

        public void RefreshResult()
        {
            RegistryHelper.ShowDrivesMoviesOnly = ShowDrivesMoviesOnly;
            WaitScreen.Show();
            if (RegistryHelper.LastResultType == LibraryItemType.MusicType)
            {
                SetMusicResults(ResultMusics.ToArray());
            }
            else
            {
                if (_originalResultMovies != null)
                {
                    SetMovieResults(_originalResultMovies);
                }
                DatabaseManager.Instance.UpdateTitles(ShowDrivesMoviesOnly, SelectedProfile);
            }

            WaitScreen.Hide();
        }


        private void MoviePropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            SynchronizationContextHelper.Instance.SendInBackground(d => RaiseCanExecuteChanged(), null);
        }

        private void HandleMediaFailedEvent(object sender, ExceptionRoutedEventArgs e)
        {
            if (PlayingMusic==null)
                return;
            PlayingMusic.Status = MusicStatus.Failed;
            PlayNextMusic();
        }

        private void PlayNextMusic()
        {
            if (PlayingMusic.Status == MusicStatus.Playing)
            {
                DatabaseManager.Instance.AdvanceScore(SelectedProfile, PlayingMusic, 0.5);
            }
            if (SelectedMusicDJ.CanMoveNext)
                SelectedMusicDJ.Next();
        }

        private void HandleMediaOpenedEvent(object sender, RoutedEventArgs e)
        {
            PlayingMusic.Status = MusicStatus.Playing;
        }

        private void HandleMediaEndedEvent(object sender, RoutedEventArgs e)
        {
            if (IsPlaying == false)
                return;
            if (PlayingMusic != null)
            {
                DatabaseManager.Instance.AdvanceScore(SelectedProfile, PlayingMusic, 0.5);
            }
            if (SelectedMusicDJ.CanMoveNext)
            {
                SelectedMusicDJ.Next();
            }
        }

        private void UpdateTimer(object state)
        {
            IsUpdatingTime = true;
            Position = MusicPlayer.Position;
            NaturalDuration = MusicPlayer.NaturalDuration;
            if (NaturalDuration.HasTimeSpan)
            {
                TimeRemains = Position - NaturalDuration.TimeSpan;
            }
            IsUpdatingTime = false;
        }

        protected bool IsUpdatingTime { get; set; }


        public TimeSpan TimeRemains
        {
            get { return (TimeSpan)GetValue(TimeRemainsProperty); }
            set { SetValue(TimeRemainsProperty, value); }
        }

        public static readonly DependencyProperty TimeRemainsProperty =
            DependencyProperty.Register("TimeRemains", typeof(TimeSpan), typeof(LibraryDataSource), new UIPropertyMetadata(default(TimeSpan)));



        public Duration NaturalDuration
        {
            get { return (Duration)GetValue(NaturalDurationProperty); }
            set { SetValue(NaturalDurationProperty, value); }
        }

        public static readonly DependencyProperty NaturalDurationProperty =
            DependencyProperty.Register("NaturalDuration", typeof(Duration), typeof(LibraryDataSource), new UIPropertyMetadata(default(Duration), OnPropertyChanged));


        public TimeSpan Position
        {
            get { return (TimeSpan)GetValue(PositionProperty); }
            set { SetValue(PositionProperty, value); }
        }

        public static readonly DependencyProperty PositionProperty =
            DependencyProperty.Register("Position", typeof(TimeSpan), typeof(LibraryDataSource), new UIPropertyMetadata(default(TimeSpan), OnPropertyChanged));



        private Uri GetPlayingMusicUri(string fullPath)
        {
            if (PlayingMusic != null)
                return new Uri(String.Format("file://{0}", fullPath));
            return null;
        }

        public void AddFilesInBackground(IEnumerable<string> fileNames)
        {
            StatusMessageService.SetStatusMessage("Adding files");
            var job = new Job(j => AddFiles(fileNames));
            job.StartBlocked();
            DatabaseManager.Instance.UpdateNewMovieTitle(ShowDrivesMoviesOnly, SelectedProfile);
            DatabaseManager.Instance.UpdateProcessingTitle(ShowDrivesMoviesOnly);
            StatusMessageService.SetStatusMessage(StatusMessages.Ready);
        }

        private void AddFiles(IEnumerable<string> fileNames)
        {
            WaitScreen.Show(fileNames.Count(), 0);
            var progress = 0;
            foreach (string fileName in fileNames)
            {
                AddFile(fileName, progress++);
            }
        }

        private void AddFile(string fileName, int progress)
        {
            SynchronizationContextHelper.Instance.Send(AddFileWithProgress, new object[] { fileName, progress });
            Thread.Sleep(100);
        }
        [Import]
        public StatusMessageBarPresenter StatusMessageBarPresenter { get; set; }
        private void AddFileWithProgress(object o)
        {
            var fileName = (string)((object[])o)[0];
            var progress = (int)((object[])o)[1];
            WaitScreen.Show(progress);
            if (Utility.IsMusicFile(fileName))
                StatusMessageBarPresenter.SetMessage(String.Format(StatusMessages.AddingMusic, fileName));
            else if (Utility.IsMovieFile(fileName))
            {
                StatusMessageBarPresenter.SetMessage(String.Format(StatusMessages.AddingMovie, fileName));
            }
            DatabaseManager.Instance.AddFile(fileName);
        }

        public void SelectLastImportedPlaylist()
        {
            var lastImportedPlaylist = DatabaseManager.Instance.GetLastImportedPlaylist();
            SelectedLibraryItem = null;
            SelectedLibraryItem = lastImportedPlaylist;
        }

        public void SetMusicResults(IEnumerable<Music> musics)
        {
            ResultMusics.Clear();
            var index = 1;
            WaitScreen.Show(musics.Count(), index - 1);
            foreach (var music in musics)
            {
                music.Index = index++;
                music.Preferance = string.Empty;
                WaitScreen.Show(musics.Count(), index);
                ResultMusics.Add(music);
                Application.Current.DoEvents();
            }
            UpdateCurrentLists();
        }

        public void UpdateCurrentLists()
        {
            WaitScreen.Show();

            CurrentGenres.Clear();
            CurrentGenres.AddRange(ResultMusics.Where(m => string.IsNullOrWhiteSpace(m.Genre) == false).Select(m => m.Genre).Distinct().OrderBy(o => o));
            CurrentArtists.Clear();
            CurrentArtists.AddRange(ResultMusics.Where(m => string.IsNullOrWhiteSpace(m.Artist) == false).Select(m => m.Artist).Distinct().OrderBy(o => o));
            CurrentAlbums.Clear();
            CurrentAlbums.AddRange(ResultMusics.Where(m => string.IsNullOrWhiteSpace(m.Album) == false).Select(m => m.Album).Distinct().OrderBy(o => o));
            CurrentComposers.Clear();
            CurrentComposers.AddRange(ResultMusics.Where(m => string.IsNullOrWhiteSpace(m.Composer) == false).Select(m => m.Composer).Distinct().OrderBy(o => o));
            WaitScreen.Hide();
        }

        public void SetMovieResults(IEnumerable<Movie> movies)
        {
            SetMovieResults(movies, m => m.Rating);
        }

        [Import]
        private WaitScreenService WaitScreen { get; set; }
        public void SetMovieResults(IEnumerable<Movie> movies, Func<Movie, double?> orderBySelector)
        {
            if (movies == null)
                return;
            _originalResultMovies = movies;
            var resultMovies = new ObservableCollection<Movie>();
            resultMovies.Clear();
            var index = 1;
            var resultArray = ShowDrivesMoviesOnly ? movies.Where(m => m.IsLocal()) : movies;
            var orderedArray = orderBySelector == null ? resultArray.ToArray() : resultArray.OrderByDescending(orderBySelector).ToArray();
            WaitScreen.Show(orderedArray.Length, index - 1);
            foreach (var movie in orderedArray)
            {
                movie.Index = index++;
                if (movie.Size==null && File.Exists(movie.FullPath))
                {
                    DatabaseManager.Instance.UpdateMovieFileSize(movie);
                }
                resultMovies.Add(movie);

                WaitScreen.Show(orderedArray.Length, index - 1);
                Application.Current.DoEvents();
            }
            ResultMovies = resultMovies;
            SelectedMovie = ResultMovies.FirstOrDefault();
        }

        public void InitializeMovieForList(Movie movie)
        {
            var profileMovie = DatabaseManager.Instance.GetProfileMovie(SelectedProfile, movie);
            if (profileMovie == null)
            {
                if (String.IsNullOrWhiteSpace(movie.FullPath) == false)
                    movie.IsNew = true;
            }
            else
            {
                movie.IsNew = profileMovie.IsNewMovie();
                movie.IsStarred = profileMovie.Star > 0;
                movie.Watched = profileMovie.Watched;
                movie.IsInWishList = profileMovie.IsInWishList.HasValue && profileMovie.IsInWishList.Value;
            }
        }

        [Import]
        private Lazy<MusicDurationUpdater> MusicDurationUpdater { get; set; }
        public void UpdateDuration()
        {
            var musics = ResultMusics.Where(m => String.IsNullOrWhiteSpace(m.TimeText) && m.Status != "Playing").ToArray();
            if (musics.Count() <= 0) return;
            MusicDurationUpdater.Value.AddRange(musics);
        }

        [Import]
        private Lazy<BackgroundScannerManager> BackgroundScannerManager { get; set; }
        private void LoadSelectedItemResults()
        {
            if (SelectedLibraryItem == null)
                return;
            WaitScreen.Show();
            BackgroundScannerManager.Value.Pause();
            switch (SelectedLibraryItem.Type)
            {
                case LibraryItemType.ProcessingLibrary:
                    SetMovieResults(DatabaseManager.Instance.UpdateProcessingMovies());
                    break;
                case LibraryItemType.FailedLibrary:
                    SetMovieResults(DatabaseManager.Instance.GetFailedMovies());
                    break;
                case LibraryItemType.UnreadMovieLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetNewMovies(SelectedProfile));
                    }
                    break;
                case LibraryItemType.WatchListLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetWatchedMovies(SelectedProfile));
                    }
                    break;
                case LibraryItemType.WishListLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetWishListMovie(SelectedProfile));
                    }
                    break;
                case LibraryItemType.StaredMovieLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetStarMovies(SelectedProfile));
                    }
                    break;
                case LibraryItemType.RecommendedMovieLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetRecommendedMovies(SelectedProfile), null);
                    }
                    break;
                case LibraryItemType.RecentlyPlayedMovieLibrary:
                    if (SelectedProfile != null)
                    {
                        SetMovieResults(DatabaseManager.Instance.GetRecentlyPlayedMovies(SelectedProfile), null);
                    }
                    break;
                case LibraryItemType.IMDbMustWatchList:
                    DatabaseManager.Instance.UpdateIMDBMustWatchList();
                    ShowSelectedLibraryItemsResult();
                    break;
                case LibraryItemType.MovieLibrary:
                    SetMovieResults(DatabaseManager.Instance.GetAllMovies());
                    break;
                case LibraryItemType.MusicLibrary:
                    SetMusicResults(DatabaseManager.Instance.GetAllMusics());
                    UpdateDuration();
                    break;
                
                default:
                    ShowSelectedLibraryItemsResult();
                    break;
            }

            BackgroundScannerManager.Value.Resume();
            EventAggregator.GetEvent<BaseEvent<PerformSelectedItemActionEventArgs>>().Publish(new PerformSelectedItemActionEventArgs(this, SelectedLibraryItem));
            WaitScreen.Hide();
        }

        private void ShowSelectedLibraryItemsResult()
        {
            var job = new Job(ExecuteGetAllMoviesOrMusics);
            job.Store.Add(SelectedLibraryItem);
            job.StartBlocked();
            if (LibraryItemType.IsMusicItem(SelectedLibraryItem.Type))
            {
                SetMusicResults(job.Store.GetObject<IEnumerable<Music>>());
                UpdateDuration();
            }
            else
            {
                SetMovieResults(job.Store.GetObject<IEnumerable<Movie>>());
            }
        }

        private static void ExecuteGetAllMoviesOrMusics(Job obj)
        {
            var libraryItem = obj.Store.GetObject<LibraryItem>();
            if (LibraryItemType.IsMusicItem(libraryItem.Type))
            {
                obj.Store.Add(libraryItem.GetAllMusic());
            }
            else
            {
                obj.Store.Add(libraryItem.GetAllMovies());
            }
        }

        public void Play(Music music)
        {
            if (PlayingMusic == music)
                return;
            PlayingMusic = music;
            DatabaseManager.Instance.AdvanceScore(SelectedProfile, PlayingMusic, 0.5);
            IsPlaying = true;
        }


        public MediaElement MusicPlayer
        {
            get { return (MediaElement)GetValue(MusicPlayerProperty); }
            set { SetValue(MusicPlayerProperty, value); }
        }

        public static readonly DependencyProperty MusicPlayerProperty =
            DependencyProperty.Register("MusicPlayer", typeof(MediaElement), typeof(LibraryDataSource), new UIPropertyMetadata(null, OnPropertyChanged));


        public bool IsPlaying
        {
            get { return (bool)GetValue(IsPlayingProperty); }
            set { SetValue(IsPlayingProperty, value); }
        }

        public Music SelectedMusic
        {
            get { return (Music)GetValue(SelectedMusicProperty); }
            set { SetValue(SelectedMusicProperty, value); }
        }

        public static readonly DependencyProperty SelectedMusicProperty =
            DependencyProperty.Register("SelectedMusic", typeof(Music), typeof(LibraryDataSource), new UIPropertyMetadata(null, OnPropertyChanged));



        public static readonly DependencyProperty IsPlayingProperty =
            DependencyProperty.Register("IsPlaying", typeof(bool), typeof(LibraryDataSource), new UIPropertyMetadata(false, OnPropertyChanged));


        public void AddFolderInBackground(string folderPath)
        {
            AddFilesInBackground(CollectFileNames(folderPath));
        }

        [Import]
        private StatusMessageService StatusMessageService { get; set; }

        private IEnumerable<string> CollectFileNames(string folderPath)
        {
            StatusMessageService.SetStatusMessage("Searching folder for musics and movies");
            var files = new List<string>();
            new Job(j => AddFolderRecursively(folderPath, files)).StartBlocked();
            return files;
        }

        private static void AddFolderRecursively(string folderPath, List<string> files)
        {
            files.AddRange(Directory.GetFiles(folderPath, "*.mp3"));
            files.AddRange(Directory.GetFiles(folderPath, "*.wma"));
            foreach (var extension in Utility.SupportedMovieFileExtension)
            {
                files.AddRange(Directory.GetFiles(folderPath, "*" + extension));
            }

            foreach (string directory in Directory.GetDirectories(folderPath))
            {
                AddFolderRecursively(directory, files);
            }
        }

        public void SelectMusicDJ(string dJName)
        {
            SelectedMusicDJ = MusicDjs.FirstOrDefault(d => d.Name == dJName);
        }

        public void StartMusicDJ(Music playingMusic)
        {
            if (playingMusic == null || SelectedMusicDJ == null) return;
            SelectedMusicDJ.Initialize(playingMusic);
        }

        public void SelectProfile(string profileName)
        {
            SelectedProfile = DatabaseManager.Instance.GetProfile(profileName);
        }

        public Profile SelectedProfile
        {
            get { return _selectedProfile; }
            set
            {
                _selectedProfile = value;
                OnPropertyChanged("SelectedProfile");
                MediaFSManager.Instance.SelectedProfile = value;
            }
        }


        public Movie SelectedMovie
        {
            get { return (Movie)GetValue(SelectedMovieProperty); }
            set { SetValue(SelectedMovieProperty, value); }
        }

        public static readonly DependencyProperty SelectedMovieProperty =
            DependencyProperty.Register("SelectedMovie", typeof(Movie), typeof(LibraryDataSource), new UIPropertyMetadata(null, OnPropertyChanged));

        private IEnumerable<Movie> _originalResultMovies;
        private Profile _selectedProfile;

        public bool IsPlaylistExists(string playlistTitle)
        {
            return Playlists.Any(p => String.Compare(p.Title, playlistTitle, true) == 0);
        }

        public LibraryItem CreatePlaylist(string playlistTitle)
        {
            var playlist = DatabaseManager.Instance.CreatePlaylist(playlistTitle);
            Playlists.Add(playlist);
            return playlist;
        }

        public LibraryItem GetPlaylist(string playlistTitle)
        {
            return Playlists.FirstOrDefault(p => String.Compare(p.Title, playlistTitle) == 0);
        }

        public void UpdateMusic(Music music)
        {
            var position = Position;
            if (music == PlayingMusic)
            {
                MusicPlayer.Stop();
                MusicPlayer.Close();
            }
            DatabaseManager.Instance.UpdateAndLink(music);
            if (PlayingMusic != null && music == PlayingMusic)
            {
                MusicPlayer.Source = GetPlayingMusicUri(PlayingMusic.FullPath);
                MusicPlayer.Position = position;
                if (IsPlaying)
                {
                    MusicPlayer.Play();
                }
            }
        }


        public void UpdateMovie(Movie movie, JObject jsonObject)
        {
            var newMovie = DatabaseManager.Instance.UpdateMovie(movie, jsonObject);
            if (movie.Equals(newMovie) == false)
            {
                var resultMovie = ResultMovies.FirstOrDefault(m => m.Equals(movie));
                if (resultMovie != null)
                {
                    newMovie.Index = resultMovie.Index;
                    ResultMovies.Remove(movie);
                    InsertMovieToCurrentResult(newMovie);
                    var originalResult = _originalResultMovies.ToList();
                    originalResult.Remove(resultMovie);
                    _originalResultMovies = originalResult;
                }
            }
        }

        private void InsertMovieToCurrentResult(Movie newMovie)
        {
            ResultMovies.Insert(newMovie.Index - 1, newMovie);
        }

        public void SelectYear(int year)
        {
            SelectedLibraryItem = DatabaseManager.Instance.GetYearLibraryItem(year);
        }

        private void Play(Movie movie)
        {
            DatabaseManager.Instance.IncrementPlayCount(movie, SelectedProfile);
            SystemHelper.PlayMovie(movie.FullPath);
        }

        private static bool VerifyFileLocation(Movie movie)
        {
            bool isExist = true;
            if (File.Exists(movie.FullPath) == false)
            {
                if (
                    MessageBox.Show(String.Format("Cannot access {0}. Press Ok to browse the movie?", movie.FullPath),
                                    "Cannot Access", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    var fileDialog = new OpenFileDialog { Filter = Utility.SupportedMovieFileFilter, Multiselect = false };
                    if (fileDialog.ShowDialog() == true)
                    {
                        DatabaseManager.Instance.UpdateMovieLocation(movie, fileDialog.FileName);

                    }
                    else
                    {
                        isExist = false;
                    }
                }
                else
                {
                    isExist = false;
                }
            }
            return isExist;
        }

        public void InitializeDatabase()
        {
            MusicPlayer.Volume = RegistryHelper.Volume;
            MusicPlayer.IsMuted = RegistryHelper.IsMuted;
            if (MediaAssistantEntities.IsUpdatedVersion == false)
            {
                DatabaseManager.Instance.ConvertOldVersionMusicLibrary();
            }
            SelectProfile(RegistryHelper.ProfileName);
            LoadLibrary();
            var selectedMusicDj = MusicDjs.SingleOrDefault(m => m.Name == RegistryHelper.SelectedMusicDJ);
            if (selectedMusicDj != null)
                SelectedMusicDJ = selectedMusicDj;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) KAZ Software Limited
Bangladesh Bangladesh
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions