/// <summary>
        /// Creates a ExportWindowView and attaches an instance of ExportViewModel to it.
        /// </summary>
        /// <returns>The ViewModel of the Window.</returns>
        public static ExportViewModel SpawnExportWindowView(Project project, string videoPath, double durationSeconds, List<Description> descriptionList, LoadingViewModel loadingViewModel)
        {
            var viewModel = new ExportViewModel(project, videoPath, durationSeconds, descriptionList, loadingViewModel);
            var view = new ExportWindow(viewModel);
            viewModel.DialogResult = view.ShowDialog();

            return viewModel;
        }
        public ExportViewModel(Project project, string videoPath, double durationSeconds, List<Description> descriptionList, LoadingViewModel loadingViewModel)
        {
            ChoosePathCommand = new RelayCommand(ChoosePath);
            ExportCommand = new RelayCommand(ExportProject, CanExport);

            _project = project;
            _videoPath = videoPath;
            _durationSeconds = durationSeconds;
            _descriptionList = descriptionList;
            _loadingViewModel = loadingViewModel;
        }
        public ProjectManager(LoadingViewModel loadingViewModel, UndoRedoManager undoRedoManager)
        {
            _undoRedoManager = undoRedoManager;

            _allDescriptions = new ObservableCollection<Description>();
            _allDescriptions.CollectionChanged += DescriptionsOnCollectionChanged;

            _extendedDescriptions = new ObservableCollection<Description>();
            _extendedDescriptions.CollectionChanged +=
                ObservableCollectionIndexer<Description>.CollectionChangedListener;
            _extendedDescriptions.CollectionChanged += ObservableCollection_ProjectModifiedHandler;

            _regularDescriptions = new ObservableCollection<Description>();
            _regularDescriptions.CollectionChanged +=
                ObservableCollectionIndexer<Description>.CollectionChangedListener;
            _regularDescriptions.CollectionChanged += ObservableCollection_ProjectModifiedHandler;

            _spaces = new ObservableCollection<Space>();
            _spaces.CollectionChanged += ObservableCollectionIndexer<Space>.CollectionChangedListener;
            _spaces.CollectionChanged += SpacesOnCollectionChanged;
            _spaces.CollectionChanged += ObservableCollection_ProjectModifiedHandler;

            _projectLoader = new ProjectLoader(loadingViewModel);
            _projectLoader.DescriptionsLoaded += (sender, args) => AddDescriptions(args.Value);
            _projectLoader.SpacesLoaded += (sender, args) => Spaces.AddRange(args.Value);
            _projectLoader.SpacesAudioAnalysisCompleted += (sender, args) =>
            {
                Spaces.AddRange(args.Item2);
                //Save autogenerated spaces to file.
                FileWriter.WriteSpacesFile(args.Item1, Spaces);
            };
            _projectLoader.ProjectLoaded += (sender, args) =>
            {
                Project = args.Value;
                IsProjectModified = false;
                OnProjectLoaded(Project);
            };
        }
 public ProjectLoader(LoadingViewModel loadingViewModel)
 {
     _loadingViewModel = loadingViewModel;
 }
        public MainViewModel(ILiveDescribePlayer mediaVideo)
        {
            DispatcherHelper.Initialize();

            _undoRedoManager = new UndoRedoManager();
            _loadingViewModel = new LoadingViewModel(100, null, 0, false);
            _projectManager = new ProjectManager(_loadingViewModel, _undoRedoManager);
            _descriptionRecordingViewModel = new DescriptionRecordingViewModel(mediaVideo,
                _projectManager);
            _mediaViewModel = new MediaViewModel(mediaVideo, _projectManager);
            _preferences = new PreferencesViewModel();
            _intervalInfoListViewModel = new IntervalInfoListViewModel(_projectManager, _descriptionRecordingViewModel);
            _markingSpacesViewModel = new MarkingSpacesViewModel(_intervalInfoListViewModel, mediaVideo, _undoRedoManager);
            _audioCanvasViewModel = new AudioCanvasViewModel(mediaVideo, _projectManager, _undoRedoManager);
            _descriptionCanvasViewModel = new DescriptionCanvasViewModel(mediaVideo, _projectManager, _undoRedoManager);
            _numberLineViewModel = new NumberLineViewModel(mediaVideo);
            _timelineViewModel = new TimelineViewModel(_audioCanvasViewModel, _descriptionCanvasViewModel, _mediaViewModel,
                _numberLineViewModel, _projectManager);

            _mediaVideo = mediaVideo;

            DescriptionPlayer = new DescriptionPlayer();
            DescriptionPlayer.DescriptionFinishedPlaying += (sender, e) =>
            {
                try
                {
                    DispatcherHelper.UIDispatcher.Invoke(() =>
                        _mediaViewModel.ResumeFromDescription(e.Value));
                }
                catch (TaskCanceledException exception)
                {
                    Log.Warn("Task Canceled Exception", exception);
                }
            };

            #region Commands
            //Commands
            CloseProject = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    if (_projectManager.IsProjectModified)
                    {
                        var result = MessageBoxFactory.ShowWarningQuestion(
                            string.Format(UiStrings.MessageBox_Format_SaveProjectWarning, _project.ProjectName));

                        if (result == MessageBoxResult.Yes)
                            SaveProject.Execute();
                        else if (result == MessageBoxResult.Cancel)
                            return;
                    }

                    _projectManager.CloseProject();
                });

            NewProject = new RelayCommand(() =>
            {
                var viewModel = DialogShower.SpawnNewProjectView();

                if (viewModel.DialogResult != true)
                    return;

                if (viewModel.CopyVideo)
                    CopyVideoAndSetProject(viewModel.VideoPath, viewModel.Project);
                else
                    SetProject(viewModel.Project);
            });

            OpenProject = new RelayCommand(() =>
            {
                var projectChooser = new OpenFileDialog
                {
                    Filter = string.Format(UiStrings.OpenFileDialog_Format_OpenProject, Project.Names.ProjectExtension)
                };

                bool? dialogSuccess = projectChooser.ShowDialog();
                if (dialogSuccess != true)
                    return;

                OpenProjectPath.Execute(projectChooser.FileName);
            });

            OpenProjectPath = new RelayCommand<string>(path =>
            {
                //Attempt to read project. If object fields are missing, an error window pops up.
                try
                {
                    Project p = FileReader.ReadProjectFile(path);
                    SetProject(p);
                }
                catch (JsonSerializationException)
                {
                    MessageBoxFactory.ShowError(UiStrings.MessageBox_OpenProjectFileMissingError);
                }
                catch (DirectoryNotFoundException e)
                {
                    Log.Warn("Directory not found while trying to open project", e);
                    MessageBoxFactory.ShowError(UiStrings.MessageBox_DirectoryNotFoundError);
                }
                catch (FileNotFoundException e)
                {
                    Log.Warn("FileNotFound while trying to open project", e);
                    MessageBoxFactory.ShowError(string.Format(UiStrings.MessageBox_Format_FileNotFoundError,
                        e.FileName));
                }
            });

            ClearRecentProjects = new RelayCommand(() =>
            {
                Settings.Default.RecentProjects.Clear();
                Settings.Default.Save();
            });

            ShowImportAudioDescription = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var viewModel = DialogShower.SpawnImportAudioDescriptionView(_projectManager, _mediaVideo.DurationMilliseconds);
                }
               );

            SaveProject = new RelayCommand(
                canExecute: () => _projectManager.IsProjectModified,
                execute: () => _projectManager.SaveProject()
            );

            ExportWithDescriptions = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var viewModel = DialogShower.SpawnExportWindowView(_project, _mediaVideo.Path,
                        _mediaVideo.DurationSeconds, _projectManager.AllDescriptions.ToList(),
                        _loadingViewModel);

                    if (viewModel.DialogResult != true)
                        return;
                });

            ClearCache = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var p = _project;

                    CloseProject.Execute();

                    Directory.Delete(p.Folders.Cache, true);

                    SetProject(p);
                });

            ShowPreferences = new RelayCommand(() =>
            {
                _preferences.RetrieveApplicationSettings();
                var preferencesWindow = new PreferencesWindow(_preferences);
                preferencesWindow.ShowDialog();
            });

            FindSpaces = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var spaces = AudioAnalyzer.FindSpaces(_mediaViewModel.Waveform);
                    _projectManager.Spaces.AddRange(spaces);
                }
            );

            ExportDescriptionsTextToSrt = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var saveFileDialog = new SaveFileDialog
                    {
                        FileName = Path.GetFileNameWithoutExtension(_mediaViewModel.Path),
                        Filter = UiStrings.SaveFileDialog_ExportToSrt
                    };

                    saveFileDialog.ShowDialog();
                    FileWriter.WriteDescriptionsTextToSrtFile(saveFileDialog.FileName,
                        _projectManager.AllDescriptions);
                }
            );

            ExportSpacesTextToSrt = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var saveFileDialog = new SaveFileDialog
                    {
                        FileName = Path.GetFileNameWithoutExtension(_mediaViewModel.Path),
                        Filter = UiStrings.SaveFileDialog_ExportToSrt
                    };

                    saveFileDialog.ShowDialog();
                    FileWriter.WriteSpacesTextToSrtFile(saveFileDialog.FileName, _projectManager.Spaces);
                }
            );

            ShowDescriptionFolder = new RelayCommand(
                canExecute: () => _projectManager.HasProjectLoaded,
                execute: () =>
                {
                    var pfi = new ProcessStartInfo("Explorer.exe", _project.Folders.Descriptions.AbsolutePath);
                    Process.Start(pfi);
                }
            );

            ShowAboutInfo = new RelayCommand(DialogShower.SpawnAboutInfoView);
            #endregion

            //If apply requested happens  in the preferences use the new saved microphone in the settings
            _descriptiontimer = new Timer(10);
            _descriptiontimer.Elapsed += Play_Tick;
            _descriptiontimer.AutoReset = true;

            #region MediaViewModel Events
            _mediaViewModel.PlayRequested += (sender, e) =>
            {
                _mediaVideo.Play();
                _descriptiontimer.Start();
                //this Handler should be attached to the view to update the graphics
                OnPlayRequested(sender, e);
            };

            _mediaViewModel.PauseRequested += (sender, e) =>
            {
                _mediaVideo.Pause();
                _descriptiontimer.Stop();
                if (_lastRegularDescriptionPlayed != null && _lastRegularDescriptionPlayed.IsPlaying)
                    DescriptionPlayer.Stop();
                //this Handler should be attached to the view to update the graphics
                OnPauseRequested(sender, e);
            };

            _mediaViewModel.OnPausedForExtendedDescription += (sender, e) =>
            {
                _mediaVideo.Pause();
                _descriptiontimer.Stop();
                CommandManager.InvalidateRequerySuggested();
            };

            _mediaViewModel.MuteRequested += OnMuteRequested;

            _mediaViewModel.MediaEndedEvent += (sender, e) =>
            {
                _descriptiontimer.Stop();
                _mediaVideo.Stop();
                OnMediaEnded(sender, e);
            };
            #endregion

            #region Property Changed Events

            _mediaViewModel.PropertyChanged += PropertyChangedHandler;

            //Update window title based on project name
            PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == "IsProjectModified")
                    SetWindowTitle();
            };

            #endregion

            #region ProjectManager Events
            _projectManager.ProjectLoaded += (sender, args) =>
            {
                _project = args.Value;

                _mediaViewModel.LoadVideo(_project.Files.Video);

                SetWindowTitle();
            };

            _projectManager.ProjectModifiedStateChanged += (sender, args) => SetWindowTitle();

            _projectManager.ProjectClosed += (sender, args) =>
            {
                TryToCleanUpUnusedDescriptionAudioFiles();
                _project = null;

                SetWindowTitle();
            };
            #endregion

            SetWindowTitle();
        }