/*
 * Copyright 2018, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.tools.protojs.code;

import static java.lang.String.format;
import static java.lang.String.join;
import static java.lang.System.lineSeparator;

public final class JsGenerator {

    private static final String LINE_SEPARATOR = lineSeparator();
    private static final int STANDARD_INDENT = 2;

    private final JsOutput generatedCode;
    private int currentDepth;

    public JsGenerator() {
        this.generatedCode = new JsOutput(LINE_SEPARATOR, STANDARD_INDENT);
        this.currentDepth = 0;
    }

    public JsGenerator(int indent) {
        this.generatedCode = new JsOutput(LINE_SEPARATOR, indent);
        this.currentDepth = 0;
    }

    public void addLine(String lineOfCode) {
        generatedCode.addLine(lineOfCode, currentDepth);
    }

    public void addEmptyLine() {
        addLine("");
    }

    public void increaseDepth() {
        currentDepth++;
    }

    public void decreaseDepth() {
        currentDepth--;
    }

    /**
     * @param functionName full function name including type name
     * @param functionArgs
     */
    public void enterFunction(String functionName, String... functionArgs) {
        String argString = join(", ", functionArgs);
        addLine(functionName + " = function(" + argString + ") {");
        currentDepth++;
    }

    public void exitFunction() {
        currentDepth--;
        addLine("};");
    }

    public void enterIfBlock(String condition) {
        enterBlock("if (" + condition + ')');
    }

    public void enterElseBlock() {
        currentDepth--;
        addLine("} else {");
        currentDepth++;
    }

    public void enterBlock(String blockHeader) {
        addLine(blockHeader + " {");
        currentDepth++;
    }

    public void exitBlock() {
        currentDepth--;
        addLine("}");
    }

    public void exportMap(String mapName) {
        addLine("export const " + mapName + " = new Map([");
        increaseDepth();
    }

    public void addMapEntry(String entry, boolean isLast) {
        String lineToAdd = appendCommaIfNotLast(entry, isLast);
        addLine(lineToAdd);
    }

    public void quitMapDeclaration() {
        decreaseDepth();
        addLine("]);");
    }

    public JsOutput getGeneratedCode() {
        return generatedCode;
    }

    private static String appendCommaIfNotLast(String entry, boolean isLast) {
        if (!isLast) {
            return entry + ',';
        }
        return entry;
    }
}

@@ -3029,91 +3029,110 @@
     
-String lineToAdd = appendCommaIfNotLast(entry, isLast);%0A        addLine(lineToAdd);
+if (isLast) %7B%0A            addLine(entry);%0A        %7D else %7B%0A            addLine(entry + ',');%0A        %7D
 %0A   
@@ -3267,24 +3267,24 @@
 tedCode() %7B%0A
+
         retu
@@ -3310,180 +3310,7 @@
    %7D
-%0A%0A    private static String appendCommaIfNotLast(String entry, boolean isLast) %7B%0A        if (!isLast) %7B%0A            return entry + ',';%0A        %7D%0A        return entry;%0A    %7D
 %0A%7D%0A

Remove excessive method declaration