/// <summary>
        /// Sets up this instance using the specified client controller host name.
        /// </summary>
        /// <param name="clientControllerHostName">Name of the client controller host.</param>
        public static OfficeWorkerActivityController Create(string clientControllerHostName, string instanceId)
        {
            // The office worker is a separate process, so it must make a call up to the client controller to obtain
            // the manifest that will be used for the test.
            SystemManifest manifest = null;

            using (var serviceConnection = ClientControllerServiceConnection.Create(clientControllerHostName))
            {
                var data = serviceConnection.Channel.GetManifest(instanceId);
                manifest = SystemManifest.Deserialize(data);
                manifest.PushToGlobalDataStore(instanceId);
                manifest.PushToGlobalSettings();
                _sessionId    = manifest.SessionId;
                _statusLogger = new VirtualResourceInstanceStatusLogger(_sessionId, Environment.UserName, 0, Enum.GetName(typeof(RuntimeState), 6), false, GlobalDataStore.ResourceInstanceId);
            }


            TraceFactory.Logger.Debug("Resource type: {0}".FormatWith(manifest.ResourceType));
            TraceFactory.Logger.Debug("InstanceId: {0}".FormatWith(GlobalDataStore.ResourceInstanceId));
            TraceFactory.Logger.Debug("UserName: {0}".FormatWith(GlobalDataStore.Credential.UserName));

            FrameworkServicesInitializer.InitializeExecution();

            return(ObjectFactory.Create <OfficeWorkerActivityController>(manifest.ResourceType, clientControllerHostName));
        }
        /// <summary>
        /// Runs the Schedule of activities.
        /// </summary>
        public void Run(VirtualResourceInstanceStatusLogger logger)
        {
            var schedule = LegacySerializer.DeserializeXml <ExecutionSchedule>(_workerDetail.ExecutionSchedule);

            _virtualResourceStatusLogger = logger;


            if (schedule.SegmentCount > 0)
            {
                TraceFactory.Logger.Debug("Will process {0} segments in this scheduled execution.".FormatWith(schedule.SegmentCount));
            }
            else
            {
                TraceFactory.Logger.Debug("There are no scheduled items to execute, aborting...");
                Halt();
                return;
            }

            // Start the flow monitor to collect time on any pause events that will be used to adjust the total run time
            _flowControlMonitor.Start();

            // Set the base time in the scheduled execution object as the base time reference.
            schedule.BaseTime = _baseTime;
            TraceFactory.Logger.Debug("Base Time {0}".FormatWith(_baseTime));

            try
            {
                // Handle any startup delay that may occur because there is a staggered startup.
                var endTime = schedule.CalculateInitialEndTime();

                // Begin executing the schedule according to execution type (Repeat or Duration)
                int count = 0;
                if (schedule.UseDuration)
                {
                    TraceFactory.Logger.Debug("Duration execution starting...");

                    TimeSpan totalDuration = new TimeSpan(0, schedule.Duration, 0);

                    var scheduledExpiration = _baseTime.Add(totalDuration);
                    TraceFactory.Logger.Debug("Schedule Expiration at {0}".FormatWith(scheduledExpiration));

                    if (scheduledExpiration < endTime)
                    {
                        TraceFactory.Logger.Debug("Expiration earlier than initial end time, stopping at {0}".FormatWith(scheduledExpiration));

                        // The schedule expiration will hit before the first end time, so just delay
                        // for the expiration period and then return.  Adjust the expiration to account
                        // for any wall clock time lost from the base.
                        TimeSpan lostTime = DateTime.Now - _baseTime;
                        TimeSpan duration = totalDuration - lostTime;

                        _flowControlMonitor.Pause(() => !ExecutionHalted, duration, TimeSpan.FromSeconds(1));
                        return;
                    }
                    else if (endTime > _baseTime)
                    {
                        // Sleep for any startup time that is there because of a stagger setting
                        TimeSpan duration = endTime - DateTime.Now;

                        TraceFactory.Logger.Debug("Initial sleep until {0}".FormatWith(endTime));
                        _flowControlMonitor.Pause(() => !ExecutionHalted, duration, TimeSpan.FromSeconds(1));
                    }

                    // While the endtime is less than the schedule's expiration, execution the next
                    // schedule.  When endTime exceeds the schedules expiration, then we are done.
                    do
                    {
                        // Calculate a new end time based on the previous value and the current schedule iteration
                        TraceFactory.Logger.Debug("End Time {0}".FormatWith(endTime));
                        var scheduleSegment = schedule.CalculateNextEndTime(endTime, count++);

                        endTime = scheduleSegment.Item1;
                        var state = scheduleSegment.Item2;

                        TraceFactory.Logger.Debug("New End Time {0}, State {1}".FormatWith(endTime, state));

                        if (endTime > scheduledExpiration.Add(_flowControlMonitor.PauseTime))
                        {
                            endTime = scheduledExpiration.Add(_flowControlMonitor.PauseTime);
                            TraceFactory.Logger.Debug("End time later than Schedule Expiration");
                        }

                        RunSchedule(state, endTime);

                        // Include any pause time that has accumulated during the run to ensure the
                        // test runs the for the full duration.
                    } while (endTime < scheduledExpiration.Add(_flowControlMonitor.PauseTime));

                    TraceFactory.Logger.Debug("Duration execution complete");
                }
                else
                {
                    TraceFactory.Logger.Debug("Repeat Count execution starting...");

                    if (endTime > _baseTime)
                    {
                        // Sleep for any startup time that is there because of a stagger setting
                        TimeSpan duration = endTime - DateTime.Now;

                        TraceFactory.Logger.Debug("Initial sleep until {0}".FormatWith(endTime));
                        _flowControlMonitor.Pause(() => !ExecutionHalted, duration, TimeSpan.FromSeconds(1));
                    }

                    // Execute each segment until the total repeat count is met, which is the
                    // number of segments x repeat count.
                    do
                    {
                        endTime = endTime + _flowControlMonitor.PauseTime;

                        var scheduleSegment = schedule.CalculateNextEndTime(endTime, count++);
                        endTime = scheduleSegment.Item1;
                        var state = scheduleSegment.Item2;
                        TraceFactory.Logger.Debug("State: " + state + " , Endtime: " + endTime);
                        RunSchedule(state, endTime);
                        TraceFactory.Logger.Debug(count + " of " + schedule.TotalIterations);
                    } while (count < schedule.TotalIterations);

                    TraceFactory.Logger.Debug("Repeat Count execution complete");
                }
            }
            catch (WorkerHaltedException ex)
            {
                TraceFactory.Logger.Debug(ex.Message);
                return;
            }
        }