/// <summary>
        /// Adds new result to workflow state - Don't override this
        /// </summary>
        /// <param name="control"></param>
        /// <param name="result"></param>
        internal virtual void AddResult(string control, string result)
        {
            var state = SchedulableStateSerializer.Deserialize(control);

            if (state == null)
            {
                state = new SchedulableState();
            }

            if (!_decisionContext.Results.ContainsKey(state.StepNumber))
            {
                _decisionContext.Results.Add(state.StepNumber, new Dictionary <int, string>());
            }

            var res = _decisionContext.Results[state.StepNumber];

            res[state.ActionNumber] = result;
        }
        /// <summary>
        /// Fills the decision context (a god object contains all the particular data based on event type).
        /// </summary>
        /// <param name="historyEvent">Amazon history event. It's a core Amazon SWF object storing all the serialized workflow events. </param>
        internal void ProcessDecisionContext(HistoryEvent historyEvent, WorkflowDecisionContext decisionContext)
        {
            //impl
            if (historyEvent.EventType == EventType.WorkflowExecutionStarted)
            {
                decisionContext.DecisionType  = historyEvent.EventType;
                decisionContext.InputRef      = historyEvent.WorkflowExecutionStartedEventAttributes.Input;
                decisionContext.StartingInput = historyEvent.WorkflowExecutionStartedEventAttributes.Input;
                if (historyEvent.WorkflowExecutionStartedEventAttributes.ParentWorkflowExecution != null)
                {
                    decisionContext.WorkflowParentId =
                        historyEvent.WorkflowExecutionStartedEventAttributes.ParentWorkflowExecution.WorkflowId;
                }

                AddInput(decisionContext.InputRef);
            }
            //impl
            else if (historyEvent.EventType == EventType.WorkflowExecutionContinuedAsNew)
            {
                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.InputRef     = historyEvent.WorkflowExecutionContinuedAsNewEventAttributes.Input;
            }
            else if (historyEvent.EventType == EventType.WorkflowExecutionCancelRequested)
            {
                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.Cause        = historyEvent.WorkflowExecutionCancelRequestedEventAttributes.Cause;
            }
            else if (historyEvent.EventType == EventType.DecisionTaskCompleted)
            {
                // If a decision task completed event was encountered, use it to save
                // some of the key information as the execution context is not available as part of
                // the rest of the ActivityTask* event attributes.
                // NB: We don't act on this event.
                decisionContext.ScheduledEventId = historyEvent.DecisionTaskCompletedEventAttributes.ScheduledEventId;
                decisionContext.StartedEventId   = historyEvent.DecisionTaskCompletedEventAttributes.StartedEventId;
                decisionContext.ExecutionContext =
                    WorkflowStateSerializer.Deserialize(historyEvent.DecisionTaskCompletedEventAttributes.ExecutionContext);
            }
            else if (historyEvent.EventType == EventType.ActivityTaskScheduled)
            {
                // If an activity task scheduled event was encountered, use it to save
                // some of the key information as the activity information is not available as part of
                // the rest of the ActivityTask* event attributes. We don't act on this event.
                decisionContext.ActivityId      = historyEvent.ActivityTaskScheduledEventAttributes.ActivityId;
                decisionContext.ActivityName    = historyEvent.ActivityTaskScheduledEventAttributes.ActivityType.Name;
                decisionContext.ActivityVersion = historyEvent.ActivityTaskScheduledEventAttributes.ActivityType.Version;
                decisionContext.Control         = historyEvent.ActivityTaskScheduledEventAttributes.Control;
                decisionContext.InputRef        = historyEvent.ActivityTaskScheduledEventAttributes.Input;

                // Remove related timer if applicable.
                var state = SchedulableStateSerializer.Deserialize(decisionContext.Control);
                foreach (var timer in decisionContext.Timers)
                {
                    var timerState = SchedulableStateSerializer.Deserialize(timer.Value.Control);
                    if (timerState != null && timerState.Equals(state))
                    {
                        if (decisionContext.FiredTimers.ContainsKey(timer.Key))
                        {
                            decisionContext.FiredTimers.Remove(timer.Key);
                        }

                        decisionContext.Timers.Remove(timer.Key);
                        break;
                    }
                }
            }
            //impl
            else if (historyEvent.EventType == EventType.ActivityTaskCompleted)
            {
                decisionContext.DecisionType     = historyEvent.EventType;
                decisionContext.ScheduledEventId = historyEvent.ActivityTaskCompletedEventAttributes.ScheduledEventId;
                decisionContext.StartedEventId   = historyEvent.ActivityTaskCompletedEventAttributes.StartedEventId;
                decisionContext.ResultRef        = historyEvent.ActivityTaskCompletedEventAttributes.Result;

                var evt = FindEventTypeById(decisionContext.ScheduledEventId);
                decisionContext.ActivityId = evt.ActivityTaskScheduledEventAttributes.ActivityId;
                decisionContext.Control    = evt.ActivityTaskScheduledEventAttributes.Control;
                decisionContext.InputRef   = evt.ActivityTaskScheduledEventAttributes.Input;

                AddInput(decisionContext.InputRef);
                AddResult(decisionContext.Control, decisionContext.ResultRef);
            }
            //impl
            else if (historyEvent.EventType == EventType.ActivityTaskFailed)
            {
                decisionContext.DecisionType     = historyEvent.EventType;
                decisionContext.ScheduledEventId = historyEvent.ActivityTaskFailedEventAttributes.ScheduledEventId;
                decisionContext.StartedEventId   = historyEvent.ActivityTaskFailedEventAttributes.StartedEventId;
                decisionContext.Details          = historyEvent.ActivityTaskFailedEventAttributes.Details;
                decisionContext.Reason           = historyEvent.ActivityTaskFailedEventAttributes.Reason;

                var evt = FindEventTypeById(decisionContext.ScheduledEventId);
                decisionContext.ActivityId = evt.ActivityTaskScheduledEventAttributes.ActivityId;
                decisionContext.Control    = evt.ActivityTaskScheduledEventAttributes.Control;
                decisionContext.InputRef   = evt.ActivityTaskScheduledEventAttributes.Input;
            }
            //impl
            else if (historyEvent.EventType == EventType.ActivityTaskTimedOut)
            {
                decisionContext.DecisionType     = historyEvent.EventType;
                decisionContext.ScheduledEventId = historyEvent.ActivityTaskTimedOutEventAttributes.ScheduledEventId;
                decisionContext.StartedEventId   = historyEvent.ActivityTaskTimedOutEventAttributes.StartedEventId;
                decisionContext.Details          = historyEvent.ActivityTaskTimedOutEventAttributes.Details;
                decisionContext.TimeoutType      = historyEvent.ActivityTaskTimedOutEventAttributes.TimeoutType;

                var evt = FindEventTypeById(decisionContext.ScheduledEventId);
                decisionContext.ActivityId = evt.ActivityTaskScheduledEventAttributes.ActivityId;
                decisionContext.Control    = evt.ActivityTaskScheduledEventAttributes.Control;
                decisionContext.InputRef   = evt.ActivityTaskScheduledEventAttributes.Input;
            }
            else if (historyEvent.EventType == EventType.ScheduleActivityTaskFailed)
            {
                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.ActivityId   = historyEvent.ScheduleActivityTaskFailedEventAttributes.ActivityId;
                decisionContext.DecisionTaskCompletedEventId = historyEvent.ScheduleActivityTaskFailedEventAttributes.DecisionTaskCompletedEventId;
                decisionContext.ActivityName    = historyEvent.ScheduleActivityTaskFailedEventAttributes.ActivityType.Name;
                decisionContext.ActivityVersion = historyEvent.ScheduleActivityTaskFailedEventAttributes.ActivityType.Version;
                decisionContext.Cause           = historyEvent.ScheduleActivityTaskFailedEventAttributes.Cause;
            }
            else if (historyEvent.EventType == EventType.StartChildWorkflowExecutionInitiated)
            {
                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.InputRef     = historyEvent.StartChildWorkflowExecutionInitiatedEventAttributes.Input;
                decisionContext.Control      = historyEvent.StartChildWorkflowExecutionInitiatedEventAttributes.Control;

                //decisionContext.WorkflowId = historyEvent.StartChildWorkflowExecutionInitiatedEventAttributes.WorkflowId;
                decisionContext.ChildWorkflowName =
                    historyEvent.StartChildWorkflowExecutionInitiatedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion =
                    historyEvent.StartChildWorkflowExecutionInitiatedEventAttributes.WorkflowType.Version;

                AddInput(decisionContext.InputRef);
            }
            else if (historyEvent.EventType == EventType.ChildWorkflowExecutionStarted)
            {
                decisionContext.DecisionType         = historyEvent.EventType;
                decisionContext.ChildWorkflowName    = historyEvent.ChildWorkflowExecutionStartedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion = historyEvent.ChildWorkflowExecutionStartedEventAttributes.WorkflowType.Version;
                //decisionContext.WorkflowId = historyEvent.ChildWorkflowExecutionStartedEventAttributes.WorkflowExecution.WorkflowId;
                decisionContext.WorkflowExecRunId = historyEvent.ChildWorkflowExecutionStartedEventAttributes.WorkflowExecution.RunId;
            }
            //impl
            else if (historyEvent.EventType == EventType.ChildWorkflowExecutionCompleted)
            {
                decisionContext.DecisionType         = historyEvent.EventType;
                decisionContext.ChildWorkflowName    = historyEvent.ChildWorkflowExecutionCompletedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion = historyEvent.ChildWorkflowExecutionCompletedEventAttributes.WorkflowType.Version;
                decisionContext.ResultRef            = historyEvent.ChildWorkflowExecutionCompletedEventAttributes.Result;

                var evt = FindEventTypeById(historyEvent.ChildWorkflowExecutionCompletedEventAttributes.InitiatedEventId);
                decisionContext.Control = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Control;

                AddInput(evt.StartChildWorkflowExecutionInitiatedEventAttributes.Input);
                AddResult(decisionContext.Control, decisionContext.ResultRef);
            }
            //impl
            else if (historyEvent.EventType == EventType.ChildWorkflowExecutionFailed)
            {
                decisionContext.DecisionType         = historyEvent.EventType;
                decisionContext.ChildWorkflowName    = historyEvent.ChildWorkflowExecutionFailedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion =
                    historyEvent.ChildWorkflowExecutionFailedEventAttributes.WorkflowType.Version;
                decisionContext.Details           = historyEvent.ChildWorkflowExecutionFailedEventAttributes.Details;
                decisionContext.Reason            = historyEvent.ChildWorkflowExecutionFailedEventAttributes.Reason;
                decisionContext.WorkflowExecRunId =
                    historyEvent.ChildWorkflowExecutionFailedEventAttributes.WorkflowExecution.RunId;

                var evt = FindEventTypeById(historyEvent.ChildWorkflowExecutionFailedEventAttributes.InitiatedEventId);
                decisionContext.Control  = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Control;
                decisionContext.InputRef = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Input;
            }
            else if (historyEvent.EventType == EventType.ChildWorkflowExecutionTerminated)
            {
                decisionContext.DecisionType         = historyEvent.EventType;
                decisionContext.ChildWorkflowName    = historyEvent.ChildWorkflowExecutionTerminatedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion =
                    historyEvent.ChildWorkflowExecutionTerminatedEventAttributes.WorkflowType.Version;
                decisionContext.Details           = "";
                decisionContext.WorkflowExecRunId =
                    historyEvent.ChildWorkflowExecutionTerminatedEventAttributes.WorkflowExecution.RunId;

                var evt = FindEventTypeById(historyEvent.ChildWorkflowExecutionTerminatedEventAttributes.InitiatedEventId);
                decisionContext.Control  = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Control;
                decisionContext.InputRef = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Input;
            }
            //impl
            else if (historyEvent.EventType == EventType.ChildWorkflowExecutionTimedOut)
            {
                decisionContext.DecisionType         = historyEvent.EventType;
                decisionContext.ChildWorkflowName    = historyEvent.ChildWorkflowExecutionTimedOutEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion =
                    historyEvent.ChildWorkflowExecutionTimedOutEventAttributes.WorkflowType.Version;
                decisionContext.TimeoutType       = historyEvent.ChildWorkflowExecutionTimedOutEventAttributes.TimeoutType;
                decisionContext.Details           = "";
                decisionContext.WorkflowExecRunId =
                    historyEvent.ChildWorkflowExecutionTimedOutEventAttributes.WorkflowExecution.RunId;

                var evt = FindEventTypeById(historyEvent.ChildWorkflowExecutionTimedOutEventAttributes.InitiatedEventId);
                decisionContext.Control  = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Control;
                decisionContext.InputRef = evt.StartChildWorkflowExecutionInitiatedEventAttributes.Input;
            }
            else if (historyEvent.EventType == EventType.MarkerRecorded)
            {
                // We don't act on markers but save the marker information in the decision context so that
                // the workflow has all the information it needs to make the decision. NOTE: values of markers
                // with the same names are overwritten.
                var markerName = historyEvent.MarkerRecordedEventAttributes.MarkerName;
                decisionContext.Markers[markerName] = Utils.GetDataFromStore(historyEvent.MarkerRecordedEventAttributes.Details, _storageClient);
            }
            else if (historyEvent.EventType == EventType.StartChildWorkflowExecutionFailed)
            {
                decisionContext.DecisionType      = historyEvent.EventType;
                decisionContext.ChildWorkflowName =
                    historyEvent.StartChildWorkflowExecutionFailedEventAttributes.WorkflowType.Name;
                decisionContext.ChildWorkflowVersion =
                    historyEvent.StartChildWorkflowExecutionFailedEventAttributes.WorkflowType.Version;
                decisionContext.Cause   = historyEvent.StartChildWorkflowExecutionFailedEventAttributes.Cause;
                decisionContext.Control = historyEvent.StartChildWorkflowExecutionFailedEventAttributes.Control;
            }
            else if (historyEvent.EventType == EventType.TimerStarted)
            {
                var timer = historyEvent.TimerStartedEventAttributes;

                decisionContext.DecisionType          = historyEvent.EventType;
                decisionContext.TimerId               = timer.TimerId;
                decisionContext.Timers[timer.TimerId] = timer;
            }
            else if (historyEvent.EventType == EventType.TimerFired)
            {
                var firedTimer = historyEvent.TimerFiredEventAttributes;

                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.TimerId      = firedTimer.TimerId;

                if (decisionContext.Timers.ContainsKey(firedTimer.TimerId))
                {
                    decisionContext.FiredTimers[firedTimer.TimerId] = firedTimer;
                    //decisionContext.Control = decisionContext.Timers[firedTimer.TimerId].Control;
                    //decisionContext.Timers.Remove(firedTimer.TimerId);
                }
            }
            else if (historyEvent.EventType == EventType.TimerCanceled)
            {
                var canceledTimer = historyEvent.TimerCanceledEventAttributes;

                decisionContext.DecisionType = historyEvent.EventType;
                decisionContext.TimerId      = canceledTimer.TimerId;

                if (decisionContext.Timers.ContainsKey(canceledTimer.TimerId))
                {
                    decisionContext.CanceledTimers[canceledTimer.TimerId] = canceledTimer;
                    //decisionContext.Control = decisionContext.Timers[canceledTimer.TimerId].Control;
                    //decisionContext.Timers.Remove(canceledTimer.TimerId);
                }
            }
            else if (historyEvent.EventType == EventType.StartChildWorkflowExecutionInitiated)
            {
            }
        }