// Copyright (c) 2019, 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 'dart:io' show File;
import 'dart:typed_data' show Uint8List;

import 'package:_fe_analyzer_shared/src/parser/parser.dart';
import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart';
import 'package:_fe_analyzer_shared/src/scanner/token.dart';

import 'package:dart_style/dart_style.dart' show DartFormatter;

import 'utils/io_utils.dart' show computeRepoDirUri;

void main(List<String> args) {
  final Uri repoDir = computeRepoDirUri();
  String generated = generateTestListener(repoDir);
  new File.fromUri(computeTestListenerUri(repoDir))
      .writeAsStringSync(generated, flush: true);
}

Uri computeTestListenerUri(Uri repoDir) {
  return repoDir.resolve("pkg/front_end/test/parser_test_listener.dart");
}

String generateTestListener(Uri repoDir) {
  final StringBuffer out = new StringBuffer();
  File f = new File.fromUri(
      repoDir.resolve("pkg/_fe_analyzer_shared/lib/src/parser/listener.dart"));
  List<int> rawBytes = f.readAsBytesSync();

  Uint8List bytes = new Uint8List(rawBytes.length + 1);
  bytes.setRange(0, rawBytes.length, rawBytes);

  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: true);
  Token firstToken = scanner.tokenize();

  out.write(r"""
// Copyright (c) 2019, 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 'package:_fe_analyzer_shared/src/parser/assert.dart';
import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
import 'package:_fe_analyzer_shared/src/parser/constructor_reference_context.dart';
import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
import 'package:_fe_analyzer_shared/src/parser/listener.dart';
import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:front_end/src/fasta/messages.dart';

// THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
// Run this command to update it:
// 'dart pkg/front_end/test/parser_test_listener_creator.dart'

class ParserTestListener implements Listener {
  int indent = 0;
  final StringBuffer sb = new StringBuffer();
  final bool trace;

  ParserTestListener(this.trace);

  String createTrace() {
    List<String> traceLines = StackTrace.current.toString().split("\n");
    for (int i = 0; i < traceLines.length; i++) {
      // Find first one that's not any of the denylisted ones.
      String line = traceLines[i];
      if (line.contains("parser_test_listener.dart:") ||
          line.contains("parser_suite.dart:")) continue;
      return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")"));
    }
    return "N/A";
  }

  void doPrint(String s) {
    String outString = s;
    if (trace) outString += " (${createTrace()})";
    if (outString != "") {
      sb.writeln(("  " * indent) + outString);
    } else {
      sb.writeln("");
    }
  }

  bool checkEof(Token token) {
    if (token.isEof) {
      doPrint("// WARNING: Reporting at eof for $token.");
      return true;
    }
    Token? next = token.next;
    while (next != null && next.offset == token.offset && !next.isEof) {
      next = next.next;
    }
    if (next != null && next.offset == token.offset && next.isEof) {
      doPrint("// WARNING: Reporting at the eof offset for $token.");
      return true;
    }
    return false;
  }

  void seen(Token? token) {}

""");

  ParserCreatorListener listener = new ParserCreatorListener(out);
  ClassMemberParser parser = new ClassMemberParser(listener);
  parser.parseUnit(firstToken);

  out.writeln("}");

  return new DartFormatter().format("$out");
}

class ParserCreatorListener extends Listener {
  final StringSink out;
  bool insideListenerClass = false;
  String? currentMethodName;
  String? latestSeenParameterTypeToken;
  List<String> parameters = [];
  List<String?> parameterTypes = [];

  ParserCreatorListener(this.out);

  @override
  void beginClassDeclaration(Token begin, Token? abstractToken, Token name) {
    if (name.lexeme == "Listener") insideListenerClass = true;
  }

  @override
  void endClassDeclaration(Token beginToken, Token endToken) {
    insideListenerClass = false;
  }

  @override
  void beginMethod(
      DeclarationKind declarationKind,
      Token? externalToken,
      Token? staticToken,
      Token? covariantToken,
      Token? varFinalOrConst,
      Token? getOrSet,
      Token name) {
    currentMethodName = name.lexeme;
  }

  @override
  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
      Token? beginInitializers, Token endToken) {
    if (insideListenerClass) {
      out.writeln("  @override");
      out.write("  ");
      Token token = beginToken;
      Token? latestToken;
      while (true) {
        if (latestToken != null && latestToken.charEnd < token.charOffset) {
          out.write(" ");
        }
        out.write(token.lexeme);
        if ((token is BeginToken &&
                token.type == TokenType.OPEN_CURLY_BRACKET) ||
            token is SimpleToken && token.type == TokenType.FUNCTION) {
          break;
        }
        if (token == endToken) {
          throw token.runtimeType;
        }
        latestToken = token;
        token = token.next!;
      }

      if (token is SimpleToken && token.type == TokenType.FUNCTION) {
        out.write(" null;");
      } else {
        out.write("\n    ");
        if (currentMethodName!.startsWith("end")) {
          out.write("indent--;\n    ");
        }
        for (int i = 0; i < parameterTypes.length; i++) {
          if (parameterTypes[i] == "Token") {
            out.write("seen(${parameters[i]});");
          }
        }
        out.write("doPrint('$currentMethodName(");
        String separator = "";
        for (int i = 0; i < parameters.length; i++) {
          out.write(separator);
          out.write(r"' '$");
          out.write(parameters[i]);
          separator = ", ";
        }
        out.write(")');\n  ");

        if (currentMethodName!.startsWith("begin")) {
          out.write("  indent++;\n  ");
        }

        if (currentMethodName == "handleErrorToken") {
          // It redirects to give an error message, so also do that here.
          out.write("  handleRecoverableError("
              "token.assertionMessage, token, token);");
        } else if (currentMethodName == "handleRecoverableError") {
          // Check for reporting on eof.
          out.write("checkEof(endToken);");
        }

        out.write("}");
      }
      out.write("\n\n");
    }
    parameters.clear();
    parameterTypes.clear();
    currentMethodName = null;
  }

  @override
  void handleNoType(Token lastConsumed) {
    latestSeenParameterTypeToken = null;
  }

  @override
  void handleType(Token beginToken, Token? questionMark) {
    latestSeenParameterTypeToken = beginToken.lexeme;
  }

  @override
  void endFormalParameter(
      Token? thisKeyword,
      Token? superKeyword,
      Token? periodAfterThisOrSuper,
      Token nameToken,
      Token? initializerStart,
      Token? initializerEnd,
      FormalParameterKind kind,
      MemberKind memberKind) {
    parameters.add(nameToken.lexeme);
    parameterTypes.add(latestSeenParameterTypeToken);
  }
}
