public TaskAnswer RunState(TaskAnswer answer, UserProfile profile, string query, string queryType)
        {
            answer = PreStateAction(answer, profile, query);

            TrainBookingState taskState = answer.TaskState as TrainBookingState;
            if (taskState == null)
            {
                return answer;
            }
            TaskStateCode state = answer.CurrentState;

            bool isUpdated = false;
            answer.IterationCount++;

            switch (state)
            {
                case TaskStateCode.InitState:
                    answer.CurrentState = TaskStateCode.InitState;
                    answer.NextState = TaskStateCode.SourceStationState;
                    break;
                case TaskStateCode.SourceStationState:
                case TaskStateCode.DestinationStationState:
                    isUpdated = classifier.TryUpdateTaskState(answer, profile, query);
                    break;
                case TaskStateCode.DateOfJourneyState:
                    taskState.DateOfJourney = DateTime.ParseExact(query, "dd-MM-yyyy", null);
                    break;
                case TaskStateCode.TrainSelectionState:
                case TaskStateCode.PreferredCoachState:
                case TaskStateCode.NumberOfPassangersState:
                case TaskStateCode.PassengerNameState:
                case TaskStateCode.PassengerAgeState:
                case TaskStateCode.PassengerGenderState:
                case TaskStateCode.PassengerSeatPreferenceState:
                case TaskStateCode.PassengerDetailsState:
                case TaskStateCode.PhoneNumberState:
                case TaskStateCode.BookTicketState:
                    isUpdated = classifier.TryUpdateTaskState(answer, profile, query);
                    break;
                default:
                    break;
            }

            if (isUpdated)
            {
                answer.IterationCount = 0;
            }
            if (answer.IterationCount > 3)
            {
                DummyUpdateAnswer(answer, profile, query);
            }

            return PostStateAction(answer, profile, query);
        }
        static void CreateSampleAnswer()
        {
            ChatItem item1 = new ChatItem();
            item1.Id = "Cortana";
            item1.ChatText = "Hi this is Cortana";

            ChatItem item2 = new ChatItem();
            item2.Id = "User";
            item2.ChatText = "Hi this is User";

            ChatItem item3 = new ChatItem();
            item3.Id = "Cortana";
            item3.ChatText = "Hi shall we complete the Task?";

            ChatWindow chatWindow = new ChatWindow();
            chatWindow.ChatList.Add(item1);
            chatWindow.ChatList.Add(item2);
            chatWindow.ChatList.Add(item3);

            TrainBookingState bookingState = new TrainBookingState();

            bookingState.Source = new Station();
            bookingState.Source.Name = "Hyderabad";
            bookingState.Source.Code = "SC";

            bookingState.Destination = new Station();
            bookingState.Destination.Name = "Chennai Central";
            bookingState.Destination.Code = "MAS";

            bookingState.DateOfJourney = DateTime.Now.AddDays(10);

            bookingState.TrainInfo = new TrainInfo();
            bookingState.TrainInfo.Name = "Chennai Express";
            bookingState.TrainInfo.Number = "12604";

            bookingState.CoachPreference = CoachType.SecondAC;
            bookingState.PhoneNumber = "1234567890";

            bookingState.NumberOfPassangers = 4;

            PassangerInfo pas1 = new PassangerInfo();
            pas1.Name = "BillGates";
            pas1.Age = 50;
            pas1.Gender = Gender.Male;
            pas1.BerthChoice = BerthChoice.SideLower;

            PassangerInfo pas2 = new PassangerInfo();
            pas2.Name = "Balmer";
            pas2.Age = 49;
            pas2.Gender = Gender.Male;
            pas2.BerthChoice = BerthChoice.SideUpper;

            PassangerInfo pas3 = new PassangerInfo();
            pas3.Name = "BillGates";
            pas3.Age = 45;
            pas3.Gender = Gender.Male;
            pas3.BerthChoice = BerthChoice.Lower;

            bookingState.PassangerInfoList = new List<PassangerInfo>();
            bookingState.PassangerInfoList.Add(pas1);
            bookingState.PassangerInfoList.Add(pas2);
            bookingState.PassangerInfoList.Add(pas3);


            TaskAnswer answer = new TaskAnswer();
            answer.Title = "Book Train Ticket Task";
            answer.TaskType = TaskType.Train;
            answer.ChatWindow = chatWindow;
            answer.TaskState = bookingState;


            string jsonString = JsonConvert.SerializeObject(answer);

            return;



        }
        public string RunAnswer(string userId, string sessionId, string query, string queryType)
        {
            //  Get the Answer State from Storage
            bool isNewSession = false;
            TaskAnswer answer;
            if (string.IsNullOrEmpty(sessionId))
            {
                sessionId = Guid.NewGuid().ToString();
                answer = new TaskAnswer();
                answer.Title = "Train Ticket Booking";
                answer.UserId = userId;
                answer.SessionId = sessionId;
            }
            else
            {
                string content = blobStorage.DownloadFileAsText(GetBlobKey(userId, sessionId));
                if (string.IsNullOrEmpty(content))
                {
                    return null;
                }
                answer = JsonConvert.DeserializeObject<TaskAnswer>(content);
            }

            // Get the Profile State from Storage
            string profileString = blobStorage.DownloadFileAsText(userId);
            UserProfile userProfile = null;
            if (string.IsNullOrEmpty(profileString))
            {
                userProfile = new UserProfile();
                userProfile.UserId = userId;
                userProfile.MyProfile = new Person();
                userProfile.MyProfile.Name = userId;
            }
            
            // TODO: Classify the Query
            //answer = DummyUpdateAnswer(query, queryType, answer);
            // TODO: Run the state machine on Classifier Output
            
            // Update Profile
            answer = RunState(answer, userProfile, query, queryType);
           
                        
            // Store the Profile
            string userProfileString = JsonConvert.SerializeObject(userProfile);
            blobStorage.UploadFile(userId, userProfileString);

            // Store the State
            string stateString = JsonConvert.SerializeObject(answer);
            blobStorage.UploadFile(GetBlobKey(userId, sessionId), stateString);

            return stateString;
        }
        private TaskAnswer DummyUpdateAnswer(TaskAnswer answer, UserProfile profile, string query)
        {
            var state = answer.TaskState as TrainBookingState;

            switch (answer.CurrentState)
            {
                case TaskStateCode.InitState:
                    answer.CurrentState = TaskStateCode.InitState;
                    break;
                case TaskStateCode.SourceStationState:
                    state.Source = new Station();
                    state.Source.Name = "Hyderabad";
                    state.Source.Code = "SC";
                    break;
                case TaskStateCode.DestinationStationState:
                    state.Destination = new Station();
                    state.Destination.Name = "Hyderabad";
                    state.Destination.Code = "SC";
                    break;
                case TaskStateCode.DateOfJourneyState:
                    state.DateOfJourney = DateTime.Now.AddDays(5);
                    break;
                case TaskStateCode.TrainSelectionState:
                    state.TrainInfo = new TrainInfo();
                    state.TrainInfo.Name = "Naryanadri";
                    state.TrainInfo.Number = "123456";
                    break;
                case TaskStateCode.PreferredCoachState:
                    state.CoachPreference = CoachType.FirstAC;
                    break;
                case TaskStateCode.NumberOfPassangersState:
                    state.NumberOfPassangers = 1;
                    break;
                case TaskStateCode.PassengerNameState:
                    break;
                case TaskStateCode.PassengerAgeState:
                    break;
                case TaskStateCode.PassengerGenderState:
                    break;
                case TaskStateCode.PassengerSeatPreferenceState:
                    break;
                case TaskStateCode.PassengerDetailsState:
                    break;
                case TaskStateCode.PhoneNumberState:
                    break;
                case TaskStateCode.BookTicketState:
                    break;
                default:
                    break;
            }

            return answer;
        }
        private ChatItem GetChatItem(TaskAnswer answer, TaskStateCode stateCode)
        {
            TrainBookingState taskState = answer.TaskState as TrainBookingState;
            if (taskState == null)
            {
                return null;
            }

            string question;
            if (!_chatItemMap.TryGetValue(stateCode, out question))
            {
                question = "Some Error. it shouldn't";
            }

            ChatItem item = new ChatItem();
            item.Id = "Cortana";
            item.ChatText = question;
            return item;
        }
        private TaskStateCode GetNextState(TaskAnswer answer)
        {
            if (answer.TaskType.Equals(TaskType.Train))
            {
                var trainBookingState = answer.TaskState as TrainBookingState;

                if (trainBookingState.Source == null)
                {
                    return TaskStateCode.SourceStationState;
                }

                if (trainBookingState.Destination == null)
                {
                    return TaskStateCode.DestinationStationState;
                }

                if (trainBookingState.DateOfJourney == null)
                {
                    return TaskStateCode.DateOfJourneyState;
                }

                if (trainBookingState.TrainInfo == null)
                {
                    return TaskStateCode.TrainSelectionState;
                }

                if (trainBookingState.CoachPreference.Equals(CoachType.None))
                {
                    return TaskStateCode.PreferredCoachState;
                }

                if (trainBookingState.NumberOfPassangers == 0)
                {
                    return TaskStateCode.NumberOfPassangersState;
                }

                uint iPassenger = answer.CurrentPassengerId;
                var passenger = trainBookingState.PassangerInfoList.FirstOrDefault(x => x.Id == iPassenger);

                if (passenger == null)
                {
                    return TaskStateCode.PassengerNameState;
                }

                TaskStateCode nextState;
                if (TryGetNextPassengerState(passenger, out nextState))
                {
                    return nextState;
                }
                passenger.IsComplete = true;
                // FIXME: small hack, some how, how can avoid this.
                if (answer.CompletedPassengers < trainBookingState.NumberOfPassangers)
                {
                    answer.CompletedPassengers += 1;
                }

                if (answer.CompletedPassengers < trainBookingState.NumberOfPassangers)
                {
                    answer.CurrentPassengerId++;
                    return TaskStateCode.PassengerNameState;
                }

                if (answer.IsStateFinished)
                {
                    switch (answer.TicketBookedState)
                    {
                        case BookedState.None:
                            return TaskStateCode.BookTicketState;
                            break;
                        case BookedState.Cancelled:
                            return TaskStateCode.SaveState;
                            break;
                        case BookedState.Confirmed:
                            return TaskStateCode.EndState;
                            break;
                    }
                }

                if (answer.CompletedPassengers == trainBookingState.NumberOfPassangers)
                {
                    if (string.IsNullOrEmpty(trainBookingState.PhoneNumber))
                    {
                        return TaskStateCode.PhoneNumberState;
                    }

                    answer.IsStateFinished = true;
                    return TaskStateCode.BookTicketState;
                }
                
                if (answer.CurrentState == TaskStateCode.SaveState)
                {
                    return TaskStateCode.BookTicketState;
                }
                
                return TaskStateCode.ExceptionState;
            }
            return TaskStateCode.ExceptionState;
        }
        private TaskAnswer PostStateAction(TaskAnswer answer, UserProfile profile, string query)
        {
            TrainBookingState taskState = answer.TaskState as TrainBookingState;
            if (taskState == null)
            {
                return null;
            }

            TaskStateCode nextState = GetNextState(answer);
            answer.CurrentState = nextState;

            string question;
            if (!_chatItemMap.TryGetValue(nextState, out question))
            {
                question = "Some Error. it shouldn't";
                return null;
            }
            ChatItem chatItem = new ChatItem();
            PassangerInfo passenger = taskState.PassangerInfoList.FirstOrDefault(x => x.Id == answer.CurrentPassengerId);
            if (passenger == null)
            {
                // Fixme; avoid dummy passenger
                PassangerInfo passanger = new PassangerInfo();
            }
            
            switch (nextState)
            {
                case TaskStateCode.InitState:
                    break;
                case TaskStateCode.SourceStationState:
                    break;
                case TaskStateCode.DestinationStationState:
                    break;
                case TaskStateCode.DateOfJourneyState:
                    break;
                case TaskStateCode.TrainSelectionState:
                    question = string.Format(question, taskState.Source.Code, taskState.Destination.Code);
                    FillTrainList(chatItem, taskState.Source.Code, taskState.Destination.Code);
                    break;
                case TaskStateCode.PreferredCoachState:
                    FillPreferredCoachList(chatItem);
                    break;
                case TaskStateCode.NumberOfPassangersState:
                    break;
                case TaskStateCode.PassengerNameState:
                    question = string.Format(question, answer.CurrentPassengerId);
                    break;
                case TaskStateCode.PassengerGenderState:
                    question = string.Format(question, passenger.Name);
                    break;
                case TaskStateCode.PassengerAgeState:
                    question = string.Format(question, (passenger.Gender.Equals(Gender.Male)) ? "his" : "her");
                    break;
                case TaskStateCode.PassengerSeatPreferenceState:
                    FillePreferredBerthList(chatItem);
                    break;
                case TaskStateCode.PassengerDetailsState:
                    break;
                case TaskStateCode.PhoneNumberState:
                    break;
                case TaskStateCode.BookTicketState:
                    break;
                case TaskStateCode.EndState:
                    profileHelper.UpdateUserProfile(taskState, profile);
                    break;
                default:
                    break;
            }

            chatItem.Id = "Cortana";
            chatItem.ChatText = question;
            answer.ChatWindow.ChatList.Add(chatItem);
            return answer;
        }
        private TaskAnswer PreStateAction(TaskAnswer answer, UserProfile profile, string query)
        {
            // Add the User Query to Chat List Window
            var userChatItem = GetUserChatItem(answer.UserId, query);
            answer.ChatWindow.ChatList.Add(userChatItem);

            return answer;
        }
        public bool TryUpdateTaskState(TaskAnswer answer, UserProfile userProfile, string query)
        {
            TrainBookingState taskState = answer.TaskState as TrainBookingState;
            if (taskState == null)
            {
                return false;
            }

            TaskStateCode currentState = answer.CurrentState;
            bool updated = false;
            switch (currentState)
            {
                case TaskStateCode.SourceStationState:
                    Station sourceStation;
                    if (TryGetStation(query, out sourceStation))
                    {
                        taskState.Source = sourceStation;
                        updated = true;
                    }
                    break;

                case TaskStateCode.DestinationStationState:
                    Station destinationStation;
                    if (TryGetStation(query, out destinationStation))
                    {
                        taskState.Destination = destinationStation;
                        updated = true;
                    }
                    break;

                case TaskStateCode.DateOfJourneyState:
                    DateTime date;
                    if (DateTime.TryParse(query, out date))
                    {
                        taskState.DateOfJourney = date;
                        updated = true;
                    }
                    break;

                case TaskStateCode.TrainSelectionState:
                    TrainInfo trainInfo;
                    if (TryGetTrain(query, out trainInfo))
                    {
                        taskState.TrainInfo = trainInfo;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PreferredCoachState:
                    CoachType coachType;
                    if (TryGetCoach(query, out coachType))
                    {
                        taskState.CoachPreference = coachType;
                        updated = true;
                    }
                    break;

                case TaskStateCode.NumberOfPassangersState:
                    uint number;
                    if (TryGetNumberOfPassengers(query, out number))
                    {
                        taskState.NumberOfPassangers = number;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PassengerNameState:
                    string name;
                    if (TryGetPassengerName(query, out name))
                    {
                        uint iPassenger = answer.CurrentPassengerId;
                        var passengerList = taskState.PassangerInfoList;
                        var passenger = passengerList.FirstOrDefault(x => x.Id == iPassenger);
                        if (passenger == null)
                        {
                            passenger = new PassangerInfo();
                            passengerList.Add(passenger);
                            passenger.Id = (uint)passengerList.Count;
                            answer.CurrentPassengerId = passenger.Id;
                        }
                        passenger.Name = name;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PassengerAgeState:
                    uint age;
                    if (TryGetPassengerAge(query, out age))
                    {
                        uint iPassenger = answer.CurrentPassengerId;
                        var passengerList = taskState.PassangerInfoList;
                        var passenger = passengerList.FirstOrDefault(x => x.Id == iPassenger);
                        if (passenger == null)
                        {
                            passenger = new PassangerInfo();
                            passengerList.Add(passenger);
                            passenger.Id = (uint)passengerList.Count;
                            answer.CurrentPassengerId = passenger.Id;
                        }
                        passenger.Age = age;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PassengerGenderState:
                    Gender gender;
                    if (TryGetPassengerGender(query, out gender))
                    {
                        uint iPassenger = answer.CurrentPassengerId;
                        var passengerList = taskState.PassangerInfoList;
                        var passenger = passengerList.FirstOrDefault(x => x.Id == iPassenger);
                        if (passenger == null)
                        {
                            passenger = new PassangerInfo();
                            passengerList.Add(passenger);
                            passenger.Id = (uint)passengerList.Count;
                            answer.CurrentPassengerId = passenger.Id;
                        }
                        passenger.Gender = gender;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PassengerSeatPreferenceState:
                    BerthChoice berthChoice;
                    if (TryGetPassengerSeatPreference(query, out berthChoice))
                    {
                        uint iPassenger = answer.CurrentPassengerId;
                        var passengerList = taskState.PassangerInfoList;
                        var passenger = passengerList.FirstOrDefault(x => x.Id == iPassenger);
                        if (passenger == null)
                        {
                            passenger = new PassangerInfo();
                            passengerList.Add(passenger);
                            passenger.Id = (uint)passengerList.Count;
                            answer.CurrentPassengerId = passenger.Id;
                        }
                        passenger.BerthChoice = berthChoice;
                        updated = true;
                    }
                    break;

                case TaskStateCode.PhoneNumberState:
                    string phoneNumber;
                    if (TryGetPhoneNumber(query, out phoneNumber))
                    {
                        taskState.PhoneNumber = phoneNumber;
                        updated = true;
                    }
                    break;

                case TaskStateCode.BookTicketState:
                    BookedState ticketBookedState;
                    if (TryGetConfirmation(query, out ticketBookedState))
                    {
                        answer.TicketBookedState = ticketBookedState;
                        updated = true;
                    }
                    break;
            }

            return updated;

        }