package compiler;

import filehandler.JsonWriter;
import grammar.ReceiptLexer;
import grammar.ReceiptParser;
import infrastructure.SemanticListener;
import infrastructure.exceptions.JsonExportException;
import infrastructure.exceptions.SemanticException;
import infrastructure.exceptions.TranslationException;
import infrastructure.json.JsonStructure;
import infrastructure.translator.Translator;
import java.io.File;
import java.io.FileInputStream;
import java.util.LinkedList;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.RecognitionException;

/**
 *
 * @author Lucas
 */
public class Compiler {

    private static LinkedList<String> filesToCompile;

    private String in;
    private String out;
    
    private static int Id;

    Compiler(String in) {
        try {
            if (in.isEmpty()) {
                throw new IllegalArgumentException("Parameter in cannot be an empty String");
            }

            this.in = in;
            
            String parent = new File(in).getParentFile().getName();
            out = in.substring(0, in.indexOf("input")) + "output\\";
            
            if (!parent.equals("input")) {
                out += parent + "\\";
            }
            
            out += (++Id) + ".json";
        } catch (NullPointerException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }
    
    Compiler(String in, String out) {
        this(in);
        this.out = out;
    }

    /**
     * @param args the command line arguments
     * @throws java.lang.Exception
     */
    public static void main(String[] args) throws Exception {
        filesToCompile = new LinkedList<>();

        if (args.length > 0) {
            File file = new File(args[0]);
            
            if (file.isDirectory()) {
                for (File child : file.listFiles()) {
                    filesToCompile.add(child.getPath());
                }
            } else {
                filesToCompile.add(file.getPath());
            }
        } else {
            filesToCompile.add("src/input/test.txt");
        }
        
        for (String file : filesToCompile) {
            try {
                new Compiler(file).start();
            
            } catch (IllegalArgumentException e) {
                System.err.println("The input file name is invalid: \"" + file + "\"");
            
            } catch (RecognitionException e) {
                System.err.println("Recognition error on file \"" + file + "\": "
                + e.getMessage());

            } catch (SemanticException e) {
                System.err.println("Semantic error on file \"" + file + "\".\n"
                        + "The compilation of this specific file cannot continue.");

            } catch (TranslationException e) {
                System.err.println("Translation error on file \"" + file + "\": "
                    + e.getMessage());
                
            } catch (JsonExportException e) {
                System.err.println("Json exportation error on file \"" + file + "\": "
                    + e.getMessage());
            } catch (Exception e) {
                System.err.println("An error has occured while compiling file \"" + file + "\": "
                    + e.getMessage());
            }
        }
    }

    private void start() throws Exception {
        System.out.println("\nCompilation proccess has started. File being compiled: " + in);

        ANTLRInputStream inputStream = new ANTLRInputStream(new FileInputStream(in));

        ReceiptLexer lexer   = new ReceiptLexer(inputStream);
        ReceiptParser parser = new ReceiptParser(new CommonTokenStream(lexer));

        // parse input file and retrieve its JsonStructure
        JsonStructure tree = parser.receipt().e;
        
        SemanticListener semantics = new SemanticListener(tree);
        
        if(semantics.hasErrors()) {
            System.err.println("\nSemantic errors were found:");
            
            for (String error : semantics.errors()) {
                System.err.println(error);
            }
            
            throw new SemanticException();
        }

        System.out.println("Parsing completed.");

        // print JsonStructure to the String result
        String result = new Translator(tree)
                .run()
                .export();

        // export file with printed JsonStructure
        new JsonWriter(out, result)
                .export();

        System.out.println("Finished!");
    }
}

@@ -3564,73 +3564,84 @@
 (%22%5Cn
-Compilation proccess has started. File being compiled: %22 + in);%0D%0A
+Input file: %22 + in);%0D%0A%0D%0A        System.out.print(%22Parsing has started... %22);
 %0D%0A  
@@ -3983,16 +3983,54 @@
 t().e;%0D%0A
+        System.out.println(%22Done!%22);%0D%0A
         
@@ -4176,18 +4176,16 @@
 rintln(%22
-%5Cn
 Semantic
@@ -4435,37 +4435,42 @@
 rint
-ln(%22Parsing comple
+(%22Translation has star
 ted.
+.. 
 %22);%0D%0A
-%0D%0A
     
@@ -4607,32 +4607,127 @@
      .export();%0D
+%0A        System.out.println(%22Done!%22);%0D%0A%0D%0A        System.out.print(%22Exporting .json file... %22);%0D
 %0A%0D%0A        // ex
@@ -4863,16 +4863,12 @@
 ln(%22
-Finished
+Done
 !%22);

Update compilation proccess messages