public App()
        {
            var tracksSerializer    = new iTunesXMLTracksDeserializer();
            var tracksRepository    = new SerializingTracksRepository(tracksSerializer);
            var playlistsRepository = new FakePlaylistsRepository(tracksRepository);

            var service = new LocalLibraryService(tracksRepository, tracksRepository);

            var audio         = new CSCoreAudioPlaybackEngine();
            var windowManager = new CustomWindowManager();
            var dialog        = new WindowsDialogService(windowManager);
            var proxy         = new LibraryViewModelsProxy(service, t => new TrackViewModel(t));
            //var tagger = new TagLibSharpAudioFileTagger();
            //var audioDurationCalc = new CSCoreAudioFileDurationCalculator();
            //var audioFIProvider = new LocalAudioFileInfoProvider(tagger, audioDurationCalc);

            var libraryVM   = new LibraryViewModel(proxy);
            var libraryView = new LibraryWindow()
            {
                DataContext = libraryVM
            };
            var libraryConductor = new CustomWindowManager.WindowConductor(libraryVM, libraryView);

            libraryView.ShowDialog();

            //var shellVM = new ShellViewModel(audio, service, dialog, libraryVM, new PlaybackControlsViewModel(audio, new PlaybackTimelineViewModel(audio)));
            //var shellView = new ShellWindow() { DataContext = shellVM };
            //var shellConductor = new CustomWindowManager.WindowConductor(shellVM, shellView);
            //shellView.ShowDialog();

            this.Shutdown();
        }
        public LibraryViewModel(
            IAudioFileInfoProvider audioFileInfoProvider,
            //IReadLibraryService readLibraryService,
            IWriteLibraryService writeLibraryService,
            IAudioPlaybackEngine audioPlaybackEngine,
            IDialogService dialogService,
            LibraryViewModelsProxy libraryViewModelsProxy
            //Func<Track, EditTrackTagsViewModel> editTrackViewModelFactoryMethod,
            //Func<PlaylistBase, PlaylistBaseViewModel> playlistBaseViewModelFactoryMethod
            )
        {
            this._audioFileInfoProvider = audioFileInfoProvider ?? throw new ArgumentNullException(nameof(audioFileInfoProvider));
            //this._readLibraryService = readLibraryService ?? throw new ArgumentNullException(nameof(readLibraryService));
            this._writeLibraryService    = writeLibraryService ?? throw new ArgumentNullException(nameof(writeLibraryService));
            this._audioPlaybackEngine    = audioPlaybackEngine ?? throw new ArgumentNullException(nameof(audioPlaybackEngine));
            this._dialogService          = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
            this._libraryViewModelsProxy = libraryViewModelsProxy ?? throw new ArgumentNullException(nameof(libraryViewModelsProxy));

            //this._editTrackTagsViewModelFactoryMethod = editTrackViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(editTrackViewModelFactoryMethod));
            //this._playlistBaseViewModelFactoryMethod = playlistBaseViewModelFactoryMethod ?? throw new ArgumentNullException(nameof(playlistBaseViewModelFactoryMethod));

            this._serialViewModelsChangesSubscription = new SerialDisposable().DisposeWith(this._disposables);

            this.ShowFilePicker = ReactiveCommand.CreateFromTask(
                async() =>
            {
                var openFileDialogResult = this._dialogService.OpenFileDialog(
                    "Add files to library ...",
                    Environment.GetFolderPath(Environment.SpecialFolder.MyMusic),
                    true,
                    new Dictionary <string, IReadOnlyCollection <string> >
                {
                    { "Audio files", this._audioPlaybackEngine.SupportedExtensions }
                });

                if (openFileDialogResult.IsConfirmed != true)
                {
                    return;
                }

                IList <AddTrackCommand> atc = new List <AddTrackCommand>();

                foreach (var filePath in openFileDialogResult.Content)
                {
                    var audioFileInfo = await this._audioFileInfoProvider.ExtractAudioFileInfo(new Uri(filePath));
                    if (audioFileInfo == null)
                    {
                        // TODO: handle & log
                    }

                    atc.Add(new AddTrackCommand(
                                audioFileInfo.Location,
                                audioFileInfo.Duration,
                                audioFileInfo.LastModifiedDateTime,
                                audioFileInfo.SizeBytes,
                                audioFileInfo.Tags.Title,
                                audioFileInfo.Tags.PerformersNames,
                                audioFileInfo.Tags.ComposersNames,
                                audioFileInfo.Tags.Year,
                                new TrackAlbumAssociation(
                                    new Album(
                                        audioFileInfo.Tags.AlbumTitle,
                                        audioFileInfo.Tags.AlbumAuthors,
                                        audioFileInfo.Tags.AlbumTracksCount,
                                        audioFileInfo.Tags.AlbumDiscsCount),
                                    audioFileInfo.Tags.AlbumTrackNumber,
                                    audioFileInfo.Tags.AlbumDiscNumber)));
                }

                //var addedTracks =
                await this._writeLibraryService.AddTracksAsync(atc);
            })
                                  .DisposeWith(this._disposables);
            this.ShowFilePicker.ThrownExceptions.Subscribe(x =>
            {
                // TODO: log
                Debug.WriteLine(x);
            });

            this.AllTracksViewModel = this._libraryViewModelsProxy.AllTracksViewModel;

            //this._libraryViewModelsProxy.PlaylistViewModelsChanges.Bind(out var playlists).Subscribe(_ => this.PlaylistViewModelsROOC = playlists).DisposeWith(this._disposables);
            //this._libraryViewModelsProxy.PlaylistViewModels
            //    .Cast<IChangeSet<TracksSubsetViewModel, uint>>()
            //    .StartWithItem(this.AllTracksViewModel, 0u)
            //    .Bind(out var subsets).Subscribe(_ => this.PlaylistViewModelsROOC = playlists).DisposeWith(this._disposables);
        }