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);
        }
        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;
        }
        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 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;

        }
        public void UpdateUserProfile(TrainBookingState taskState, UserProfile userProfile)
        {
            // Update the passangers
            var knownPeopleList = userProfile.KnownPeopleList;

            if (knownPeopleList == null)
            {
                knownPeopleList = new List<Person>();
            }

            foreach (var passenger in taskState.PassangerInfoList)
            {
                if (passenger.Name.Equals(userProfile.UserId))
                {
                    Person me = userProfile.MyProfile;
                    if (string.IsNullOrEmpty(me.ContactNumber))
                    {
                        me.ContactNumber = taskState.PhoneNumber;
                    }
                    me.Gender = passenger.Gender;
                    me.DoB = DateTime.Now.AddYears(-(int) passenger.Age);
                }
                else
                {
                    Person person =
                        knownPeopleList.FirstOrDefault(
                            x => x.Name.Equals(passenger.Name, StringComparison.OrdinalIgnoreCase));
                    if (person == null)
                    {
                        person = new Person();
                    }

                    // TODO: do we need every time?
                    person.Name = passenger.Name;
                    person.Gender = passenger.Gender;
                    person.DoB = DateTime.Now.AddYears(-(int) passenger.Age);
                    person.Relation = passenger.Relation;
                    person.BerthChoice = passenger.BerthChoice;
                }
            }

            var preferredTrips = userProfile.PreferredTrips;
            if (preferredTrips == null)
            {
                preferredTrips = new Dictionary<string, List<TravelDestination>>();
                userProfile.PreferredTrips = preferredTrips;
            }

            List<TravelDestination> destinationList;
            string src = taskState.Source.Code;
            string dest = taskState.Destination.Code;
            if (!preferredTrips.TryGetValue(src, out destinationList))
            {
                destinationList = new List<TravelDestination>();
                preferredTrips.Add(src, destinationList);
            }

            TravelDestination destination = destinationList.FirstOrDefault(x => x.Code.Equals(dest));
            if (destination == null)
            {
                destination = new TravelDestination();
                destination.PreferredTrainList = new List<TrainInfo>();
                destination.Code = dest;
                destinationList.Add(destination);
            }

            TrainInfo trainInfo =
                destination.PreferredTrainList.FirstOrDefault(x => x.Number == taskState.TrainInfo.Number);

            if (trainInfo == null)
            {
                trainInfo = new TrainInfo();
                trainInfo.Number = taskState.TrainInfo.Number;
                trainInfo.Name = taskState.TrainInfo.Name;
                destination.PreferredTrainList.Add(trainInfo);
            }
        }