package metalexer.jflex;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import metalexer.jflex.ReflectionHelper.MetaLexerWrapper;
import metalexer.jflex.ReflectionHelper.PipeWrapper;

public class ComponentMetaScannerTestTool {

    public static void main(String[] args) throws IOException {
        if (args.length != 3) {
            System.err.println("Usage: java metalexer.jflex.ComponentScannerTestTool {groupName} {layoutName} {basename}");
            System.exit(1);
        }

        String groupName = args[0];
        String layoutName = args[1];
        String baseName = args[2];

        MetaScannerPropHelper propHelper = new MetaScannerPropHelper(groupName, layoutName);
        String inFileName = baseName + ".in";
        String outFileName = baseName + ".out";

        List<Character> input = new ArrayList<Character>();
        BufferedReader inReader = new BufferedReader(new FileReader(inFileName));
        while(inReader.ready()) {
            String line = inReader.readLine();
            input.add(propHelper.getMacroValue(line));
        }
        inReader.close();
        
        List<List<Integer>> actualOutput = getActualOutput(input);
        PrintWriter outWriter = new PrintWriter(new FileWriter(outFileName));
        for(List<Integer> line : actualOutput) {
            boolean first = true;
            for(Integer val : line) {
                if(!first) {
                    outWriter.print(" ");
                }
                outWriter.print(propHelper.getEmbeddingName(val));
                first = false;
            }
            outWriter.println();
        }
        outWriter.close();
    }

    public static List<List<Integer>> getActualOutput(List<Character> input) {
        PipeWrapper pipe = new PipeWrapper("test.jflex.metalexer.ComponentScanner$Pipe");
        final MetaLexerWrapper metalexer = new MetaLexerWrapper("test.jflex.metalexer.ComponentScanner_Meta", pipe);
        Thread metaLexerThread = new Thread(new Runnable() {
            public void run() {
                metalexer.start();
            }}, "MetaLexerThread");


        metaLexerThread.start();

        List<List<Integer>> actualOutput = new ArrayList<List<Integer>>();
        for(int i = 0; i < input.size(); i++) {
            char ch = input.get(i);
            pipe.write(ch);
            Integer transition = metalexer.checkForTransition();
            List<Integer> line = new ArrayList<Integer>();
            if(transition != null) {
                line.add(transition);
            }
            actualOutput.add(line);
        }

        pipe.writeFinal('\n');

        Integer transition = metalexer.checkForTransition();
        if(transition != null) {
            throw new IllegalStateException("Extraneous trailing output " + transition);
        }

        try {
            metaLexerThread.join();
        } catch (InterruptedException e) {
            throw new RuntimeException("Failed to join metalexer thread", e);
        }

        return actualOutput;
    }
}
