private static object UnhandledMboxResponse(
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            MboxRequest mboxRequest,
            TraceHandler traceHandler)
        {
            if (prefetchResponse != null)
            {
                var prefetchMboxResponse = new PrefetchMboxResponse(mboxRequest.Index, mboxRequest.Name)
                {
                    Trace = traceHandler?.CurrentTrace,
                };
                prefetchResponse.Mboxes ??= new List <PrefetchMboxResponse>();
                prefetchResponse.Mboxes.Add(prefetchMboxResponse);
                return(null);
            }

            var response = new MboxResponse(mboxRequest.Index, mboxRequest.Name)
            {
                Trace = traceHandler?.CurrentTrace,
            };

            executeResponse.Mboxes ??= new List <MboxResponse>();
            executeResponse.Mboxes.Add(response);
            return(null);
        }
        private static bool HandleResult(
            IDictionary <string, object> consequence,
            OnDeviceDecisioningRule rule,
            RequestDetailsUnion details,
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            IList <Notification> notifications,
            string globalMbox = "target-global-mbox")
        {
            if (consequence == null || consequence.Count == 0)
            {
                return(false);
            }

            consequence.TryGetValue(Name, out var nameObject);
            var consequenceName = (string)nameObject;

            consequence.TryGetValue(Options, out var optionsObject);
            var consequenceOptions = (List <Option>)optionsObject;

            consequence.TryGetValue(Metrics, out var metricsObject);
            var consequenceMetrics = GetMetrics(metricsObject);

            if (executeResponse != null)
            {
                var notification = CreateNotification(details, consequenceOptions, globalMbox);
                notifications.Add(notification);
            }

            return(details.Match(
                       _ => HandlePageLoad(prefetchResponse, executeResponse, consequenceOptions, consequenceMetrics),
                       mboxRequest => HandleMboxRequest(prefetchResponse, executeResponse, mboxRequest, consequenceOptions, consequenceMetrics),
                       _ => HandleViewRequest(prefetchResponse, consequenceName, consequenceOptions, consequenceMetrics)));
        }
        private static bool HandlePageLoad(
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            IList <Option> consequenceOptions,
            IList <Metric> consequenceMetrics,
            TraceHandler traceHandler)
        {
            PageLoadResponse pageLoad = null;

            if (prefetchResponse != null)
            {
                prefetchResponse.PageLoad ??= new PageLoadResponse();
                pageLoad = prefetchResponse.PageLoad;
            }
            else if (executeResponse != null)
            {
                executeResponse.PageLoad ??= new PageLoadResponse();
                pageLoad = executeResponse.PageLoad;
            }

            if (pageLoad == null)
            {
                return(false);
            }

            pageLoad.Trace = traceHandler?.CurrentTrace;

            if (consequenceOptions != null)
            {
                foreach (var option in consequenceOptions)
                {
                    if (executeResponse != null)
                    {
                        option.EventToken = null;
                    }

                    if (option.Type == null && option.Content == null && option.EventToken == null && option.ResponseTokens == null)
                    {
                        continue;
                    }

                    pageLoad.Options ??= new List <Option>();
                    pageLoad.Options.Add(option);
                }
            }

            if (consequenceMetrics == null)
            {
                return(true);
            }

            foreach (var metric in consequenceMetrics
                     .Where(metric => pageLoad.Metrics == null || !pageLoad.Metrics.Contains(metric)))
            {
                pageLoad.Metrics ??= new List <Metric>();
                pageLoad.Metrics.Add(metric);
            }

            return(true);
        }
 private static void UnhandledResponse(RequestDetailsUnion details, PrefetchResponse prefetchResponse, ExecuteResponse executeResponse)
 {
     _ = details.Match <object>(
         _ => UnhandledPageLoadResponse(prefetchResponse, executeResponse),
         mboxRequest => UnhandledMboxResponse(prefetchResponse, executeResponse, mboxRequest),
         _ => UnhandledViewResponse(prefetchResponse));
 }
        private static object UnhandledViewResponse(PrefetchResponse prefetchResponse)
        {
            var view = new View();

            prefetchResponse.Views ??= new List <View>();
            prefetchResponse.Views.Add(view);
            return(null);
        }
        private static object UnhandledViewResponse(PrefetchResponse prefetchResponse, TraceHandler traceHandler)
        {
            var view = new View {
                Trace = traceHandler?.CurrentTrace
            };

            prefetchResponse.Views ??= new List <View>();
            prefetchResponse.Views.Add(view);
            return(null);
        }
        private static object UnhandledPageLoadResponse(PrefetchResponse prefetchResponse, ExecuteResponse executeResponse)
        {
            var response = new PageLoadResponse();

            if (prefetchResponse != null)
            {
                prefetchResponse.PageLoad = response;
                return(null);
            }

            executeResponse.PageLoad = response;
            return(null);
        }
        private static bool HandleViewRequest(
            PrefetchResponse prefetchResponse,
            string consequenceName,
            List <Option> consequenceOptions,
            List <Metric> consequenceMetrics,
            TraceHandler traceHandler)
        {
            if (prefetchResponse == null)
            {
                return(false);
            }

            var responseView = new View(consequenceName, null, consequenceOptions, consequenceMetrics);

            responseView.Trace = traceHandler?.CurrentTrace;

            var views = prefetchResponse.Views;

            if (views == null)
            {
                views = new List <View>();
                prefetchResponse.Views = views;
            }

            var foundView = views.Find(view => view.Name == responseView.Name);

            if (foundView == null)
            {
                views.Add(responseView);
                return(true);
            }

            if (responseView.Options != null)
            {
                foundView.Options ??= new List <Option>();
                foundView.Options.AddRange(responseView.Options);
            }

            if (responseView.Metrics != null)
            {
                foundView.Metrics ??= new List <Metric>();
                foundView.Metrics.AddRange(responseView.Metrics);
            }

            return(true);
        }
        private static object UnhandledPageLoadResponse(
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            TraceHandler traceHandler)
        {
            var response = new PageLoadResponse {
                Trace = traceHandler?.CurrentTrace
            };

            if (prefetchResponse != null)
            {
                prefetchResponse.PageLoad = response;
                return(null);
            }

            executeResponse.PageLoad = response;
            return(null);
        }
        private static bool HandleMboxRequest(
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            MboxRequest mboxRequest,
            List <Option> consequenceOptions,
            List <Metric> consequenceMetrics,
            TraceHandler traceHandler)
        {
            if (prefetchResponse != null)
            {
                var prefetchMboxResponse =
                    new PrefetchMboxResponse(mboxRequest.Index, mboxRequest.Name, consequenceOptions, consequenceMetrics);
                prefetchResponse.Mboxes ??= new List <PrefetchMboxResponse>();
                prefetchResponse.Mboxes.Add(prefetchMboxResponse);
                return(true);
            }

            if (executeResponse == null)
            {
                return(false);
            }

            var mboxResponse =
                new MboxResponse(mboxRequest.Index, mboxRequest.Name, metrics: consequenceMetrics)
            {
                Options = consequenceOptions?.Select(
                    option =>
                {
                    option.EventToken = null;
                    return(option);
                })
                          .Where(option => option.Type != null || option.Content != null || option.ResponseTokens != null)
                          .ToList(),
                Trace = traceHandler?.CurrentTrace,
            };

            executeResponse.Mboxes ??= new List <MboxResponse>();
            executeResponse.Mboxes.Add(mboxResponse);
            return(true);
        }
        public void ExecuteDetails(
            TargetDeliveryRequest deliveryRequest,
            IDictionary <string, object> localContext,
            string visitorId,
            ISet <string> responseTokens,
            TraceHandler traceHandler,
            OnDeviceDecisioningRuleSet ruleSet,
            RequestDetailsUnion details,
            PrefetchResponse prefetchResponse,
            ExecuteResponse executeResponse,
            IList <Notification> notifications)
        {
            traceHandler?.UpdateRequest(deliveryRequest, details, executeResponse != null);
            var rules = GetDetailsRules(details, ruleSet);

            if (rules == null)
            {
                UnhandledResponse(details, prefetchResponse, executeResponse, traceHandler);
                return;
            }

            var propertyToken      = deliveryRequest.DeliveryRequest.Property?.Token;
            var handledAtLeastOnce = false;
            var skipKeySet         = new HashSet <string>();

            foreach (var rule in rules)
            {
                if (PropertyTokenMismatch(rule.PropertyTokens, propertyToken))
                {
                    continue;
                }

                if (rule.RuleKey != null && skipKeySet.Contains(rule.RuleKey))
                {
                    continue;
                }

                var consequence = this.ruleExecutor.ExecuteRule(localContext, details, visitorId, rule, responseTokens, traceHandler);
                if (!HandleResult(consequence, rule, details, prefetchResponse, executeResponse, notifications, traceHandler, ruleSet.GlobalMbox))
                {
                    continue;
                }

                handledAtLeastOnce = true;
                if (rule.RuleKey != null)
                {
                    skipKeySet.Add(rule.RuleKey);
                }

                if (details.Match(
                        _ => false,
                        _ => true,
                        _ => false))
                {
                    break;
                }
            }

            if (!handledAtLeastOnce)
            {
                UnhandledResponse(details, prefetchResponse, executeResponse, traceHandler);
            }
        }