private void Aquire(
                Dictionary <int, OverlapppedDiscounts> itemGroupIndexToOverlapppedDiscountsLookup,
                OverlapppedDiscounts overlapppedDiscountsToAcquire)
            {
                using (SimpleProfiler profiler = new SimpleProfiler("OverlappedDiscounts.Aquire", 4))
                {
                    this.MixAndMatchAndQuantityDiscounts.AddRange(overlapppedDiscountsToAcquire.MixAndMatchAndQuantityDiscounts);
                    this.CoveredItemGroupIndexSet.AddRange(overlapppedDiscountsToAcquire.CoveredItemGroupIndexSet);

                    foreach (KeyValuePair <string, DiscountBase> pairOfferIdToDiscount in overlapppedDiscountsToAcquire.MixAndMatchAndQuantityDiscounts)
                    {
                        DiscountBase discount = pairOfferIdToDiscount.Value;
                        foreach (KeyValuePair <int, HashSet <decimal> > pair in discount.ItemGroupIndexToDiscountLineNumberSetMap)
                        {
                            int itemGroupIndex = pair.Key;
                            itemGroupIndexToOverlapppedDiscountsLookup[itemGroupIndex] = this;
                        }
                    }
                }
            }
            /// <summary>
            /// Splits all discounts into multiple groups of overlapped discounts with each group non-overlapping with each other.
            /// </summary>
            /// <param name="possibleDiscounts">Possible discounts.</param>
            /// <returns>A collection of overlapped discounts.</returns>
            /// <remarks>By isolating discounts into groups, we can calculate and optimize discounts for each group.</remarks>
            internal static IEnumerable <OverlapppedDiscounts> BuildOverlappedDiscountsGroup(List <DiscountBase> possibleDiscounts)
            {
                // DISCOUNTPERF: add filtering by remaining quantities
                // Build lookup for mix and match and quantity discounts. Ignore offer discounts for now.
                Dictionary <int, OverlapppedDiscounts> itemGroupIndexToOverlapppedDiscountsLookup = new Dictionary <int, OverlapppedDiscounts>();

                foreach (DiscountBase discount in possibleDiscounts)
                {
                    if (discount is MixAndMatchDiscount || discount is MultipleBuyDiscount)
                    {
                        OverlapppedDiscounts myOverlapppedDiscounts = null;
                        foreach (KeyValuePair <int, HashSet <decimal> > pair in discount.ItemGroupIndexToDiscountLineNumberSetMap)
                        {
                            int itemGroupIndex = pair.Key;
                            OverlapppedDiscounts overlappedDiscounts = null;
                            if (itemGroupIndexToOverlapppedDiscountsLookup.TryGetValue(itemGroupIndex, out overlappedDiscounts))
                            {
                                // Item covered in an overlappedDiscounts already.
                                if (myOverlapppedDiscounts == null)
                                {
                                    // myOverlapppedDiscounts not set yet, add current discount to it.
                                    myOverlapppedDiscounts = overlappedDiscounts;
                                    myOverlapppedDiscounts.MixAndMatchAndQuantityDiscounts.Add(discount.OfferId, discount);
                                }
                                else if (myOverlapppedDiscounts.OverlapId != overlappedDiscounts.OverlapId)
                                {
                                    // Item covered in a different overlappedDiscounts, myOverlapppedDiscounts acquires it.
                                    myOverlapppedDiscounts.Aquire(itemGroupIndexToOverlapppedDiscountsLookup, overlappedDiscounts);
                                    itemGroupIndexToOverlapppedDiscountsLookup[itemGroupIndex] = myOverlapppedDiscounts;
                                }
                            }
                            else
                            {
                                // Item not covered yet.
                                if (myOverlapppedDiscounts == null)
                                {
                                    // New overlappedDiscounts.
                                    myOverlapppedDiscounts = new OverlapppedDiscounts(itemGroupIndex, discount);
                                }
                                else
                                {
                                    // Add item to the overlappedDiscounts.
                                    myOverlapppedDiscounts.CoveredItemGroupIndexSet.Add(itemGroupIndex);
                                }

                                itemGroupIndexToOverlapppedDiscountsLookup[itemGroupIndex] = myOverlapppedDiscounts;
                            }
                        }
                    }
                }

                // Add offer discounts to the lookup.
                foreach (DiscountBase discount in possibleDiscounts)
                {
                    if (discount is OfferDiscount)
                    {
                        foreach (KeyValuePair <int, HashSet <decimal> > pair in discount.ItemGroupIndexToDiscountLineNumberSetMap)
                        {
                            int itemGroupIndex = pair.Key;
                            OverlapppedDiscounts overlappedDiscounts = null;
                            if (itemGroupIndexToOverlapppedDiscountsLookup.TryGetValue(itemGroupIndex, out overlappedDiscounts))
                            {
                                overlappedDiscounts.OfferDiscounts[discount.OfferId] = discount;
                            }
                        }
                    }
                }

                // Convert itemGroupIndexToOverlapppedDiscountsLookup to List<OverlapppedDiscounts>.
                HashSet <Guid> overlappedIdSet = new HashSet <Guid>();
                List <OverlapppedDiscounts> overlappedDiscountsList = new List <OverlapppedDiscounts>();

                foreach (KeyValuePair <int, OverlapppedDiscounts> pair in itemGroupIndexToOverlapppedDiscountsLookup)
                {
                    OverlapppedDiscounts overlappedDiscounts = pair.Value;

                    if (!overlappedIdSet.Contains(overlappedDiscounts.OverlapId))
                    {
                        overlappedIdSet.Add(overlappedDiscounts.OverlapId);
                        overlappedDiscountsList.Add(overlappedDiscounts);
                    }
                }

                return(overlappedDiscountsList);
            }
            internal DiscountBase[] GetSortedDiscountsToApplyInFastMode(
                DiscountableItemGroup[] discountableItemGroups,
                decimal[] remainingQuantities,
                decimal[] remainingQuantitiesForCompound,
                HashSet <int> itemsWithOverlappingDiscounts,
                HashSet <int> itemsWithOverlappingDiscountsCompoundedOnly)
            {
                using (SimpleProfiler profiler = new SimpleProfiler("OverlappedDiscounts.GetDiscountsToApplyInFastMode", 2))
                {
                    Dictionary <string, DiscountDealEstimate> offerIdToEstimateNonCompoundedLookup = new Dictionary <string, DiscountDealEstimate>(StringComparer.OrdinalIgnoreCase);

                    // Consolidate all compounded discounts into one estimate, to be sorted with the rest later.
                    List <DiscountBase>  compoundedDiscounts           = new List <DiscountBase>();
                    DiscountDealEstimate combinedEstimateForCompounded = null;

                    // Build estimates for offer discounts.
                    combinedEstimateForCompounded = OverlapppedDiscounts.BuildEstimates(
                        offerIdToEstimateNonCompoundedLookup,
                        compoundedDiscounts,
                        combinedEstimateForCompounded,
                        this.OfferDiscounts,
                        discountableItemGroups,
                        remainingQuantities,
                        remainingQuantitiesForCompound,
                        itemsWithOverlappingDiscounts,
                        itemsWithOverlappingDiscountsCompoundedOnly);

                    // Build estimates for mix and match and quantity discounts.
                    combinedEstimateForCompounded = OverlapppedDiscounts.BuildEstimates(
                        offerIdToEstimateNonCompoundedLookup,
                        compoundedDiscounts,
                        combinedEstimateForCompounded,
                        this.MixAndMatchAndQuantityDiscounts,
                        discountableItemGroups,
                        remainingQuantities,
                        remainingQuantitiesForCompound,
                        itemsWithOverlappingDiscounts,
                        itemsWithOverlappingDiscountsCompoundedOnly);

                    List <DiscountDealEstimate> estimatedSorted = new List <DiscountDealEstimate>(offerIdToEstimateNonCompoundedLookup.Values);
                    if (combinedEstimateForCompounded != null)
                    {
                        estimatedSorted.Add(combinedEstimateForCompounded);
                    }

                    estimatedSorted.Sort(DiscountDealEstimate.GetComparison());

    #if DEBUG
                    foreach (DiscountDealEstimate estimate in estimatedSorted)
                    {
                        estimate.DebugDisplay();
                    }
    #endif

                    DiscountBase[] discountsSorted = new DiscountBase[this.MixAndMatchAndQuantityDiscounts.Count + this.OfferDiscounts.Count];
                    int            discountIndex   = 0;
                    for (int i = estimatedSorted.Count - 1; i >= 0; i--)
                    {
                        DiscountDealEstimate estimate = estimatedSorted[i];

                        if (estimate.CanCompound)
                        {
                            for (int compoundedIndex = 0; compoundedIndex < compoundedDiscounts.Count; compoundedIndex++)
                            {
                                discountsSorted[discountIndex] = compoundedDiscounts[compoundedIndex];
                                discountIndex++;
                            }
                        }
                        else
                        {
                            DiscountBase discount = null;

                            if (this.MixAndMatchAndQuantityDiscounts.TryGetValue(estimate.OfferId, out discount))
                            {
                                discountsSorted[discountIndex] = discount;
                                discountIndex++;
                            }
                            else if (this.OfferDiscounts.TryGetValue(estimate.OfferId, out discount))
                            {
                                discountsSorted[discountIndex] = discount;
                                discountIndex++;
                            }
                        }
                    }

                    return(discountsSorted);
                }
            }