public void PreviousAndNext()
        {
            var manager = new PlaylistManager();
            manager.AddAndReplaceItems(threeItems);

            Assert.IsFalse(manager.CanPreviousItem);
            Assert.IsFalse(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.CurrentItem = threeItems[0]);
            Assert.IsFalse(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanPreviousItem, () => manager.NextItem());
            Assert.AreEqual(threeItems[1], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.NextItem());
            Assert.AreEqual(threeItems[2], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsFalse(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.PreviousItem());
            Assert.AreEqual(threeItems[1], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);
        }
        public void SearchTextTest()
        {
            var viewModel = Container.GetExportedValue<PlaylistViewModel>();
            var view = Container.GetExportedValue<MockPlaylistView>();
            PlaylistItem scrollIntoViewItem = null;
            view.ScrollIntoViewStub = x => scrollIntoViewItem = x;
            bool focusSearchBoxCalled = false;
            view.FocusSearchBoxStub = () => focusSearchBoxCalled = true;

            var musicFiles = new[]
            {
                MockMusicFile.CreateEmpty(@"C:\Users\Public\Music\Dancefloor\Culture Beat - Serenity.wav"),
                MockMusicFile.CreateEmpty(@"C:\Future Breeze - Why don't you dance with me.mp3"),
                MockMusicFile.CreateEmpty(@"C:\Culture Beat - Serenity - Epilog.wma"),
            };
            var playlistManager = new PlaylistManager();
            playlistManager.AddAndReplaceItems(musicFiles.Select(x => new PlaylistItem(x)));
            viewModel.PlaylistManager = playlistManager;
            
            viewModel.SearchText = "Bill";
            Assert.IsNull(viewModel.SelectedPlaylistItem);
            Assert.IsNull(scrollIntoViewItem);
            Assert.IsTrue(focusSearchBoxCalled);

            viewModel.SearchText = "Cul";
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[0], scrollIntoViewItem);

            // Selection stays on the same item
            viewModel.SearchText = "Cultur";
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[0], scrollIntoViewItem);

            viewModel.SearchText = "Epi";
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[2], scrollIntoViewItem);

            // Selection stays on the same item
            scrollIntoViewItem = null;
            viewModel.SearchText = "";
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            Assert.IsNull(scrollIntoViewItem);

            viewModel.SelectedPlaylistItem = playlistManager.Items[1];

            // Search starts from selection
            viewModel.SearchText = "Cul";
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[2], scrollIntoViewItem);
        }
        public void PreviousAndNextWithShuffle()
        {
            var randomService = new MockRandomService();
            int randomNumber = 0;
            int lastMaxValue = -1;
            randomService.NextRandomNumberStub = maxValue =>
            {
                lastMaxValue = maxValue;
                return randomNumber;
            };

            var manager = new PlaylistManager(3, randomService);
            manager.AddAndReplaceItems(threeItems);
            manager.Shuffle = true;

            Assert.IsFalse(manager.CanPreviousItem);
            Assert.IsFalse(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.CurrentItem = threeItems[0]);
            Assert.IsFalse(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);

            randomNumber = 1;
            AssertHelper.PropertyChangedEvent(manager, x => x.CanPreviousItem, () => manager.NextItem());
            Assert.AreEqual(1, lastMaxValue);
            Assert.AreEqual(threeItems[2], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);

            randomNumber = 0;
            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.NextItem());
            Assert.AreEqual(0, lastMaxValue);
            Assert.AreEqual(threeItems[1], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsFalse(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.PreviousItem());
            Assert.AreEqual(threeItems[2], manager.CurrentItem);
            Assert.IsTrue(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);

            AssertHelper.PropertyChangedEvent(manager, x => x.CanPreviousItem, () => manager.PreviousItem());
            Assert.AreEqual(threeItems[0], manager.CurrentItem);
            Assert.IsFalse(manager.CanPreviousItem);
            Assert.IsTrue(manager.CanNextItem);
        }
        public void SearchNextAndPrevious()
        {
            var viewModel = Container.GetExportedValue<PlaylistViewModel>();
            var view = Container.GetExportedValue<MockPlaylistView>();
            
            var musicFiles = new[]
            {
                MockMusicFile.CreateEmpty(@"C:\Culture Beat"),
                MockMusicFile.CreateEmpty(@"C:\Culture Beat"),
                MockMusicFile.CreateEmpty(@"C:\Culture Beat"),
                MockMusicFile.CreateEmpty(@"C:\Foo"),
            };
            var playlistManager = new PlaylistManager();
            playlistManager.AddAndReplaceItems(musicFiles.Select(x => new PlaylistItem(x)));
            viewModel.PlaylistManager = playlistManager;

            viewModel.SearchText = "Culture";
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);

            viewModel.SearchNextCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[1], viewModel.SelectedPlaylistItem);

            viewModel.SearchNextCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            
            viewModel.SearchNextCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);

            viewModel.SearchPreviousCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);

            viewModel.SearchPreviousCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[1], viewModel.SelectedPlaylistItem);

            viewModel.SearchPreviousCommand.Execute(null);
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);
        }
        public void SearchTextIsContainedTest()
        {
            var viewModel = Container.GetExportedValue<PlaylistViewModel>();
            var view = Container.GetExportedValue<MockPlaylistView>();
            PlaylistItem scrollIntoViewItem = null;
            view.ScrollIntoViewStub = x => scrollIntoViewItem = x;

            var musicFiles = new[]
            {
                CreateMockMusicFile(@"C:\Music\Foo.mp3", "1 title", "1 artist"),
                CreateMockMusicFile(@"C:\Music\Baz.wma", "2 TiTle", "2 ArTisT"),
                CreateMockMusicFile(@"C:\Music\Abc.mp3", "3 TITLE", "3a artist", "3B ARTIST"),
                new MusicFile(x => Task.FromResult((MusicMetadata)null), "do not load"),
            };
            var playlistManager = new PlaylistManager();
            playlistManager.AddAndReplaceItems(musicFiles.Select(x => new PlaylistItem(x)));
            viewModel.PlaylistManager = playlistManager;

            viewModel.SearchText = "1 TIT";
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[0], scrollIntoViewItem);

            viewModel.SearchText = "1 ART";
            Assert.AreEqual(playlistManager.Items[0], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[0], scrollIntoViewItem);

            viewModel.SearchText = "3B art";
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            Assert.AreEqual(playlistManager.Items[2], scrollIntoViewItem);

            // File name is not considered as Title & Artist are set and shown.
            scrollIntoViewItem = null;
            viewModel.SearchText = "baz";
            Assert.AreEqual(playlistManager.Items[2], viewModel.SelectedPlaylistItem);
            Assert.IsNull(scrollIntoViewItem);

            // Ensure that the search feature does not load the metadata of all Playlist items.
            Assert.IsFalse(musicFiles.Last().IsMetadataLoaded);
        }
        public void TotalDurationWithMetadataLoading()
        {
            var manager = new PlaylistManager();
            Assert.AreEqual(TimeSpan.Zero, manager.TotalDuration);
            var firstFile = new MockMusicFile(new MusicMetadata(TimeSpan.FromSeconds(10), 0), "");
            manager.AddAndReplaceItems(new[] { new PlaylistItem(firstFile) });
            
            var secondMetadata = new MusicMetadata(TimeSpan.FromSeconds(20), 0);
            var secondFile = new MusicFile(async x =>
            {
                await Task.Delay(10);
                return secondMetadata;
            }, "");

            manager.AddItems(new[] { new PlaylistItem(secondFile) });
            Assert.IsTrue(manager.IsTotalDurationEstimated);
            Assert.AreEqual(TimeSpan.FromSeconds(20), manager.TotalDuration);
            AssertHelper.PropertyChangedEvent(manager, x => x.TotalDuration, () => secondFile.GetMetadataAsync().GetResult());
            Assert.IsFalse(manager.IsTotalDurationEstimated);
            Assert.AreEqual(TimeSpan.FromSeconds(30), manager.TotalDuration);

            var thirdFile = new MockMusicFile(new MusicMetadata(TimeSpan.FromSeconds(30), 0), "");
            AssertHelper.PropertyChangedEvent(manager, x => x.TotalDuration, () => manager.AddItems(new[] { new PlaylistItem(thirdFile) }));
            Assert.AreEqual(TimeSpan.FromSeconds(60), manager.TotalDuration);
        }
        public void AddRemoveAndMoveItems()
        {
            var manager = new PlaylistManager();
            Assert.AreEqual(0, manager.Items.Count);

            manager.AddItems(threeItems);
            Assert.AreEqual(3, manager.Items.Count);

            manager.RemoveItems(new[] { threeItems[2] });
            Assert.AreEqual(2, manager.Items.Count);

            manager.AddAndReplaceItems(threeItems);
            Assert.AreEqual(3, manager.Items.Count);

            manager.MoveItems(2, new[] { manager.Items[0] });
            Assert.IsTrue(manager.Items.SequenceEqual(new[] { threeItems[1], threeItems[2], threeItems[0] }));
        }
        public void NextWithShuffleAndRepeatAndOneItem()
        {
            var manager = new PlaylistManager();
            manager.AddAndReplaceItems(threeItems.Take(1));
            manager.Shuffle = true;
            manager.Repeat = true;
            manager.CurrentItem = threeItems[0];

            manager.NextItem();
            Assert.AreEqual(threeItems[0], manager.CurrentItem);
        }
        public void PreviousAndNextWithClear()
        {
            var manager = new PlaylistManager();
            manager.AddAndReplaceItems(threeItems);
            manager.CurrentItem = threeItems[1];

            Assert.IsTrue(manager.CanPreviousItem);
            AssertHelper.PropertyChangedEvent(manager, x => x.CanPreviousItem, () => manager.ClearItems());
            Assert.IsFalse(manager.CanPreviousItem);
            AssertHelper.ExpectedException<InvalidOperationException>(() => manager.PreviousItem());

            manager.AddAndReplaceItems(threeItems);
            manager.CurrentItem = threeItems[1];

            Assert.IsTrue(manager.CanNextItem);
            AssertHelper.PropertyChangedEvent(manager, x => x.CanNextItem, () => manager.ClearItems());
            Assert.IsFalse(manager.CanNextItem);
            AssertHelper.ExpectedException<InvalidOperationException>(() => manager.NextItem());
        }
        public void PreviousAndNextWithRepeat()
        {
            var manager = new PlaylistManager();
            manager.AddAndReplaceItems(threeItems);
            manager.Repeat = true;
            manager.CurrentItem = threeItems[0];

            for (int i = 0; i < 5; i++)
            {
                Assert.AreEqual(threeItems[i % 3], manager.CurrentItem);
                Assert.IsTrue(manager.CanNextItem);
                manager.NextItem();
            }

            manager.Shuffle = true;

            for (int i = 0; i < 5; i++)
            {
                Assert.IsTrue(manager.CanNextItem);
                manager.NextItem();
            }
        }
        public void ResetNextWithShuffle()
        {
            var manager = new PlaylistManager();
            manager.AddAndReplaceItems(threeItems);
            manager.Shuffle = true;
            manager.CurrentItem = threeItems[0];

            for (int i = 0; i < 2; i++)
            {
                Assert.IsTrue(manager.CanNextItem);
                manager.NextItem();
            }

            Assert.IsFalse(manager.CanNextItem);

            manager.Reset();

            for (int i = 0; i < 2; i++)
            {
                Assert.IsTrue(manager.CanNextItem);
                manager.NextItem();
            }

            Assert.IsFalse(manager.CanNextItem);
        }