package org.dicio.sentences_compiler.compiler;

import org.dicio.sentences_compiler.construct.Section;
import org.dicio.sentences_compiler.util.CompilerError;
import org.dicio.sentences_compiler.util.JavaSyntaxCheck;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;

public class CompilerToJava extends CompilerBase {
    private final String variablePrefix;
    private final String packageName;
    private final String className;
    private final String sectionMapName;

    public CompilerToJava(final String variablePrefix,
                          final String packageName,
                          final String className,
                          final String sectionMapName) {
        this.variablePrefix = variablePrefix;
        this.packageName = packageName;
        this.className = className;
        this.sectionMapName = sectionMapName;

        if (!variablePrefix.isEmpty()) {
            JavaSyntaxCheck.checkValidJavaVariableName(variablePrefix, "variablePrefix");
        }
        JavaSyntaxCheck.checkValidJavaVariableName(className, "className");
        if (!sectionMapName.isEmpty()) {
            JavaSyntaxCheck.checkValidJavaVariableName(sectionMapName, "sectionMapName");
        }
    }

    public void compileToVariables(final OutputStreamWriter output)
            throws IOException, CompilerError {
        final List<Section> sections = getSections();
        for (final Section section : sections) {
            section.compileToJava(output, variablePrefix + section.getSectionId());
            output.write(";\n");
        }

        if (!sectionMapName.isEmpty()) {
            output.write("public static final Map<String,StandardRecognizerData>");
            output.write(sectionMapName);
            output.write("=new HashMap<String,StandardRecognizerData>(){{");
            for (final Section section : sections) {
                output.write("put(\"");
                output.write(section.getSectionId());
                output.write("\",");
                output.write(variablePrefix + section.getSectionId());
                output.write(");");
            }
            output.write("}};\n");
        }

        output.flush();
    }

    @Override
    public void compile(final OutputStreamWriter output,
                        final OutputStreamWriter sectionIdsOutput)
            throws IOException, CompilerError {
        super.compile(output, sectionIdsOutput);

        output.write("/*\n * ");
        output.write(autoGeneratedFileNotice);
        output.write("\n */\n\n");

        output.write("package ");
        output.write(packageName);

        // when changing imported packages, make sure to also update the list of restricted
        // variable names in util.JavaSyntaxCheck.importedClasses
        if (!sectionMapName.isEmpty()) {
            output.write(";\n"
                    + "import java.util.Map;\n"
                    + "import java.util.HashMap");
        }
        output.write(
                ";\n"
                + "import org.dicio.skill.skill.Specificity;\n"
                + "import org.dicio.skill.standard.Sentence;\n"
                + "import org.dicio.skill.standard.StandardRecognizerData;\n"
                + "import org.dicio.skill.standard.word.DiacriticsInsensitiveWord;\n"
                + "import org.dicio.skill.standard.word.DiacriticsSensitiveWord;\n"
                + "import org.dicio.skill.standard.word.DiacriticsInsensitiveRegexWord;\n"
                + "import org.dicio.skill.standard.word.DiacriticsSensitiveRegexWord;\n"
                + "import org.dicio.skill.standard.word.CapturingGroup;\n"
                + "public class ");
        output.write(className);

        output.write(" {\n");
        compileToVariables(output);
        output.write("}\n");
        output.flush();
    }
}
