private async void AddCommand_Click(object sender, RoutedEventArgs e)
        {
            var selectedScene = SceneGrid.SelectedItem as Scene;
            if (selectedScene == null) return;

            SceneCmdsGrid.SelectedItems.Clear();
            var sceneStoredCommand = new SceneStoredCommand();

            //Send it to the command builder to get filled with a command
            var cbWindow = new CommandBuilder(_context, sceneStoredCommand) { Owner = _app.ZvsWindow };

            if (!(cbWindow.ShowDialog() ?? false)) return;

            //Set Order
            var max = selectedScene.Commands.Max(o => o.SortOrder);
            if (max.HasValue)
                sceneStoredCommand.SortOrder = max.Value + 1;
            else
                sceneStoredCommand.SortOrder = 0;

            if (selectedScene.IsRunning)
            {
                ShowSceneEditWarning(selectedScene.Name);
            }
            else
            {
                selectedScene.Commands.Add(sceneStoredCommand);

                var result = await _context.TrySaveChangesAsync(_app.Cts.Token);
                if (result.HasError)
                    await Log.ReportErrorFormatAsync(_app.Cts.Token, "Error adding scene command. {0}", result.Message);

                SceneCmdsGrid.SelectedItems.Add(sceneStoredCommand);
            }
        }
        public async Task RunSceneAsyncMultipleCommandCancelRunTest()
        {
            //Arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Scene-RunSceneAsyncMultipleCommandCancelRunTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e);
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };
            var cts = new CancellationTokenSource();
            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    if (ranstoredCommands.Count == 2)
                    {
                        cts.Cancel();
                    }

                    return Task.FromResult(Result.ReportSuccessFormat("Ran command Id:{0}", commandId));
                }
            };
            var scene = new Scene
            {
                Name = "I have one command"
            };

            var cmd1 = new Command
            {
                Description = "Command 1"
            };
            var command1 = new SceneStoredCommand
            {
                SortOrder = 1,
                TargetObjectName = "Device 1",
                Description = "Turn On Device 1",
                Command = cmd1
            };

            var cmd2 = new Command
            {
                Description = "Command 2"
            };
            var command2 = new SceneStoredCommand
            {
                SortOrder = 2,
                Description = "TIME DELAY",
                Command = cmd2
            };

            var cmd3 = new Command
            {
                Description = "Command 3"
            };
            var command3 = new SceneStoredCommand
            {
                SortOrder = 3,
                TargetObjectName = "Device 3",
                Description = "Turn On Device 3",
                Command = cmd3
            };

            scene.Commands.Add(command3);
            scene.Commands.Add(command1);
            scene.Commands.Add(command2);

            using (var context = new ZvsContext(dbConnection))
            {
                context.Scenes.Add(scene);
                await context.SaveChangesAsync(CancellationToken.None);
            }

           
            var sceneRunner = new SceneRunner(log, commandProcessor, dbConnection);

            //Act
            var result = await sceneRunner.RunSceneAsync(scene.Id, cts.Token);

            Console.WriteLine(result.Message);

            //Assert
            Assert.IsFalse(result.HasError);
            Assert.IsTrue(logEntries.Count(o => o.Level == LogEntryLevel.Warn) == 0, "Expected one warning log entries");
            Assert.IsTrue(logEntries.Count(o => o.Level == LogEntryLevel.Error) == 0, "Expected zero error log entries");
            Assert.IsTrue(ranstoredCommands.Count == 2, "Scene runner did not run the correct amount of commands.");
        }
        private async Task DeleteSelectedSceneCommandsAsync()
        {
            if (SceneCmdsGrid.SelectedItems.Count > 0)
            {
                var selectedItemsCopy = new SceneStoredCommand[SceneCmdsGrid.SelectedItems.Count];
                SceneCmdsGrid.SelectedItems.CopyTo(selectedItemsCopy, 0);

                if (MessageBox.Show(
                    $"Are you sure you want to delete {SceneCmdsGrid.SelectedItems.Count} selected scene command(s)?",
                                   "Are you sure?", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    foreach (var sceneStoredCommand in selectedItemsCopy)
                    {
                        var storedCommand = sceneStoredCommand;
                        var sceneCommand = await _context.SceneStoredCommands.FirstOrDefaultAsync(o => o.Id == storedCommand.Id);
                        if (sceneCommand != null)
                            _context.SceneStoredCommands.Local.Remove(sceneCommand);
                    }

                    var result = await _context.TrySaveChangesAsync(_app.Cts.Token);
                    if (result.HasError)
                        await Log.ReportErrorFormatAsync(_app.Cts.Token, "Error deleting scene command. {0}", result.Message);
                }
            }
        }
        public async Task RunSceneAsyncOneCommandTest()
        {
            //Arrange 
            var dbConnection = new UnitTestDbConnection();
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccessFormat("Ran command Id:{0}", commandId));
                }
            };
            var scene = new Scene
            {
                Name = "I have one command"
            };

            var command1 = new SceneStoredCommand
            {
                SortOrder = 1,
                TargetObjectName = "Device 1",
                Description = "Turn On",
                Command = new Command
                {
                    Description = "Command 1"
                }
            };

            scene.Commands.Add(command1);

            using (var context = new ZvsContext(dbConnection))
            {
                context.Scenes.Add(scene);
                await context.SaveChangesAsync(CancellationToken.None);
            }

            var cts = new CancellationTokenSource();
            var sceneRunner = new SceneRunner(log, commandProcessor, dbConnection);

            //Act
            var result = await sceneRunner.RunSceneAsync(scene.Id, cts.Token);
            Console.WriteLine(result.Message);

            //Assert
            Assert.IsFalse(result.HasError);
            Assert.IsTrue(logEntries.All(o => o.Level == LogEntryLevel.Info), "Expected only info type log entries");
            Assert.IsTrue(ranstoredCommands.Count == 1, "Scene runner did not run the correct amount of commands.");
            Assert.IsTrue(ranstoredCommands.All(o => o == command1.Id), "Scene runner did not run the correct command.");
        }