using System;
using System.Collections.Generic;
using System.Text;
namespace mustache
{
    /// 
    /// Builds text by combining the output of other generators.
    /// 
    internal sealed class CompoundGenerator : IGenerator
    {
        private readonly TagDefinition _definition;
        private readonly ArgumentCollection _arguments;
        private readonly LinkedList _primaryGenerators;
        private IGenerator _subGenerator;
        /// 
        /// Initializes a new instance of a CompoundGenerator.
        /// 
        /// The tag that the text is being generated for.
        /// The arguments that were passed to the tag.
        public CompoundGenerator(TagDefinition definition, ArgumentCollection arguments)
        {
            _definition = definition;
            _arguments = arguments;
            _primaryGenerators = new LinkedList();
        }
        /// 
        /// Adds the given generator. 
        /// 
        /// The generator to add.
        public void AddGenerator(IGenerator generator)
        {
            addGenerator(generator, false);
        }
        /// 
        /// Adds the given generator, determining whether the generator should
        /// be part of the primary generators or added as an secondary generator.
        /// 
        /// The tag that the generator is generating text for.
        /// The generator to add.
        public void AddGenerator(TagDefinition definition, IGenerator generator)
        {
            bool isSubGenerator = _definition.ShouldCreateSecondaryGroup(definition);
            addGenerator(generator, isSubGenerator);
        }
        /// 
        /// Creates a StaticGenerator from the given value and adds it.
        /// 
        /// The static generators to add.
        public void AddStaticGenerators(IEnumerable generators)
        {
            foreach (StaticGenerator generator in generators)
            {
                LinkedListNode node = _primaryGenerators.AddLast(generator);
                generator.Node = node;
            }
        }
        private void addGenerator(IGenerator generator, bool isSubGenerator)
        {
            if (isSubGenerator)
            {
                _subGenerator = generator;
            }
            else
            {
                _primaryGenerators.AddLast(generator);
            }
        }
        string IGenerator.GetText(IFormatProvider provider, KeyScope scope)
        {
            StringBuilder builder = new StringBuilder();
            Dictionary arguments = _arguments.GetArguments(scope);
            IEnumerable scopes = _definition.GetChildScopes(scope, arguments);
            LinkedList generators;
            if (_definition.ShouldGeneratePrimaryGroup(arguments))
            {
                generators = _primaryGenerators;
            }
            else
            {
                generators = new LinkedList();
                if (_subGenerator != null)
                {
                    generators.AddLast(_subGenerator);
                }
            }
            foreach (KeyScope childScope in scopes)
            {
                foreach (IGenerator generator in generators)
                {
                    builder.Append(generator.GetText(provider, childScope));
                }
            }
            string innerText = builder.ToString();
            string outerText = _definition.Decorate(provider, innerText, arguments);
            return outerText;
        }
    }
}