package generator;

import util.State;
import java.util.List;
import java.util.ArrayList;

public class BigFstGenerator {

    private StringBuffer strBuff;

    public BigFstGenerator() {
    }

    public StringBuffer compute(State initState, String className) {
        strBuff = new StringBuffer();
        System.out.println("[FstGenerator] Transforming Fst to a java class");
        append("package generated;");

        append("public class " + className + " {");

        appendWithTab("public static float compute(int[] token) {", 1);

        appendWithTab("int pos=0;", 2);
        appendWithTab("float result=0f;", 2);
        appendWithTab("return state_" + initState.getId() + "(token, pos, result);", 2);

        appendWithTab("}", 1);

        List<State> doneStates = new ArrayList<>();
        generateCases(initState, doneStates);

        append("}");
        System.out.println("[FstGenerator] Successfully transformed fst to " + className + ".java");
        return strBuff;
    }


    private void generateCases(State currentState, List<State> doneStates) {
        List<State> nextStates = new ArrayList<>();

        append("\n\tprivate static float state_" + currentState.getId() +
                "(int[] token, int pos, float result) {");

        generateTokenLengthTest(2);
        appendWithTab("switch(token[pos++]) {", 2);
        for (int i = 0; i < currentState.getNumArcs(); i++) {
            appendWithTab("case " + currentState.getArc(i).getIlabel()  + ":", 3);

            if( currentState.getArc(i).getNextState().getNumArcs() <= 0) {
                appendWithTab("return (pos!=token.length) ? -1 : result;", 4);
                continue;
            }

            if (currentState.getArc(i).getWeight() != 0f) {
                appendWithTab("result+=" + currentState.getArc(i).getWeight() + "f;", 4);
            }

            appendWithTab("return state_" + currentState.getArc(i).getNextState().getId() +
                    "(token, pos, result);", 4);

            nextStates.add(currentState.getArc(i).getNextState());
        }
        appendWithTab("default:", 3);
        appendWithTab("return -1;", 4);
        appendWithTab("}", 2);
        appendWithTab("}", 1);

        for (State next: nextStates) {
            if (doneStates.contains(next)) {
                continue;
            }
            generateCases(next, doneStates);
            doneStates.add(next);
        }
    }

    private void generateTokenLengthTest(int tab) {
        appendWithTab("if(pos>=token.length) {return -1;}", tab);
    }

    private void append(String strToAppend) {
        strBuff.append(strToAppend);
        strBuff.append("\n");
    }

    private void appendWithTab(String strToAppend, int numberOfTab) {
        for (int i = 0; i < numberOfTab; i++) {
            strBuff.append("\t");
        }
        strBuff.append(strToAppend);
        strBuff.append("\n");
    }

}

@@ -1517,10 +1517,10 @@
   if
-(
  
+(
 curr
@@ -1545,34 +1545,18 @@
 .get
-NextState().getNumArcs() %3C
+Olabel() !
 = 0)
@@ -1595,46 +1595,57 @@
 (%22re
-turn (pos!=token.length) ? -1 : result
+sult+=%22 + currentState.getArc(i).getOlabel() + %22f
 ;%22, 
@@ -1652,32 +1652,39 @@
 4);%0A        
+    %7D%0A%0A
         
 continue;%0A  
@@ -1667,32 +1667,162 @@
  %7D%0A%0A        
-continue
+    if (currentState.getArc(i).getNextState().isFinalState()) %7B%0A                appendWithTab(%22if(pos==token.length) %7Breturn result;%7D%22, 4)
 ;%0A          
@@ -1832,34 +1832,34 @@
 %0A%0A            if
- 
 (
+ 
 currentState.get
@@ -1872,22 +1872,37 @@
 .get
-Weight() !
+NextState().getNumArcs() %3C
 = 0
-f
 ) %7B%0A
@@ -1938,63 +1938,78 @@
 (%22re
-sult+=%22 + currentState.getArc(i).getWeight() + %22f;%22, 4)
+turn (pos!=token.length) ? -1 : result;%22, 4);%0A                continue
 ;%0A  

Handle final state with arcs in BigFstGenerator