/// <summary>
        /// Formats the combination list for wiki output, supports page partitioning.
        /// </summary>
        /// <param name="comboList">The list containing item combinations.</param>
        /// <param name="selectedCard">The selected card.</param>
        /// <param name="selectedTemplatedCharacter">The selected templated character.</param>
        /// <param name="partitionSize">Results per page.</param>
        public static string PartitionedWikiOutput(IEnumerable<ItemCombinationWithInfo> comboList, Card selectedCard, Character selectedTemplatedCharacter, int partitionSize)
        {
            if (comboList.ToList().Count == 0)
                return "No Results.";

            int maxCards = comboList.Max(z => z.CardCount);

            // Impose contraints, order.
            var OrderedList = comboList
                .Where(x => x.CardCount == maxCards)
                .OrderBy(x => x.TokenCount)                                                             // Least Tokens first
                .ThenByDescending(x => x.TokenInfo.Where(t => t.Name == Talent.C).SingleOrDefault()     // Most Circle (Low end tokens first).
                    != null ? x.TokenInfo.Where(t => t.Name == Talent.C).SingleOrDefault().Total : 0);

            var chunk = OrderedList.Take(partitionSize).Select((y, i) => new { i, InfoList = y });
            int chunkCounter = 1;

            StringBuilder builder = new StringBuilder();

            while (chunk.Count() > 0)
            {
                builder.AppendLine(string.Format("(Page {0})", chunkCounter));
                builder.AppendLine();
                builder.AppendLine("{{MaxCard");
                builder.AppendLine(string.Format("|cardname={0}", selectedCard.Name));
                builder.AppendLine(string.Format("|maxqty={0}", maxCards));
                builder.AppendLine(string.Format("|class={0}", selectedTemplatedCharacter.CharacterClass));

                foreach (var itemList in chunk)
                {
                    var combined = itemList.InfoList.Items
                        .GroupBy(x => x)
                        .Select((y, j) => String.Format("|build{0}_item{1}_qty={2}\n|build{3}_item{4}={5}",
                            itemList.i + 1, j + 1, y.Count(), itemList.i + 1, j + 1, y.Key));

                    builder.AppendLine(String.Join("\n", combined));
                    builder.AppendLine(string.Empty);
                }

                builder.AppendLine("}}");
                builder.AppendLine();

                chunk = OrderedList.Skip(partitionSize * chunkCounter).Take(partitionSize).Select((y, i) => new { i, InfoList = y });
                chunkCounter++;
            }

            return builder.ToString();
        }
        /// <summary>
        /// Generates a list of all possible item combinations containing a particular card, for a particular character/slot configuration.
        /// Adds additional item details for further processing.
        /// </summary>
        /// <param name="selectedCard">The selected card.</param>
        /// <param name="selectedTemplatedCharacter">The selected templated character.</param>
        /// <returns></returns>
        public List<ItemCombinationWithInfo> GetItemCombinationsForCharacter(Func<Item, bool> itemFilter, Func<Card, bool> cardFilter, Character selectedTemplatedCharacter, bool isItemOptimisationEnabled = false)
        {
            List<ItemCombinationWithInfo> additionalInfo = new List<ItemCombinationWithInfo>();

            IEnumerable<IEnumerable<Item>> results = this.GenerateCardCombinationsForSlots(itemFilter, selectedTemplatedCharacter.Slots, cardFilter, isItemOptimisationEnabled);

            if (results.Count() == 0)
                return additionalInfo;

            additionalInfo = GenerateExtraItemListInformation(results, itemFilter, cardFilter);

            return additionalInfo;
        }
        /// <summary>
        /// Formats the combination list into a more easily readable raw text output.
        /// </summary>
        /// <param name="comboList">The list containing item combinations.</param>
        /// <param name="selectedCard">The selected card.</param>
        /// <param name="selectedTemplatedCharacter">The selected templated character.</param>
        /// <returns></returns>
        public static string MaxedRawTextOutput(IEnumerable<ItemCombinationWithInfo> comboList, Card selectedCard, Character selectedTemplatedCharacter)
        {
            if (comboList.ToList().Count == 0)
                return "No Results.";

            StringBuilder builder = new StringBuilder();

            foreach (var itemList in comboList)
            {
                // Combined list of items.
                var combined =
                    from item in itemList.Items
                    group item by item into grouped
                    select
                    String.Format("{0} x {1}", grouped.Count(), grouped.Key);

                // Combined list of Talents.
                var tokens = from token in itemList.TokenInfo
                             select String.Format("{0} x {1}", token.Name, token.Total);

                builder.AppendLine(
                    string.Format("Max: {0} - Cards present: {1} (Total Tokens: {2} Breakdown: {3}). Items: {4}",
                    selectedCard.Name,
                    itemList.CardCount,
                    itemList.TokenCount,
                    String.Join(", ", tokens),
                    String.Join(", ", combined)));
            }

            return builder.ToString();
        }