// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import java.io.*;
import java.util.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.dfa.*;
import org.antlr.v4.runtime.atn.*;

class ParsingResult {
  public int numberOfFileArguments;
  public int numberOfFailures;
}

class DartErrorListener implements ANTLRErrorListener {
  public void reportAmbiguity(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      boolean exact,
      BitSet ambigAlts,
      ATNConfigSet configs) {}

  public void reportAttemptingFullContext(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      BitSet conflictingAlts,
      ATNConfigSet configs) {}

  public void reportContextSensitivity(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      int prediction,
      ATNConfigSet configs) {}

  public void syntaxError(
      Recognizer<?,?> recognizer,
      Object offendingSymbol,
      int line,
      int charPositionInLine,
      String msg,
      RecognitionException e) {
    if (!DartParser.errorHasOccurred) DartParser.prepareForErrors();
  }
}

/// Class for `main` which will parse files given as command line arguments.
public class SpecParser {
  private static void normalExit() {
    // Terminate with exit code indicating normal termination.
    System.exit(0);
  }

  private static void compileTimeErrorExit() {
    // Terminate with exit code indicating a parse error.
    System.exit(245);
  }

  private static void helpAndExit() {
    System.err.println("Expected arguments: [--verbose] <file>...");
    normalExit();
  }

  /// Receive command lines from standard input and produce feedback about
  /// the outcome on standard output and standard error, as expected by
  /// tools/test.py when running with `--batch`.
  public static void runAsBatch() throws IOException, RecognitionException {
    ParsingResult result = new ParsingResult();
    long startTime = System.currentTimeMillis();
    InputStreamReader input = new InputStreamReader(System.in);
    BufferedReader bufferedInput = new BufferedReader(input);
    String cmdLine;

    System.out.println(">>> BATCH START");
    while ((cmdLine = bufferedInput.readLine()) != null) {
      if (cmdLine.length() == 0) {
        System.out.println(
            ">>> BATCH END (" +
            (result.numberOfFileArguments - result.numberOfFailures) +
            "/" + result.numberOfFileArguments + ") " +
            (System.currentTimeMillis() - startTime) + "ms");
        if (result.numberOfFailures > 0) compileTimeErrorExit();
        normalExit();
      }

      String[] lineArgs = cmdLine.split("\\s+");
      result = parseFiles(lineArgs);
      // Write stderr end token and flush.
      System.err.println(">>> EOF STDERR");
      String resultPassString =
          result.numberOfFailures == 0 ? "PASS" : "PARSE_FAIL";
      System.out.println(">>> TEST " + resultPassString + " " +
          (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
    }
  }

  /// From [arguments], obey the flags ("--<flag_name>", "-<any>") if known and
  /// ignore them if unknown; treat the remaining [arguments] as file paths and
  /// parse each of them. Return a [ParsingResult] specifying how many files
  /// were parsed, and how many of them failed to parse.
  private static ParsingResult parseFiles(String[] arguments)
      throws IOException, RecognitionException {
    ParsingResult result = new ParsingResult();
    boolean verbose = false;

    result.numberOfFileArguments = arguments.length;
    for (int i = 0; i < arguments.length; i++) {
      String filePath = arguments[i];
      if (filePath.startsWith("-")) {
          result.numberOfFileArguments--;
          if (result.numberOfFileArguments == 0) return result;
          if (filePath.equals("--verbose")) verbose = true;
          if (filePath.equals("--batch")) runAsBatch();
          // Ignore all other flags.
          continue;
      }
      if (verbose) System.err.println("Parsing file: " + filePath);
      DartLexer lexer = new DartLexer(new ANTLRFileStream(filePath));
      DartParser parser = new DartParser(new CommonTokenStream(lexer));
      ANTLRErrorListener errorListener = new DartErrorListener();
      lexer.addErrorListener(errorListener);
      parser.addErrorListener(errorListener);
      if (!parser.parseLibrary(filePath)) result.numberOfFailures++;
    }
    return result;
  }

  public static void main(String[] args) throws Exception {
    if (args.length == 0) helpAndExit();
    ParsingResult result = parseFiles(args);

    if (result.numberOfFileArguments == 0) {
      helpAndExit();
    } else if (result.numberOfFileArguments == 1) {
      if (result.numberOfFailures > 0) {
        System.err.println("Parsing failed");
        compileTimeErrorExit();
      } else {
        System.out.println("Parsing succeeded.");
      }
    } else {
      if (result.numberOfFailures > 0) {
        System.err.println(
            "Parsed " + result.numberOfFileArguments + " files, " +
            result.numberOfFailures + " failed.");
        compileTimeErrorExit();
      } else {
        System.out.println("Parsed " + result.numberOfFileArguments +
            " files successfully.");
      }
    }
  }
}
