// A sample mapping from ServiceNow response types to Bot Framework concepts, in many cases this will need to be adapted to a
        // Bot owners specific requirements and styling.
        private async Task HandleContentEvent(ServiceNowResponseMessage responseMessage)
        {
            foreach (var item in responseMessage.body)
            {
                IMessageActivity responseActivity;

                // Map ServiceNow UX controls to Bot Framework concepts. This will need refinement as broader experiences are used but this covers a broad range of out-of-box ServiceNow response types.
                switch (item.uiType)
                {
                case "TopicPickerControl":
                case "ItemPicker":
                case "Picker":

                    // Map the picker concept to a basic HeroCard with buttons
                    List <CardAction> cardActions = new List <CardAction>();
                    foreach (var option in item.options)
                    {
                        cardActions.Add(new CardAction("imBack", option.description ?? option.label, value: option.label));
                    }

                    var pickerHeroCard = new HeroCard(buttons: cardActions);
                    responseActivity = MessageFactory.Attachment(pickerHeroCard.ToAttachment());

                    responseActivity.AsMessageActivity().Text = item.promptMsg ?? item.label;
                    break;

                case "DefaultPicker":

                    // Map the picker concept to a basic HeroCard with buttons
                    List <CardAction> defaultPickerActions = new List <CardAction>();
                    foreach (var option in item.options)
                    {
                        defaultPickerActions.Add(new CardAction("imBack", option.description ?? option.label, value: option.label));
                    }

                    var defaultPickerCard = new HeroCard(buttons: defaultPickerActions);
                    responseActivity = MessageFactory.Attachment(defaultPickerCard.ToAttachment());
                    break;

                case "GroupedPartsOutputControl":
                    responseActivity = MessageFactory.Text(item.header);
                    responseActivity.AttachmentLayout = "carousel";
                    responseActivity.Attachments      = new List <Microsoft.Bot.Schema.Attachment>();
                    foreach (var action in item.values)
                    {
                        var cardAction = new CardAction("openUrl", action.label, value: action.action);
                        var card       = new HeroCard(action.label, null, action.description, null, null, cardAction);
                        responseActivity.Attachments.Add(card.ToAttachment());
                    }
                    break;

                case "OutputHtml":

                    // We can't render HTML inside of conversations.
                    responseActivity = MessageFactory.Text(StripTags(item.value));

                    break;

                case "Boolean":
                    List <CardAction> booleanCardActions = new List <CardAction>();

                    booleanCardActions.Add(new CardAction("imBack", title: "Yes", displayText: "Yes", value: "true"));
                    booleanCardActions.Add(new CardAction("imBack", title: "No", displayText: "Yes", value: "false"));
                    var booleanHeroCard = new HeroCard(buttons: booleanCardActions);

                    responseActivity = MessageFactory.Attachment(booleanHeroCard.ToAttachment());
                    responseActivity.AsMessageActivity().Text = item.promptMsg ?? item.label;
                    break;

                case "OutputText":
                    responseActivity = MessageFactory.Text(item.value ?? item.label);
                    break;

                case "OutputImage":

                    var cardImages = new List <CardImage>();
                    cardImages.Add(new CardImage(url: item.value));

                    var imageHeroCard = new HeroCard(images: cardImages);
                    responseActivity = MessageFactory.Attachment(imageHeroCard.ToAttachment());

                    break;

                case "OutputLink":

                    var linkHeroCard = new HeroCard(buttons: new List <CardAction> {
                        new CardAction("openUrl", item.value)
                    });
                    responseActivity = MessageFactory.Attachment(linkHeroCard.ToAttachment());
                    responseActivity.AsMessageActivity().Text = item.promptMsg ?? item.label;

                    break;

                default:
                    responseActivity = MessageFactory.Text(item.value ?? item.label);
                    break;
                }

                if (await ConversationHandoffRecordMap.GetByRemoteConversationId(responseMessage.clientSessionId) is ServiceNowHandoffRecord handoffRecord)
                {
                    if (!handoffRecord.ConversationRecord.IsClosed)
                    {
                        MicrosoftAppCredentials.TrustServiceUrl(handoffRecord.ConversationReference.ServiceUrl);

                        await(_adapter).ContinueConversationAsync(
                            _credentials.MsAppId,
                            handoffRecord.ConversationReference,
                            (turnContext, cancellationToken) => turnContext.SendActivityAsync(responseActivity, cancellationToken), default);

                        var traceActivity = Activity.CreateTraceActivity(
                            "ServiceNowVirtualAgent",
                            $"Response from ServiceNow Virtual Agent received (Id:{responseMessage.requestId})",
                            label: "ServiceNowHandoff->Response from ServiceNow Virtual Agent");

                        await(_adapter).ContinueConversationAsync(
                            _credentials.MsAppId,
                            handoffRecord.ConversationReference,
                            (turnContext, cancellationToken) => turnContext.SendActivityAsync(traceActivity, cancellationToken), default);
                    }
                }
                else
                {
                    // The bot has no record of this conversation, this should not happen
                    throw new Exception("Cannot find conversation");
                }
            }
        }
        // A sample mapping from ServiceNow response types to Bot Framework concepts, in many cases this will need to be adapted to a
        // Bot owners specific requirements and styling.
        private async Task HandleContentEvent(ServiceNowResponseMessage responseMessage)
        {
            int VAOptionsCount = 0;

            foreach (var item in responseMessage.body)
            {
                IMessageActivity responseActivity;

                // Map ServiceNow UX controls to Bot Framework concepts. This will need refinement as broader experiences are used but this covers a broad range of out-of-box ServiceNow response types.
                switch (item.uiType)
                {
                case "TopicPickerControl":
                case "ItemPicker":
                case "Picker":
                    if (item.options.All(o => !string.IsNullOrEmpty(o.attachment)))
                    {
                        // Map the picker concept to a HeroCard carousel
                        responseActivity = MessageFactory.Text(item.label);
                        responseActivity.AttachmentLayout = "carousel";
                        responseActivity.Attachments      = new List <Microsoft.Bot.Schema.Attachment>();
                        foreach (var option in item.options)
                        {
                            var card = new HeroCard(
                                subtitle: option.description,
                                images: new List <CardImage>()
                            {
                                new CardImage($"https://{_credentials.ServiceNowTenant}/{option.attachment}")
                            },
                                buttons: new List <CardAction>
                            {
                                new CardAction("imBack", option.label, value: option.label)
                            });
                            responseActivity.Attachments.Add(card.ToAttachment());
                        }
                    }
                    else
                    {
                        List <CardAction> cardActions = new List <CardAction>();
                        foreach (var option in item.options)
                        {
                            VAOptionsCount = VAOptionsCount + 1;
                            cardActions.Add(new CardAction("imBack", option.description ?? option.label, value: option.label));
                            if (VAOptionsCount <= item.options.Count())
                            {
                                if (VAOptionsCount == 50)
                                {
                                    break;
                                }
                            }
                        }

                        var pickerHeroCard = new HeroCard(text: item.promptMsg ?? item.label, buttons: cardActions);
                        responseActivity = MessageFactory.Attachment(pickerHeroCard.ToAttachment());
                    }

                    break;

                case "DefaultPicker":

                    // Map the picker concept to a basic HeroCard with buttons
                    List <CardAction> defaultPickerActions = new List <CardAction>();
                    foreach (var option in item.options)
                    {
                        VAOptionsCount = VAOptionsCount + 1;
                        defaultPickerActions.Add(new CardAction("imBack", option.description ?? option.label, value: option.label));
                        if (VAOptionsCount <= item.options.Count())
                        {
                            if (VAOptionsCount == 50)
                            {
                                break;
                            }
                        }
                    }

                    var defaultPickerCard = new HeroCard(buttons: defaultPickerActions);
                    responseActivity = MessageFactory.Attachment(defaultPickerCard.ToAttachment());
                    break;

                case "GroupedPartsOutputControl":
                    responseActivity = MessageFactory.Text(item.header);
                    responseActivity.AttachmentLayout = "carousel";
                    responseActivity.Attachments      = new List <Microsoft.Bot.Schema.Attachment>();
                    foreach (var action in item.values)
                    {
                        var card = new HeroCard(subtitle: action.description, buttons: new List <CardAction>
                        {
                            new CardAction("openUrl", action.label ?? action.action, value: action.action)
                        });
                        if (VAOptionsCount <= item.values.Count())
                        {
                            if (VAOptionsCount == 11)
                            {
                                break;
                            }
                            responseActivity.Attachments.Add(card.ToAttachment());
                        }
                    }
                    break;

                case "Boolean":
                    List <CardAction> booleanCardActions = new List <CardAction>();

                    booleanCardActions.Add(new CardAction("imBack", title: "Yes", displayText: "Yes", value: "true"));
                    booleanCardActions.Add(new CardAction("imBack", title: "No", displayText: "Yes", value: "false"));
                    var booleanHeroCard = new HeroCard(text: item.promptMsg ?? item.label, buttons: booleanCardActions);

                    responseActivity = MessageFactory.Attachment(booleanHeroCard.ToAttachment());

                    break;

                case "OutputText":
                    responseActivity = MessageFactory.Text(item.value?.ToString() ?? item.label);
                    break;

                case "OutputImage":

                    var cardImages = new List <CardImage>();
                    cardImages.Add(new CardImage(url: $"{_credentials.ServiceNowTenant}{item.value}"));
                    var imageHeroCard = new HeroCard(images: cardImages);
                    responseActivity = MessageFactory.Attachment(imageHeroCard.ToAttachment());

                    break;

                case "OutputLink":

                    var bodyValue = item.value as BodyValue;

                    var linkHeroCard = new HeroCard(text: item.header, buttons: new List <CardAction>
                    {
                        new CardAction("openUrl", item.label, value: bodyValue.action)
                    });
                    responseActivity = MessageFactory.Attachment(linkHeroCard.ToAttachment());

                    break;

                case "OutputCard":

                    var cardData = JObject.Parse(item.data.ToString());

                    var items = new List <AdaptiveColumnSet>();

                    var titleColumnSet = new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>()
                        {
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>()
                                {
                                    new AdaptiveTextBlock(cardData["title"]?.ToString())
                                    {
                                        Size   = AdaptiveTextSize.Medium,
                                        Weight = AdaptiveTextWeight.Bolder
                                    }
                                }
                            },
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>()
                                {
                                    new AdaptiveTextBlock(cardData["subtitle"]?.ToString())
                                    {
                                        Size = AdaptiveTextSize.Medium
                                    }
                                }
                            }
                        }
                    };

                    items.Add(titleColumnSet);

                    foreach (var field in cardData["fields"])
                    {
                        var columnSet = new AdaptiveColumnSet
                        {
                            Columns = new List <AdaptiveColumn>()
                            {
                                new AdaptiveColumn
                                {
                                    Items = new List <AdaptiveElement>()
                                    {
                                        new AdaptiveTextBlock(field["fieldLabel"]?.ToString())
                                        {
                                            Weight = AdaptiveTextWeight.Bolder
                                        }
                                    }
                                },
                                new AdaptiveColumn
                                {
                                    Items = new List <AdaptiveElement>()
                                    {
                                        new AdaptiveTextBlock(field["fieldValue"]?.ToString())
                                        {
                                            Wrap = true
                                        }
                                    }
                                }
                            }
                        };

                        items.Add(columnSet);
                    }

                    var adaptiveCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 2))
                    {
                        Body = new List <AdaptiveElement>()
                    };

                    adaptiveCard.Body.AddRange(items);

                    responseActivity = MessageFactory.Attachment(new Attachment
                    {
                        ContentType = AdaptiveCard.ContentType,
                        Content     = JObject.FromObject(adaptiveCard),
                    });

                    break;

                case "DateTime":
                    var dateTimeCard = new AdaptiveCard(new AdaptiveSchemaVersion(1, 2))
                    {
                        Body = new List <AdaptiveElement>()
                        {
                            new AdaptiveContainer()
                            {
                                Items = new List <AdaptiveElement>()
                                {
                                    new AdaptiveTextBlock()
                                    {
                                        Text = item.label,
                                        Wrap = true
                                    },
                                    new AdaptiveDateInput()
                                    {
                                        Id    = "dateVal",
                                        Value = DateTime.UtcNow.ToString("MM-dd-yyyy")
                                    },
                                    new AdaptiveTimeInput()
                                    {
                                        Id = "timeVal"
                                    }
                                }
                            }
                        },
                        Actions = new List <AdaptiveAction>()
                        {
                            // Using a SubmitAction with an msteams messageBack object to show display text
                            // from the user while sending the date and time inputs as data
                            new AdaptiveSubmitAction()
                            {
                                Title    = "Submit",
                                DataJson = "{\r\n\"msteams\": {\r\n\"type\": \"messageBack\",\r\n\"displayText\": \"Datetime submitted\"\r\n}\r\n}"
                            }
                        }
                    };

                    responseActivity = MessageFactory.Attachment(new Attachment
                    {
                        ContentType = AdaptiveCard.ContentType,
                        Content     = JObject.FromObject(dateTimeCard),
                    });

                    break;

                default:
                    responseActivity = MessageFactory.Text(item.value?.ToString() ?? item.label);
                    break;
                }

                if (await ConversationHandoffRecordMap.GetByRemoteConversationId(responseMessage.clientSessionId) is ServiceNowHandoffRecord handoffRecord)
                {
                    if (!handoffRecord.ConversationRecord.IsClosed)
                    {
                        MicrosoftAppCredentials.TrustServiceUrl(handoffRecord.ConversationReference.ServiceUrl);

                        await(_adapter).ContinueConversationAsync(
                            _credentials.MsAppId,
                            handoffRecord.ConversationReference,
                            (turnContext, cancellationToken) => turnContext.SendActivityAsync(responseActivity, cancellationToken), default);

                        var traceActivity = Activity.CreateTraceActivity(
                            "ServiceNowVirtualAgent",
                            $"Response from ServiceNow Virtual Agent received (Id:{responseMessage.requestId})",
                            label: "ServiceNowHandoff->Response from ServiceNow Virtual Agent");

                        await(_adapter).ContinueConversationAsync(
                            _credentials.MsAppId,
                            handoffRecord.ConversationReference,
                            (turnContext, cancellationToken) => turnContext.SendActivityAsync(traceActivity, cancellationToken), default);
                    }
                }
                else
                {
                    // The bot has no record of this conversation, this should not happen
                    throw new Exception("Cannot find conversation");
                }
            }
        }