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

package org.sablecc.objectmacro.intermediate.macro;

import java.util.*;

public class MDirective
        extends Macro {

    private DSeparator DirectiveNameSeparator;

    private DBeforeFirst DirectiveNameBeforeFirst;

    private DAfterLast DirectiveNameAfterLast;

    private DNone DirectiveNameNone;

    final List<Macro> list_DirectiveName;

    final Context DirectiveNameContext = new Context();

    final MacroValue DirectiveNameValue;

    private DSeparator DirectiveTextPartsSeparator;

    private DBeforeFirst DirectiveTextPartsBeforeFirst;

    private DAfterLast DirectiveTextPartsAfterLast;

    private DNone DirectiveTextPartsNone;

    final List<Macro> list_DirectiveTextParts;

    final Context DirectiveTextPartsContext = new Context();

    final MacroValue DirectiveTextPartsValue;

    MDirective(
            Macros macros) {

        setMacros(macros);
        this.list_DirectiveName = new LinkedList<>();
        this.list_DirectiveTextParts = new LinkedList<>();

        this.DirectiveNameValue = new MacroValue(this.list_DirectiveName,
                this.DirectiveNameContext);
        this.DirectiveTextPartsValue = new MacroValue(
                this.list_DirectiveTextParts, this.DirectiveTextPartsContext);
    }

    public void addAllDirectiveName(
            List<Macro> macros) {

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

        int i = 0;

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

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

            verifyTypeDirectiveName(macro);
            this.list_DirectiveName.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeDirectiveName(
            Macro macro) {

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

            @Override
            void setName(
                    MName mName) {

            }
        });
    }

    public void addDirectiveName(
            MName macro) {

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

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

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

    public void addAllDirectiveTextParts(
            List<Macro> macros) {

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

        int i = 0;

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

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

            verifyTypeDirectiveTextParts(macro);
            this.list_DirectiveTextParts.add(macro);
            this.children.add(macro);
            Macro.cycleDetector.detectCycle(this, macro);

            i++;
        }
    }

    void verifyTypeDirectiveTextParts(
            Macro macro) {

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

            @Override
            void setStringPart(
                    MStringPart mStringPart) {

            }

            @Override
            void setEolPart(
                    MEolPart mEolPart) {

            }

            @Override
            void setParamInsert(
                    MParamInsert mParamInsert) {

            }

            @Override
            void setMacroInsert(
                    MMacroInsert mMacroInsert) {

            }
        });
    }

    public void addDirectiveTextParts(
            MStringPart macro) {

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

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

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

    public void addDirectiveTextParts(
            MEolPart macro) {

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

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

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

    public void addDirectiveTextParts(
            MParamInsert macro) {

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

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

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

    public void addDirectiveTextParts(
            MMacroInsert macro) {

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

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

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

    private String buildDirectiveName() {

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

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

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

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

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

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

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

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

        return sb.toString();
    }

    private String buildDirectiveTextParts() {

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

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

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

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

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

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

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

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

        return sb.toString();
    }

    MacroValue getDirectiveName() {

        return this.DirectiveNameValue;
    }

    MacroValue getDirectiveTextParts() {

        return this.DirectiveTextPartsValue;
    }

    private void initDirectiveNameInternals(
            Context context) {

        for (Macro macro : this.list_DirectiveName) {
            macro.apply(new InternalsInitializer("DirectiveName") {

                @Override
                void setName(
                        MName mName) {

                }
            });
        }
    }

    private void initDirectiveTextPartsInternals(
            Context context) {

        for (Macro macro : this.list_DirectiveTextParts) {
            macro.apply(new InternalsInitializer("DirectiveTextParts") {

                @Override
                void setStringPart(
                        MStringPart mStringPart) {

                }

                @Override
                void setEolPart(
                        MEolPart mEolPart) {

                }

                @Override
                void setParamInsert(
                        MParamInsert mParamInsert) {

                }

                @Override
                void setMacroInsert(
                        MMacroInsert mMacroInsert) {

                }
            });
        }
    }

    private void initDirectiveNameDirectives() {

    }

    private void initDirectiveTextPartsDirectives() {

    }

    @Override
    void apply(
            InternalsInitializer internalsInitializer) {

        internalsInitializer.setDirective(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<>();

        initDirectiveNameDirectives();
        initDirectiveNameDirectives();
        initDirectiveTextPartsDirectives();
        initDirectiveTextPartsDirectives();

        initDirectiveNameInternals(null);
        initDirectiveTextPartsInternals(null);

        StringBuilder sb0 = new StringBuilder();

        sb0.append("Directive ");
        sb0.append("{");
        sb0.append(LINE_SEPARATOR);
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        sb2.append("    ");
        indentations.add(sb2.toString());
        sb1.append(buildDirectiveName());
        sb1.append(LINE_SEPARATOR);
        sb1.append(buildDirectiveTextParts());
        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;
    }
}
