/// <summary>
        /// Every Conversation turn for our EchoBot will call this method. In here
        /// the bot checks the Activty type to verify it's a message, bumps the
        /// turn conversation 'Turn' count, and then echoes the users typing
        /// back to them.
        /// </summary>
        /// <param name="context">Turn scoped context containing all the data needed
        /// for processing this conversation turn. </param>
        public async Task OnTurn(ITurnContext context)
        {
            try {
                // This bot is only handling Messages
                if (context.Activity.Type == ActivityTypes.Message)
                {
                    // Get the conversation state from the turn context
                    var state = context.GetConversationState <OneMeetBotState>();

                    // Bump the turn count.
                    state.TurnCount++;

                    var messageText = context.Activity.Text;

                    // Remove bot name mention
                    messageText = GetMessageWithoutMention(context, messageText);
                    messageText = messageText.Replace("<at>", "");
                    messageText = messageText.Replace("</at>", "");
                    messageText = messageText.Trim();

                    int idx = 0;
                    while (!char.IsLetterOrDigit(messageText[idx]))
                    {
                        ++idx;
                    }
                    messageText = messageText.Substring(idx);

                    // Check user intention
                    var lowerCaseMessage = messageText.ToLower();

                    // Initialize bot in channel case
                    if (lowerCaseMessage.StartsWith("here"))
                    {
                        if (context.Activity.ChannelId == "msteams")
                        {
                            Configuration.TeamsConversationId = context.Activity.Conversation.Id;
                            Configuration.TeamsConversationId = Configuration.TeamsConversationId.Split(';')[0];
                        }
                        else if (context.Activity.ChannelId == "skype")
                        {
                            Configuration.SkypeConversationId = context.Activity.Conversation.Id;
                        }
                        await context.SendActivity("Success! You have registered the bot in this channel!");
                    }
                    // Join/leave the event button clicked case
                    else if (lowerCaseMessage.StartsWith("joinleave"))
                    {
                        try
                        {
                            var           cardData    = JsonConvert.DeserializeObject <EventCardData>(context.Activity.Value.ToString());
                            EventCardData newCardData = null;

                            var eventDateTime = DateTimeOffset.Parse(cardData.EventData.Time);
                            var userDateTime  = context.Activity.LocalTimestamp;

                            if (DateTimeOffset.Compare(eventDateTime, userDateTime.Value) < 0)
                            {
                                await SendPrivateMessage(context, $"You cannot join the evnet, because it has already ended. \U0001F613");

                                return;
                            }

                            try
                            {
                                newCardData = database.UpdateAtendees(cardData.ResourceResponseId, new Atendee(context.Activity.From.Name));
                            } catch (Exception)  {
                                await SendPrivateMessage(context, "An error occured when updating Attendees. \U0001F613");
                            }

                            if (newCardData != null)
                            {
                                await context.UpdateActivity(CreateActivityForEvent(context, newCardData));
                            }
                            else
                            {
                                await SendPrivateMessage(context, "An error occured when updating Attendees. \U0001F613");
                            }
                        } catch (Exception) {
                            await SendPrivateMessage(context, "An error occured when reading event data. \U0001F613");
                        }
                    }
                    // Cancel the event button clicked case
                    else if (lowerCaseMessage.StartsWith("cancelevent"))
                    {
                        try
                        {
                            var cardData = JsonConvert.DeserializeObject <EventCardData>(context.Activity.Value.ToString());

                            // Check if user is eligible to cancel the event
                            if (context.Activity.From.Name == cardData.CreatorName)
                            {
                                await context.UpdateActivity(CancelEvent(context, cardData));
                            }
                            else
                            {
                                await SendPrivateMessage(context, "You cannot cancel the event, because you are not its creator.");
                            }
                        }
                        catch (Exception)
                        {
                            await SendPrivateMessage(context, "An error occured when reading event data. \U0001F613");
                        }
                    }
                    // GroupMeet direct command call case
                    else if (lowerCaseMessage.StartsWith("groupmeet"))
                    {
                        try
                        {
                            var newEvent = await ParseNewEvent(context, messageText, luisConnector);

                            if (newEvent == null)
                            {
                                await SendPrivateMessage(context, "Sorry, I did not understand correctly. \U0001F613");
                            }
                            else
                            {
                                await SendEventToTeams(context, newEvent);
                            }
                        } catch (Exception) {
                            await SendPrivateMessage(context, "Sorry, error occured during parsing command. \U0001F613");
                        }
                    }
                    // PairMeet command call case
                    else if (lowerCaseMessage.StartsWith("pairmeet"))
                    {
                        try {
                            var serviceUri = new Uri(context.Activity.ServiceUrl, UriKind.Absolute);
                            using (var client = new ConnectorClient(serviceUri, credentials))
                            {
                                var membersResponse = await client.Conversations.GetConversationMembersWithHttpMessagesAsync(context.Activity.Conversation.Id);

                                var members = membersResponse.Body.ToList();
                                var pairs   = new Dictionary <ChannelAccount, ChannelAccount>();

                                Random rnd = new Random();
                                while (members.Count > 1)
                                {
                                    int otherIndex = rnd.Next(1, members.Count);
                                    pairs.Add(members[0], members[otherIndex]);
                                    members.RemoveAt(otherIndex);
                                    members.RemoveAt(0);
                                }
                                if (members.Count == 1)
                                {
                                    pairs.Add(members[0], members[0]);
                                    members.Clear();
                                }

                                Microsoft.Bot.Connector.Authentication.MicrosoftAppCredentials.TrustServiceUrl(context.Activity.ServiceUrl, System.DateTime.MaxValue);
                                var teamsClient      = client.GetTeamsConnectorClient();
                                var teamsChannelData = context.Activity.GetChannelData <Microsoft.Bot.Connector.Teams.Models.TeamsChannelData>();

                                foreach (var pair in pairs)
                                {
                                    var conversationResponse = await client.Conversations.CreateOrGetDirectConversation(
                                        context.Activity.Recipient,
                                        pair.Key,
                                        teamsChannelData.Tenant.Id);

                                    await client.Conversations.SendToConversationWithHttpMessagesAsync(conversationResponse.Id, GetPairMeetActivity(pair.Key, pair.Value));

                                    if (pair.Key != pair.Value)
                                    {
                                        conversationResponse = await client.Conversations.CreateOrGetDirectConversation(
                                            context.Activity.Recipient,
                                            pair.Value,
                                            teamsChannelData.Tenant.Id);

                                        await client.Conversations.SendToConversationWithHttpMessagesAsync(conversationResponse.Id, GetPairMeetActivity(pair.Value, pair.Key));
                                    }
                                }

                                await context.SendActivity("I have notified the users in private messages!");
                            }
                        } catch (ErrorResponseException ex) {
                            await context.SendActivity(ex.Response.Content.ToString());
                        } catch (Exception ex) {
                            await context.SendActivity(ex.ToString());
                        }
                    }
                    else if (lowerCaseMessage.StartsWith("time"))
                    {
                        await context.SendActivity("Your time is: " + context.Activity.LocalTimestamp.ToString());
                    }
                    // Default case
                    else
                    {
                        // Try to analyse user message with Natural Language Processing
                        LUIS.Response response = await luisConnector.MakeRequest(messageText);

                        // Check if with high probability user want to cancel the request
                        if (response.topScoringIntent.intent == LUIS.Connector.CANCEL && response.topScoringIntent.score > 0.40)
                        {
                            state.luisConversationState = LUIS.ConversationState.ANALYZE_REQUEST;
                            await context.SendActivity(GetCancelMessage());

                            return;
                        }

                        string message;

                        // Check the conversation state
                        switch (state.luisConversationState)
                        {
                        case LUIS.ConversationState.ANALYZE_REQUEST:
                            if (response.topScoringIntent.intent == LUIS.Connector.CREATE_GROUP_MEET ||
                                response.intents.Find(i => i.intent == LUIS.Connector.CREATE_GROUP_MEET).score > response.intents.Find(i => i.intent == LUIS.Connector.HELP).score)
                            {
                                string first_reply = luisConnector.GetFirstAnswer(context, response, out state.detectedInformation);
                                state.luisConversationState = LUIS.ConversationState.ASK_NEXT;
                                await SendPrivateMessage(context, $"{first_reply}");
                            }
                            else if (response.topScoringIntent.intent == LUIS.Connector.HELP || response.topScoringIntent.intent == LUIS.Connector.GREET)
                            {
                                await SendPrivateMessage(context, GetHelpMessage(context));
                            }
                            else
                            {
                                await SendPrivateMessage(context, $"I did not understand... \U0001F613 If you want to create group meet, please send me a message with activity, place and time.");
                            }
                            break;

                        case LUIS.ConversationState.ASK_ACTIVITY:
                            message = luisConnector.GetActivity(response, ref state.detectedInformation, ref state.luisConversationState);
                            await context.SendActivity($"{message}");

                            break;

                        case LUIS.ConversationState.GET_ACTIVITY_AS_MESSAGE:
                            state.detectedInformation.Activity = messageText;
                            state.luisConversationState        = LUIS.ConversationState.ASK_NEXT;
                            await context.SendActivity($"I set activity to {messageText}.");

                            break;

                        case LUIS.ConversationState.ASK_PLACE:
                            message = luisConnector.GetPlace(response, ref state.detectedInformation, ref state.luisConversationState);
                            await context.SendActivity($"{message}");

                            break;

                        case LUIS.ConversationState.GET_PLACE_AS_MESSAGE:
                            state.detectedInformation.EventPlace = messageText;
                            state.luisConversationState          = LUIS.ConversationState.ASK_NEXT;
                            await context.SendActivity($"I set place to {messageText}.");

                            break;

                        case LUIS.ConversationState.ASK_TIME:
                            message = luisConnector.GetTime(context, response, ref state.detectedInformation, ref state.luisConversationState);
                            await context.SendActivity($"{message}");

                            break;

                        case LUIS.ConversationState.GET_TIME_AS_MESSAGE:
                            state.detectedInformation.Time = messageText;
                            state.luisConversationState    = LUIS.ConversationState.ASK_NEXT;
                            await context.SendActivity($"I set time to {messageText}.");

                            break;

                        case LUIS.ConversationState.ASK_PEOPLE:
                            message = luisConnector.GetPeople(response, ref state.detectedInformation, ref state.luisConversationState);
                            await context.SendActivity($"{message}");

                            break;

                        case LUIS.ConversationState.ASK_MEETING_PLACE:
                            message = luisConnector.GetMeetingPlace(response, ref state.detectedInformation, ref state.luisConversationState);
                            await context.SendActivity($"{message}");

                            break;

                        case LUIS.ConversationState.GET_MEETING_PLACE_AS_MESSAGE:
                            state.detectedInformation.MeetingPlace = messageText;
                            state.luisConversationState            = LUIS.ConversationState.CONFIRM_REQUEST;
                            await context.SendActivity($"I set place to {messageText}.");

                            break;

                        case LUIS.ConversationState.CONFIRM_REQUEST:
                            if (response.intents.Find(i => i.intent == LUIS.Connector.CONFIRM).score > response.intents.Find(i => i.intent == LUIS.Connector.CANCEL).score)
                            {
                                state.luisConversationState = LUIS.ConversationState.ANALYZE_REQUEST;
                                await SendEventToTeams(context, state.detectedInformation);
                            }
                            else
                            {
                                state.luisConversationState = LUIS.ConversationState.ANALYZE_REQUEST;
                                await context.SendActivity(GetCancelMessage());
                            }
                            break;

                        default:
                            // Check cancel again
                            state.luisConversationState = LUIS.ConversationState.ANALYZE_REQUEST;
                            if (response.topScoringIntent.intent == LUIS.Connector.CANCEL)
                            {
                                await SendPrivateMessage(context, GetCancelMessage());
                            }
                            else
                            {
                                await SendPrivateMessage(context, $"Sorry, I did not understand... Please try to create the event again");
                            }

                            break;
                        }
                        if (state.luisConversationState == LUIS.ConversationState.ASK_NEXT)
                        {
                            var checkStateResp = luisConnector.CheckState(state.detectedInformation);
                            state.luisConversationState = checkStateResp.Item1;
                            await context.SendActivity($"{checkStateResp.Item2}");
                        }
                        if (state.luisConversationState == LUIS.ConversationState.CONFIRM_REQUEST)
                        {
                            await context.SendActivity(GetFinalInformation(state.detectedInformation));
                        }
                    }
                }
                else if (context.Activity.Type == ActivityTypes.ConversationUpdate)
                {
                }
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
        }