package yokohama.unit.translator;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import lombok.SneakyThrows;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import yokohama.unit.ast.Group;
import yokohama.unit.ast_junit.CompilationUnit;
import yokohama.unit.grammar.YokohamaUnitLexer;
import yokohama.unit.grammar.YokohamaUnitParser;
import yokohama.unit.grammar.YokohamaUnitParser.GroupContext;

public class TranslatorUtils {

    public static class TranslationException extends RuntimeException {
    }

    private static class ErrorListener extends BaseErrorListener {
        public int numErrors = 0;
        @Override
        public void syntaxError(
                Recognizer<?, ?> recognizer,
                Object offendingSymbol,
                int line,
                int charPositionInLine,
                String msg,
                RecognitionException e) {
            numErrors++;
        }
    }

    public static Group parseDocy(final String input) {
        return parseDocy(input, YokohamaUnitLexer.DEFAULT_MODE);
    }

    @SneakyThrows(IOException.class)
    public static Group parseDocy(final String input, final int mode) {
        ErrorListener errorListener = new ErrorListener();
        InputStream bais = new ByteArrayInputStream(input.getBytes());
        CharStream stream = new ANTLRInputStream(bais);
        Lexer lex = new YokohamaUnitLexer(stream);
        lex.mode(mode);
        lex.addErrorListener(errorListener);
        CommonTokenStream tokens = new CommonTokenStream(lex);
        YokohamaUnitParser parser = new YokohamaUnitParser(tokens);
        parser.addErrorListener(errorListener);
        GroupContext ctx = parser.group();
        if (errorListener.numErrors > 0) {
            throw new TranslationException();
        }
        return new ParseTreeToAstVisitor().visitGroup(ctx);
    }

    public static String docyToJava(
            final Optional<Path> docyPath,
            final String docy,
            final String className,
            final String packageName) {
        // Source to AST
        Group ast = parseDocy(docy);

        // AST to JUnit AST
        CompilationUnit junit =
                new AstToJUnitAst(
                        docyPath,
                        className,
                        packageName,
                        new OgnlExpressionStrategy(),
                        new MockitoMockStrategy()
                ).translate(className, ast, packageName);

        // JUnit AST to string
        return junit.getText();
    }

    public static boolean compileDocy(
            final Optional<Path> path,
            final String docy,
            final String className,
            final String packageName,
            final List<String> classPath,
            final Optional<Path> dest,
            final String... options) throws IOException {
        try (ConfigurableApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml")) {
            DocyCompiler docyCompiler = context.getBean(DocyCompilerImpl.class);
            return docyCompiler.compile(
                    path.get(),
                    new ByteArrayInputStream(docy.getBytes()),
                    className,
                    packageName,
                    classPath,
                    dest,
                    Arrays.asList(options));
        }
    }
}

@@ -158,58 +158,8 @@
 h;%0D%0A
-import java.util.Arrays;%0D%0Aimport java.util.List;%0D%0A
 impo
@@ -527,152 +527,8 @@
 r;%0D%0A
-import org.springframework.context.ConfigurableApplicationContext;%0D%0Aimport org.springframework.context.support.ClassPathXmlApplicationContext;%0D%0A
 impo
@@ -2974,886 +2974,8 @@
   %7D%0D
-%0A%0D%0A    public static boolean compileDocy(%0D%0A            final Optional%3CPath%3E path,%0D%0A            final String docy,%0D%0A            final String className,%0D%0A            final String packageName,%0D%0A            final List%3CString%3E classPath,%0D%0A            final Optional%3CPath%3E dest,%0D%0A            final String... options) throws IOException %7B%0D%0A        try (ConfigurableApplicationContext context =%0D%0A                new ClassPathXmlApplicationContext(%22applicationContext.xml%22)) %7B%0D%0A            DocyCompiler docyCompiler = context.getBean(DocyCompilerImpl.class);%0D%0A            return docyCompiler.compile(%0D%0A                    path.get(),%0D%0A                    new ByteArrayInputStream(docy.getBytes()),%0D%0A                    className,%0D%0A                    packageName,%0D%0A                    classPath,%0D%0A                    dest,%0D%0A                    Arrays.asList(options));%0D%0A        %7D%0D%0A    %7D%0D
 %0A%7D%0D%0A

Delete compileDocy method