/* This file was generated by SableCC's ObjectMacro. */

package org.sablecc.objectmacro.intermediate.macro;

import java.util.*;

public class MTextArgument
        extends Macro {

    private DSeparator ParamNameSeparator;

    private DBeforeFirst ParamNameBeforeFirst;

    private DAfterLast ParamNameAfterLast;

    private DNone ParamNameNone;

    final List<String> list_ParamName;

    final Context ParamNameContext = new Context();

    final StringValue ParamNameValue;

    private DSeparator TextPartsSeparator;

    private DBeforeFirst TextPartsBeforeFirst;

    private DAfterLast TextPartsAfterLast;

    private DNone TextPartsNone;

    final List<Macro> list_TextParts;

    final Context TextPartsContext = new Context();

    final MacroValue TextPartsValue;

    MTextArgument(
            Macros macros) {

        setMacros(macros);
        this.list_ParamName = new LinkedList<>();
        this.list_TextParts = new LinkedList<>();

        this.ParamNameValue
                = new StringValue(this.list_ParamName, this.ParamNameContext);
        this.TextPartsValue
                = new MacroValue(this.list_TextParts, this.TextPartsContext);
    }

    public void addAllParamName(
            List<String> strings) {

        if (this.macros == null) {
            throw ObjectMacroException.parameterNull("ParamName");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }
        for (String string : strings) {
            if (string == null) {
                throw ObjectMacroException.parameterNull("ParamName");
            }

            this.list_ParamName.add(string);
        }
    }

    public void addParamName(
            String string) {

        if (string == null) {
            throw ObjectMacroException.parameterNull("ParamName");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        this.list_ParamName.add(string);
    }

    public void addAllTextParts(
            List<Macro> macros) {

        if (macros == null) {
            throw ObjectMacroException.parameterNull("TextParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        int i = 0;

        for (Macro macro : macros) {
            if (macro == null) {
                throw ObjectMacroException.macroNull(i, "TextParts");
            }

            if (getMacros() != macro.getMacros()) {
                throw ObjectMacroException.diffMacros();
            }

            verifyTypeTextParts(macro);
            this.list_TextParts.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeTextParts(
            Macro macro) {

        macro.apply(new InternalsInitializer("TextParts") {

            @Override
            void setStringPart(
                    MStringPart mStringPart) {

            }

            @Override
            void setEolPart(
                    MEolPart mEolPart) {

            }

            @Override
            void setParamInsert(
                    MParamInsert mParamInsert) {

            }

            @Override
            void setMacroInsert(
                    MMacroInsert mMacroInsert) {

            }
        });
    }

    public void addTextParts(
            MStringPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("TextParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_TextParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addTextParts(
            MEolPart macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("TextParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_TextParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addTextParts(
            MParamInsert macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("TextParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_TextParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    public void addTextParts(
            MMacroInsert macro) {

        if (macro == null) {
            throw ObjectMacroException.parameterNull("TextParts");
        }
        if (this.cacheBuilder != null) {
            throw ObjectMacroException
                    .cannotModify(this.getClass().getSimpleName());
        }

        if (getMacros() != macro.getMacros()) {
            throw ObjectMacroException.diffMacros();
        }

        this.list_TextParts.add(macro);
        this.children.add(macro);
        Macro.cycleDetector.detectCycle(this, macro);
    }

    private String buildParamName() {

        StringBuilder sb = new StringBuilder();
        List<String> strings = this.list_ParamName;

        int i = 0;
        int nb_strings = strings.size();

        if (this.ParamNameNone != null) {
            sb.append(this.ParamNameNone.apply(i, "", nb_strings));
        }

        for (String string : strings) {

            if (this.ParamNameBeforeFirst != null) {
                string = this.ParamNameBeforeFirst.apply(i, string, nb_strings);
            }

            if (this.ParamNameAfterLast != null) {
                string = this.ParamNameAfterLast.apply(i, string, nb_strings);
            }

            if (this.ParamNameSeparator != null) {
                string = this.ParamNameSeparator.apply(i, string, nb_strings);
            }

            sb.append(string);
            i++;
        }

        return sb.toString();
    }

    private String buildTextParts() {

        StringBuilder sb = new StringBuilder();
        Context local_context = this.TextPartsContext;
        List<Macro> macros = this.list_TextParts;

        int i = 0;
        int nb_macros = macros.size();
        String expansion = null;

        if (this.TextPartsNone != null) {
            sb.append(this.TextPartsNone.apply(i, "", nb_macros));
        }

        for (Macro macro : macros) {
            expansion = macro.build(local_context);

            if (this.TextPartsBeforeFirst != null) {
                expansion = this.TextPartsBeforeFirst.apply(i, expansion,
                        nb_macros);
            }

            if (this.TextPartsAfterLast != null) {
                expansion = this.TextPartsAfterLast.apply(i, expansion,
                        nb_macros);
            }

            if (this.TextPartsSeparator != null) {
                expansion = this.TextPartsSeparator.apply(i, expansion,
                        nb_macros);
            }

            sb.append(expansion);
            i++;
        }

        return sb.toString();
    }

    StringValue getParamName() {

        return this.ParamNameValue;
    }

    MacroValue getTextParts() {

        return this.TextPartsValue;
    }

    private void initTextPartsInternals(
            Context context) {

        for (Macro macro : this.list_TextParts) {
            macro.apply(new InternalsInitializer("TextParts") {

                @Override
                void setStringPart(
                        MStringPart mStringPart) {

                }

                @Override
                void setEolPart(
                        MEolPart mEolPart) {

                }

                @Override
                void setParamInsert(
                        MParamInsert mParamInsert) {

                }

                @Override
                void setMacroInsert(
                        MMacroInsert mMacroInsert) {

                }
            });
        }
    }

    private void initParamNameDirectives() {

    }

    private void initTextPartsDirectives() {

        StringBuilder sb1 = new StringBuilder();
        sb1.append(LINE_SEPARATOR);
        this.TextPartsSeparator = new DSeparator(sb1.toString());
        this.TextPartsValue.setSeparator(this.TextPartsSeparator);
    }

    @Override
    void apply(
            InternalsInitializer internalsInitializer) {

        internalsInitializer.setTextArgument(this);
    }

    public String build() {

        CacheBuilder cache_builder = this.cacheBuilder;

        if (cache_builder == null) {
            cache_builder = new CacheBuilder();
        }
        else if (cache_builder.getExpansion() == null) {
            throw new InternalException("Cycle detection detected lately");
        }
        else {
            return cache_builder.getExpansion();
        }
        this.cacheBuilder = cache_builder;
        List<String> indentations = new LinkedList<>();

        initParamNameDirectives();
        initTextPartsDirectives();
        initTextPartsDirectives();

        initTextPartsInternals(null);

        StringBuilder sb0 = new StringBuilder();

        sb0.append("Value");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        sb2.append("    ");
        indentations.add(sb2.toString());
        MParamName m1 = getMacros().newParamName();

        m1.setName(null, getParamName());
        sb1.append(m1.build(null));
        sb1.append(LINE_SEPARATOR);
        sb1.append(buildTextParts());
        sb0.append(applyIndent(sb1.toString(),
                indentations.remove(indentations.size() - 1)));
        sb0.append(LINE_SEPARATOR);
        sb0.append("}");

        cache_builder.setExpansion(sb0.toString());
        return sb0.toString();
    }

    @Override
    String build(
            Context context) {

        return build();
    }

    private void setMacros(
            Macros macros) {

        if (macros == null) {
            throw new InternalException("macros cannot be null");
        }

        this.macros = macros;
    }
}
