/// <summary>
        /// Return results of the call to QnA Maker.
        /// </summary>
        /// <param name="dialogContext">Context object containing information for a single turn of conversation with a user.</param>
        /// <param name="activity">The incoming activity received from the user. The Text property value is used as the query text for QnA Maker.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <param name="telemetryProperties">Additional properties to be logged to telemetry with the LuisResult event.</param>
        /// <param name="telemetryMetrics">Additional metrics to be logged to telemetry with the LuisResult event.</param>
        /// <returns>A <see cref="RecognizerResult"/> containing the QnA Maker result.</returns>
        public override async Task <RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken, Dictionary <string, string> telemetryProperties = null, Dictionary <string, double> telemetryMetrics = null)
        {
            // Identify matched intents
            var recognizerResult = new RecognizerResult
            {
                Text    = activity.Text,
                Intents = new Dictionary <string, IntentScore>(),
            };

            if (string.IsNullOrEmpty(activity.Text))
            {
                recognizerResult.Intents.Add("None", new IntentScore());
                return(recognizerResult);
            }

            var filters = new List <Metadata>();

            if (IncludeDialogNameInMetadata.GetValue(dialogContext.State))
            {
                filters.Add(new Metadata
                {
                    Name  = "dialogName",
                    Value = dialogContext.ActiveDialog.Id
                });
            }

            // if there is $qna.metadata set add to filters
            var externalMetadata = Metadata?.GetValue(dialogContext.State);

            if (externalMetadata != null)
            {
                filters.AddRange(externalMetadata);
            }

            // Calling QnAMaker to get response.
            var qnaClient = await GetQnAMakerClientAsync(dialogContext).ConfigureAwait(false);

            var answers = await qnaClient.GetAnswersAsync(
                dialogContext.Context,
                new QnAMakerOptions
            {
                Context        = Context?.GetValue(dialogContext.State),
                ScoreThreshold = Threshold.GetValue(dialogContext.State),
                StrictFilters  = filters.ToArray(),
                Top            = Top.GetValue(dialogContext.State),
                QnAId          = QnAId.GetValue(dialogContext.State),
                RankerType     = RankerType.GetValue(dialogContext.State),
                IsTest         = IsTest
            },
                null).ConfigureAwait(false);

            if (answers.Any())
            {
                QueryResult topAnswer = null;
                foreach (var answer in answers)
                {
                    if (topAnswer == null || answer.Score > topAnswer.Score)
                    {
                        topAnswer = answer;
                    }
                }

                if (topAnswer.Answer.Trim().ToUpperInvariant().StartsWith(IntentPrefix.ToUpperInvariant(), StringComparison.Ordinal))
                {
                    recognizerResult.Intents.Add(topAnswer.Answer.Trim().Substring(IntentPrefix.Length).Trim(), new IntentScore {
                        Score = topAnswer.Score
                    });
                }
                else
                {
                    recognizerResult.Intents.Add(QnAMatchIntent, new IntentScore {
                        Score = topAnswer.Score
                    });
                }

                var answerArray = new JArray();
                answerArray.Add(topAnswer.Answer);
                ObjectPath.SetPathValue(recognizerResult, "entities.answer", answerArray);

                var instance = new JArray();
                instance.Add(JObject.FromObject(topAnswer));
                ObjectPath.SetPathValue(recognizerResult, "entities.$instance.answer", instance);

                recognizerResult.Properties["answers"] = answers;
            }
            else
            {
                recognizerResult.Intents.Add("None", new IntentScore {
                    Score = 1.0f
                });
            }

            TrackRecognizerResult(dialogContext, "QnAMakerRecognizerResult", FillRecognizerResultTelemetryProperties(recognizerResult, telemetryProperties), telemetryMetrics);

            return(recognizerResult);
        }
        public async override Task <RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary <System.String, System.String> telemetryProperties = null, Dictionary <System.String, System.Double> telemetryMetrics = null)
        {
            var qluceneEngine = await QLuceneEngineCache.GetEngine(dialogContext, this.KnowledgeBase).ConfigureAwait(false);

            var threshold        = Threshold.GetValue(dialogContext);
            var recognizerResult = new RecognizerResult
            {
                Text    = activity.Text,
                Intents = new Dictionary <string, IntentScore>(),
            };

            if (string.IsNullOrEmpty(activity.Text))
            {
                recognizerResult.Intents.Add("None", new IntentScore());
                return(recognizerResult);
            }
            var  rankerType = RankerType?.GetValue(dialogContext.State);
            var  strictFiltersCompoundOperationType = StrictFiltersCompoundOperationType?.GetValue(dialogContext.State);
            var  strictFilters = new List <Metadata>();
            var  context       = Context?.GetValue(dialogContext.State);
            bool includeDialogNameInMetadata = IncludeDialogNameInMetadata.GetValue(dialogContext.State);

            if (includeDialogNameInMetadata)
            {
                strictFilters.Add(new Metadata
                {
                    Name  = "dialogName",
                    Value = dialogContext.ActiveDialog.Id
                });
            }

            // if there is $qna.metadata set add to filters
            var externalMetadata = StrictFilters?.GetValue(dialogContext.State);

            if (externalMetadata != null)
            {
                strictFilters.AddRange(externalMetadata);
            }

            var topAnswer = qluceneEngine.GetAnswers(activity.Text,
                                                     strictFilters: strictFilters.ToArray(),
                                                     context: context,
                                                     threshold: threshold,
                                                     rankerType: rankerType,
                                                     strictFiltersCompoundOperationType: strictFiltersCompoundOperationType);

            if (topAnswer != null)
            {
                if (topAnswer.Answer.Trim().ToUpperInvariant().StartsWith(IntentPrefix.ToUpperInvariant(), StringComparison.Ordinal))
                {
                    recognizerResult.Intents.Add(topAnswer.Answer.Trim().Substring(IntentPrefix.Length).Trim(), new IntentScore {
                        Score = topAnswer.Score
                    });
                }
                else
                {
                    recognizerResult.Intents.Add(QnAMatchIntent, new IntentScore {
                        Score = topAnswer.Score
                    });
                }

                var answerArray = new JArray();
                answerArray.Add(topAnswer.Answer);
                ObjectPath.SetPathValue(recognizerResult, "entities.answer", answerArray);

                var instance = new JArray();
                var data     = JObject.FromObject(topAnswer);
                data["startIndex"] = 0;
                data["endIndex"]   = activity.Text.Length;
                instance.Add(data);
                ObjectPath.SetPathValue(recognizerResult, "entities.$instance.answer", instance);

                // recognizerResult.Properties["answers"] = answers;
            }
            else
            {
                recognizerResult.Intents.Add("None", new IntentScore {
                    Score = 1.0f
                });
            }

            var traceInfo = new
            {
                recognizerResult,
                options = new
                {
                    id             = this.Id,
                    knowledgeBase  = this.KnowledgeBase,
                    scoreThreshold = threshold,
                    context,
                    rankerType,
                    strictFilters = strictFilters.ToArray(),
                    includeDialogNameInMetadata,
                    strictFiltersCompoundOperationType
                }
            };

            await dialogContext.Context.TraceActivityAsync(nameof(QLuceneRecognizer), traceInfo, TraceType, TraceLabel, cancellationToken).ConfigureAwait(false);

            return(recognizerResult);
        }