/// <summary>
        /// Gets the number of pools under the specified account
        /// </summary>
        public static int GetPoolCount(BatchController controller, BatchAccountContext context)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListPoolOptions options = new ListPoolOptions(context, behaviors);

            return client.ListPools(options).Count();
        }
        /// <summary>
        /// Creates a test job schedule for use in Scenario tests.
        /// </summary>
        public static void CreateTestJobSchedule(BatchController controller, BatchAccountContext context, string jobScheduleId, TimeSpan? recurrenceInterval)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            PSJobSpecification jobSpecification = new PSJobSpecification();
            jobSpecification.PoolInformation = new PSPoolInformation();
            jobSpecification.PoolInformation.PoolId = SharedPool;
            PSSchedule schedule = new PSSchedule();
            if (recurrenceInterval != null)
            {
                schedule = new PSSchedule();
                schedule.RecurrenceInterval = recurrenceInterval;
            }

            NewJobScheduleParameters parameters = new NewJobScheduleParameters(context, jobScheduleId, behaviors)
            {
                JobSpecification = jobSpecification,
                Schedule = schedule
            };

            client.CreateJobSchedule(parameters);
        }
        /// <summary>
        /// Creates a test user for use in Scenario tests.
        /// </summary>
        public static void CreateComputeNodeUser(BatchController controller, BatchAccountContext context, string poolId, string computeNodeId, string computeNodeUserName)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            NewComputeNodeUserParameters parameters = new NewComputeNodeUserParameters(context, poolId, computeNodeId, null, behaviors)
            {
                ComputeNodeUserName = computeNodeUserName,
                Password = "Password1234!",
            };

            client.CreateComputeNodeUser(parameters);
        }
        /// <summary>
        /// Creates a test workitem for use in Scenario tests.
        /// </summary>
        public static void CreateTestWorkItem(BatchController controller, BatchAccountContext context, string workItemName, TimeSpan? recurrenceInterval)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            PSJobExecutionEnvironment jobExecutionEnvironment = new PSJobExecutionEnvironment();
            jobExecutionEnvironment.PoolName = DefaultPoolName;
            PSWorkItemSchedule schedule = null;
            if (recurrenceInterval != null)
            {
                schedule = new PSWorkItemSchedule();
                schedule.RecurrenceInterval = recurrenceInterval;
            }

            NewWorkItemParameters parameters = new NewWorkItemParameters(context, workItemName, behaviors)
            {
                JobExecutionEnvironment = jobExecutionEnvironment,
                Schedule = schedule
            };

            client.CreateWorkItem(parameters);
        }
        /// <summary>
        /// Deletes a job used in a Scenario test.
        /// </summary>
        public static void DeleteJob(BatchController controller, BatchAccountContext context, string jobId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            client.DeleteJob(context, jobId, behaviors);
        }
        /// <summary>
        /// Gets the id of a compute node in the specified pool
        /// </summary>
        public static string GetComputeNodeId(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListComputeNodeOptions options = new ListComputeNodeOptions(context, poolId, null, behaviors);

            return client.ListComputeNodes(options).First().Id;
        }
        /// <summary>
        /// Creates a test pool for use in Scenario tests.
        /// </summary>
        public static void CreateTestPool(BatchController controller, BatchAccountContext context, string poolName)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            NewPoolParameters parameters = new NewPoolParameters(context, poolName, behaviors)
            {
                OSFamily = "4",
                TargetOSVersion = "*",
                TargetDedicated = 1
            };

            client.CreatePool(parameters);
        }
        /// <summary>
        /// Creates a test task for use in Scenario tests.
        /// </summary>
        public static void CreateTestTask(BatchController controller, BatchAccountContext context, string jobId, string taskId, string cmdLine = "cmd /c dir /s")
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            NewTaskParameters parameters = new NewTaskParameters(context, jobId, null, taskId, behaviors)
            {
                CommandLine = cmdLine,
                RunElevated = true
            };
            
            client.CreateTask(parameters);
        }
        /// <summary>
        /// Creates a test user for use in Scenario tests.
        /// </summary>
        public static void CreateTestUser(BatchController controller, BatchAccountContext context, string poolName, string vmName, string vmUserName)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            NewVMUserParameters parameters = new NewVMUserParameters(context, poolName, vmName, null, behaviors)
            {
                VMUserName = vmUserName,
                Password = "Password1234!",
            };

            client.CreateVMUser(parameters);
        }
        /// <summary>
        /// Deletes a user used in a Scenario test.
        /// </summary>
        public static void DeleteUser(BatchController controller, BatchAccountContext context, string poolName, string vmName, string vmUserName)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            VMUserOperationParameters parameters = new VMUserOperationParameters(context, poolName, vmName, vmUserName, behaviors);
            client.DeleteVMUser(parameters);
        }
        /// <summary>
        /// Deletes a workitem used in a Scenario test.
        /// </summary>
        public static void DeleteWorkItem(BatchController controller, BatchAccountContext context, string workItemName)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            client.DeleteWorkItem(context, workItemName, behaviors);
        }
        /// <summary>
        /// Waits for the specified task to complete
        /// </summary>
        public static void WaitForTaskCompletion(BatchController controller, BatchAccountContext context, string workItemName, string jobName, string taskName)
        {
            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListTaskOptions options = new ListTaskOptions(context, workItemName, jobName, null, behaviors)
            {
                TaskName = taskName
            };
            IEnumerable<PSCloudTask> tasks = client.ListTasks(options);

            ITaskStateMonitor monitor = context.BatchOMClient.OpenToolbox().CreateTaskStateMonitor();
            monitor.WaitAll(tasks.Select(t => t.omObject), TaskState.Completed, TimeSpan.FromMinutes(2), null, behaviors);
        }
        /// <summary>
        /// Waits for a recent job on a workitem and returns its name. If a previous job is specified, this method waits until a new job is created.
        /// </summary>
        public static string WaitForRecentJob(BatchController controller, BatchAccountContext context, string workItemName, string previousJob = null)
        {
            DateTime timeout = DateTime.Now.AddMinutes(2);

            YieldInjectionInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListWorkItemOptions options = new ListWorkItemOptions(context, behaviors)
            {
                WorkItemName = workItemName,
                Filter = null,
                MaxCount = Constants.DefaultMaxCount
            };
            PSCloudWorkItem workItem = client.ListWorkItems(options).First();

            while (workItem.ExecutionInformation.RecentJob == null || string.Equals(workItem.ExecutionInformation.RecentJob.Name, previousJob, StringComparison.OrdinalIgnoreCase))
            {
                if (DateTime.Now > timeout)
                {
                    throw new TimeoutException("Timed out waiting for recent job");
                }
                Sleep(5000);
                workItem = client.ListWorkItems(options).First();
            }
            return workItem.ExecutionInformation.RecentJob.Name;
        }
        /// <summary>
        /// Creates a test job for use in Scenario tests.
        /// </summary>
        public static void CreateTestJob(BatchController controller, BatchAccountContext context, string jobId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            PSPoolInformation poolInfo = new PSPoolInformation();
            poolInfo.PoolId = SharedPool;

            NewJobParameters parameters = new NewJobParameters(context, jobId, behaviors)
            {
                PoolInformation = poolInfo
            };

            client.CreateJob(parameters);
        }
        public static void EnableAutoScale(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            string formula = "$TargetDedicated=2";
            AutoScaleParameters parameters = new AutoScaleParameters(context, poolId, null, formula, behaviors);
            client.EnableAutoScale(parameters);
        }
        /// <summary>
        /// Waits for a recent job on a job schedule and returns its id. If a previous job is specified, this method waits until a new job is created.
        /// </summary>
        public static string WaitForRecentJob(BatchController controller, BatchAccountContext context, string jobScheduleId, string previousJob = null)
        {
            DateTime timeout = DateTime.Now.AddMinutes(2);
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListJobScheduleOptions options = new ListJobScheduleOptions(context, behaviors)
            {
                JobScheduleId = jobScheduleId,
                Filter = null,
                MaxCount = Constants.DefaultMaxCount
            };
            PSCloudJobSchedule jobSchedule = client.ListJobSchedules(options).First();

            while (jobSchedule.ExecutionInformation.RecentJob == null || string.Equals(jobSchedule.ExecutionInformation.RecentJob.Id, previousJob, StringComparison.OrdinalIgnoreCase))
            {
                if (DateTime.Now > timeout)
                {
                    throw new TimeoutException("Timed out waiting for recent job");
                }
                Sleep(5000);
                jobSchedule = client.ListJobSchedules(options).First();
            }
            return jobSchedule.ExecutionInformation.RecentJob.Id;
        }
        public static void DisableAutoScale(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            PoolOperationParameters parameters = new PoolOperationParameters(context, poolId, null, behaviors);
            client.DisableAutoScale(parameters);
        }
        /// <summary>
        /// Waits for the specified task to complete
        /// </summary>
        public static void WaitForTaskCompletion(BatchController controller, BatchAccountContext context, string jobId, string taskId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListTaskOptions options = new ListTaskOptions(context, jobId, null, behaviors)
            {
                TaskId = taskId
            };
            IEnumerable<PSCloudTask> tasks = client.ListTasks(options);

            // Save time by not waiting during playback scenarios
            if (HttpMockServer.Mode == HttpRecorderMode.Record)
            {
                TaskStateMonitor monitor = context.BatchOMClient.Utilities.CreateTaskStateMonitor();
                monitor.WaitAll(tasks.Select(t => t.omObject), TaskState.Completed, TimeSpan.FromMinutes(2), null);
            }
        }
        public static string WaitForOSVersionChange(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListPoolOptions options = new ListPoolOptions(context, behaviors)
            {
                PoolId = poolId
            };

            DateTime timeout = DateTime.Now.AddMinutes(2);
            PSCloudPool pool = client.ListPools(options).First();
            while (pool.CurrentOSVersion != pool.TargetOSVersion)
            {
                if (DateTime.Now > timeout)
                {
                    throw new TimeoutException("Timed out waiting for active state pool");
                }
                Sleep(5000);
                pool = client.ListPools(options).First();
            }

            return pool.TargetOSVersion;
        }
        /// <summary>
        /// Terminates a job
        /// TODO: Replace with terminate Job client method when it exists.
        /// </summary>
        public static void TerminateJob(BatchAccountContext context, string jobId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };

            context.BatchOMClient.JobOperations.TerminateJob(jobId, additionalBehaviors: behaviors);
        }
        public static void WaitForSteadyPoolAllocation(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListPoolOptions options = new ListPoolOptions(context, behaviors)
            {
                PoolId = poolId
            };

            DateTime timeout = DateTime.Now.AddMinutes(2);
            PSCloudPool pool = client.ListPools(options).First();
            while (pool.AllocationState != AllocationState.Steady)
            {
                if (DateTime.Now > timeout)
                {
                    throw new TimeoutException("Timed out waiting for steady allocation state");
                }
                Sleep(5000);
                pool = client.ListPools(options).First();
            }
        }
        /// <summary>
        /// Waits for a compute node to get to the idle state
        /// </summary>
        public static void WaitForIdleComputeNode(BatchController controller, BatchAccountContext context, string poolId, string computeNodeId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListComputeNodeOptions options = new ListComputeNodeOptions(context, poolId, null, behaviors)
            {
                ComputeNodeId = computeNodeId
            };

            DateTime timeout = DateTime.Now.AddMinutes(2);
            PSComputeNode computeNode = client.ListComputeNodes(options).First();
            if (computeNode.State != ComputeNodeState.Idle)
            {
                if (DateTime.Now > timeout)
                {
                    throw new TimeoutException("Timed out waiting for idle compute node");
                }

                Sleep(5000);
                computeNode = client.ListComputeNodes(options).First();
            }
        }
        /// <summary>
        /// Gets the CurrentDedicated count from a pool
        /// </summary>
        public static int GetPoolCurrentDedicated(BatchController controller, BatchAccountContext context, string poolId)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ListPoolOptions options = new ListPoolOptions(context, behaviors)
            {
                PoolId = poolId
            };

            PSCloudPool pool = client.ListPools(options).First();
            return pool.CurrentDedicated.Value;
        }
        /// <summary>
        /// Creates a test pool for use in Scenario tests.
        /// </summary>
        public static void CreateTestPool(BatchController controller, BatchAccountContext context, string poolId, int targetDedicated)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            NewPoolParameters parameters = new NewPoolParameters(context, poolId, behaviors)
            {
                VirtualMachineSize = "small",
                OSFamily = "4",
                TargetOSVersion = "*",
                TargetDedicated = targetDedicated,
            };

            client.CreatePool(parameters);
        }
        /// <summary>
        /// Deletes a compute node user for use in Scenario tests.
        /// </summary>
        public static void DeleteComputeNodeUser(BatchController controller, BatchAccountContext context, string poolId, string computeNodeId, string computeNodeUserName)
        {
            RequestInterceptor interceptor = CreateHttpRecordingInterceptor();
            BatchClientBehavior[] behaviors = new BatchClientBehavior[] { interceptor };
            BatchClient client = new BatchClient(controller.BatchManagementClient, controller.ResourceManagementClient);

            ComputeNodeUserOperationParameters parameters = new ComputeNodeUserOperationParameters(context, poolId, computeNodeId, computeNodeUserName, behaviors);

            client.DeleteComputeNodeUser(parameters);
        }