package grammar;

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;

public class Main {
   public static void main(String[] arss)
   {
      // Example Progress code
      String code = """
DO:
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
END.



DO:
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".
MESSAGE "HELLO".





END.
""";

      // Step 1: CharStream from string
      CharStream input = CharStreams.fromString(code);

      // Step 2: Lexer
      ProgressLexer lexer = new ProgressLexer(input);

      // Step 3: Token stream
      CommonTokenStream tokens = new CommonTokenStream(lexer);

      // Step 4: Parser
      ProgressParser parser = new ProgressParser(tokens);

      // Step 5: Parse using entry rule
      ProgressParser.ProgramContext tree = parser.program();
      var foldingRanges =new FoldingRangeCollectorParserVisitor().visit(tree);

      System.out.println("done");
   }
}

// Here I attempted to implement a different way of code completion

//   {
//      ProgressLexer lexer = new ProgressLexer(CharStreams.fromString("mess-"));
//      ATN atn = lexer.getATN();
//
//      // Start at the beginning of DEFAULT_MODE
//      ATNState start = atn.modeToStartState.get(Lexer.DEFAULT_MODE);
//
//      // Consume the prefix char by char
//      Set<ATNState> currentStates = new HashSet<>();
//      currentStates.add(start);
//      currentStates = epsilonClosure(currentStates);
//      for (char c : "scoped-".toCharArray()) {
//         Set<ATNState> nextStates = new HashSet<>();
//         for (ATNState state : currentStates) {
//            for (Transition t : state.getTransitions()) {
//               if (t instanceof AtomTransition atom && atom.label().contains(c)) {
//                  nextStates.add(t.target);
//               } else if (t instanceof RangeTransition range && c >= range.from && c <= range.to) {
//                  nextStates.add(t.target);
//               } else if (t instanceof SetTransition set && set.set.contains(c)) {
//                  nextStates.add(t.target);
//               }
//            }
//         }
//         currentStates = epsilonClosure(nextStates);
//      }
//
//      // Now we’re at the state(s) after consuming the prefix
//      // Look ahead: what tokens are still possible?
//      Set<Integer> possibleTokens = new HashSet<>();
//      for (ATNState state : currentStates) {
//         collectPossibleTokens(state, possibleTokens);
//      }
//
//      // Print results
//      for (int type : possibleTokens) {
//         String name = lexer.getVocabulary().getSymbolicName(type);
//         System.out.println(" could be part of token: " + name);
//      }
//   }
//   static Set<ATNState> epsilonClosure(Set<ATNState> states) {
//      Set<ATNState> closure = new HashSet<>(states);
//      Stack<ATNState> stack = new Stack<>();
//      stack.addAll(states);
//
//      while (!stack.isEmpty()) {
//         ATNState state = stack.pop();
//         for (Transition t : state.getTransitions()) {
//            if (t.getSerializationType() == Transition.EPSILON && !closure.contains(t.target)) {
//               closure.add(t.target);
//               stack.push(t.target);
//            }
//         }
//      }
//
//      return closure;
//   }
//
//   private static void collectPossibleTokens(ATNState state, Set<Integer> tokens) {
//      Stack<ATNState> stack = new Stack<>();
//      Set<ATNState> visited = new HashSet<>();
//      stack.push(state);
//
//      while (!stack.isEmpty()) {
//         ATNState currentState = stack.pop();
//
//         if (visited.contains(currentState)) {
//            continue;
//         }
//         visited.add(currentState);
//
//         // A RuleStopState indicates the end of a token definition
//         if (currentState instanceof RuleStopState ruleStopState) {
//            tokens.add(ruleStopState.ruleIndex);
//            continue; // Stop this path, as a full token has been found
//         }
//
//         // Traverse all transitions, including epsilons and rule transitions
//         for (Transition t : currentState.getTransitions()) {
//            stack.push(t.target);
//         }
//      }
//   }
//}
