/// <summary>
        /// Adds a new rule.
        /// </summary>
        /// <param name="rule">The rule.</param>
        /// <param name="ruleAddPriorityOption">The rule add priority option.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">rule or rule</exception>
        /// <exception cref="NotSupportedException">
        /// The placement option '{ruleAddPriorityOption.PriorityOption}' is not supported.
        /// </exception>
        public Task <RuleOperationResult> AddRuleAsync(Rule <TContentType, TConditionType> rule, RuleAddPriorityOption ruleAddPriorityOption)
        {
            if (rule is null)
            {
                throw new ArgumentNullException(nameof(rule));
            }

            if (ruleAddPriorityOption is null)
            {
                throw new ArgumentNullException(nameof(rule));
            }

            return(this.AddRuleInternalAsync(rule, ruleAddPriorityOption));
        }
        private async Task <RuleOperationResult> AddRuleInternalAsync(Rule <TContentType, TConditionType> rule, RuleAddPriorityOption ruleAddPriorityOption)
        {
            List <string> errors = new List <string>();
            RulesFilterArgs <TContentType> rulesFilterArgs = new RulesFilterArgs <TContentType>
            {
                ContentType = rule.ContentContainer.ContentType
            };

            IEnumerable <Rule <TContentType, TConditionType> > existentRules = await this.rulesDataSource.GetRulesByAsync(rulesFilterArgs).ConfigureAwait(false);

            if (ruleAddPriorityOption.PriorityOption == PriorityOptions.AtRuleName &&
                !existentRules.Any(r => string.Equals(r.Name, ruleAddPriorityOption.AtRuleNameOptionValue, StringComparison.OrdinalIgnoreCase)))
            {
                errors.Add($"Rule name '{ruleAddPriorityOption.AtRuleNameOptionValue}' specified for priority placement does not exist.");
            }

            if (existentRules.Any(r => string.Equals(r.Name, rule.Name, StringComparison.OrdinalIgnoreCase)))
            {
                errors.Add($"A rule with name '{rule.Name}' already exists.");
            }

            if (errors.Any())
            {
                return(RuleOperationResult.Error(errors));
            }

            switch (ruleAddPriorityOption.PriorityOption)
            {
            case PriorityOptions.AtTop:
                rule.Priority = 1;

                await ManagementOperations.Manage(existentRules)
                .UsingDataSource(this.rulesDataSource)
                .IncreasePriority()
                .UpdateRules()
                .AddRule(rule)
                .ExecuteOperationsAsync()
                .ConfigureAwait(false);

                break;

            case PriorityOptions.AtBottom:
                rule.Priority = existentRules.Max(r => r.Priority) + 1;

                await ManagementOperations.Manage(existentRules)
                .UsingDataSource(this.rulesDataSource)
                .AddRule(rule)
                .ExecuteOperationsAsync()
                .ConfigureAwait(false);

                break;

            case PriorityOptions.AtPriorityNumber:
                int priorityMin = existentRules.MinOrDefault(r => r.Priority);
                int priorityMax = existentRules.MaxOrDefault(r => r.Priority);

                int rulePriority = ruleAddPriorityOption.AtPriorityNumberOptionValue;
                rulePriority = Math.Min(rulePriority, priorityMax + 1);
                rulePriority = Math.Max(rulePriority, priorityMin);

                rule.Priority = rulePriority;

                await ManagementOperations.Manage(existentRules)
                .UsingDataSource(this.rulesDataSource)
                .FilterFromThresholdPriorityToBottom(rulePriority)
                .IncreasePriority()
                .UpdateRules()
                .AddRule(rule)
                .ExecuteOperationsAsync()
                .ConfigureAwait(false);

                break;

            case PriorityOptions.AtRuleName:
                int firstPriorityToIncrement = existentRules
                                               .FirstOrDefault(r => string.Equals(r.Name, ruleAddPriorityOption.AtRuleNameOptionValue, StringComparison.OrdinalIgnoreCase))
                                               .Priority;
                rule.Priority = firstPriorityToIncrement;

                await ManagementOperations.Manage(existentRules)
                .UsingDataSource(this.rulesDataSource)
                .FilterFromThresholdPriorityToBottom(firstPriorityToIncrement)
                .IncreasePriority()
                .UpdateRules()
                .AddRule(rule)
                .ExecuteOperationsAsync()
                .ConfigureAwait(false);

                break;

            default:
                throw new NotSupportedException($"The placement option '{ruleAddPriorityOption.PriorityOption}' is not supported.");
            }

            return(RuleOperationResult.Success());
        }