// 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 'dart:io' as io;

import 'package:analysis_tool/package_root.dart' as package_root;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:yaml/yaml.dart';

import '../../generated/parser_fasta_test.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AbstractRecoveryTest);
  });
}

@reflectiveTest
class AbstractRecoveryTest extends FastaParserTestCase {
  /// Given the path to the file containing the declaration of the fasta Parser,
  /// return a set containing the names of all the messages and templates that
  /// are referenced (presumably because they are being generated) within that
  /// file.
  Set<String> getGeneratedNames(String parserPath) {
    String content = io.File(parserPath).readAsStringSync();
    CompilationUnit unit = parseCompilationUnit(content);
    expect(unit, isNotNull);
    GeneratedCodesVisitor visitor = GeneratedCodesVisitor();
    unit.accept(visitor);
    return visitor.generatedNames;
  }

  /// Given the path to the file 'messages.yaml', return a list of the top-level
  /// keys defined in that file that define an 'analyzerCode'.
  List<String> getMappedCodes(String messagesPath) {
    String content = io.File(messagesPath).readAsStringSync();
    YamlDocument document = loadYamlDocument(content);
    expect(document, isNotNull);
    Set<String> codes = <String>{};
    YamlNode contents = document.contents;
    if (contents is YamlMap) {
      for (String name in contents.keys) {
        Object value = contents[name];
        if (value is YamlMap) {
          if (value['analyzerCode'] != null) {
            codes.add(name);
          }
        }
      }
    }
    return codes.toList();
  }

  /// Given the path to the file 'messages.yaml', return a list of the analyzer
  /// codes defined in that file.
  List<String> getReferencedCodes(String messagesPath) {
    String content = io.File(messagesPath).readAsStringSync();
    YamlDocument document = loadYamlDocument(content);
    expect(document, isNotNull);
    Set<String> codes = <String>{};
    YamlNode contents = document.contents;
    if (contents is YamlMap) {
      for (String name in contents.keys) {
        Object value = contents[name];
        if (value is YamlMap) {
          String code = value['analyzerCode']?.toString();
          if (code != null) {
            codes.add(code);
          }
        }
      }
    }
    return codes.toList();
  }

  /// Given the path to the file containing the declaration of the AstBuilder,
  /// return a list of the analyzer codes that are translated by the builder.
  List<String> getTranslatedCodes(String astBuilderPath) {
    String content = io.File(astBuilderPath).readAsStringSync();
    CompilationUnit unit = parseCompilationUnit(content);
    ClassDeclaration astBuilder = unit.declarations[0];
    expect(astBuilder, isNotNull);
    MethodDeclaration method = astBuilder.members.firstWhere(
        (x) => x is MethodDeclaration && x.name.name == 'reportMessage',
        orElse: () => null);
    expect(method, isNotNull);
    SwitchStatement statement = (method.body as BlockFunctionBody)
        .block
        .statements
        .firstWhere((x) => x is SwitchStatement, orElse: () => null);
    expect(statement, isNotNull);
    List<String> codes = <String>[];
    for (SwitchMember member in statement.members) {
      if (member is SwitchCase) {
        codes.add((member.expression as StringLiteral).stringValue);
      }
    }
    return codes;
  }

  @failingTest
  test_mappedMessageCoverage() {
    String frontEndPath = path.join(package_root.packageRoot, 'front_end');
    String parserPath =
        path.join(frontEndPath, 'lib', 'src', 'fasta', 'parser', 'parser.dart');
    Set<String> generatedNames = getGeneratedNames(parserPath);

    String messagesPath = path.join(frontEndPath, 'messages.yaml');
    List<String> mappedCodes = getMappedCodes(messagesPath);

    generatedNames.removeAll(mappedCodes);
    if (generatedNames.isEmpty) {
      return;
    }
    List<String> sortedNames = generatedNames.toList()..sort();
    StringBuffer buffer = StringBuffer();
    buffer.writeln('Generated parser errors without analyzer codes:');
    for (String name in sortedNames) {
      buffer.write('  ');
      buffer.writeln(name);
    }
    fail(buffer.toString());
  }

  @failingTest
  test_translatedMessageCoverage() {
    String analyzerPath = path.join(package_root.packageRoot, 'analyzer');
    String astBuilderPath =
        path.join(analyzerPath, 'lib', 'src', 'fasta', 'error_converter.dart');
    List<String> translatedCodes = getTranslatedCodes(astBuilderPath);

    String messagesPath =
        path.join(path.dirname(analyzerPath), 'front_end', 'messages.yaml');
    List<String> referencedCodes = getReferencedCodes(messagesPath);

    List<String> untranslated = <String>[];
    for (String referencedCode in referencedCodes) {
      if (!translatedCodes.contains(referencedCode)) {
        untranslated.add(referencedCode);
      }
    }
    StringBuffer buffer = StringBuffer();
    if (untranslated.isNotEmpty) {
      buffer
          .writeln('Analyzer codes used in messages.yaml but not translated:');
      for (String code in untranslated) {
        buffer.write('  ');
        buffer.writeln(code);
      }
      buffer.write(
          'Add a case for these codes to FastaErrorReporter.reportError.');
    }

    List<String> unreferenced = <String>[];
    for (String translatedCode in translatedCodes) {
      if (!referencedCodes.contains(translatedCode)) {
        unreferenced.add(translatedCode);
      }
    }
    if (untranslated.isNotEmpty) {
      if (buffer.isNotEmpty) {
        buffer.writeln();
        buffer.writeln();
      }
      buffer.writeln(
          'Analyzer codes that are translated but not used in messages.yaml:');
      for (String code in unreferenced) {
        buffer.write('  ');
        buffer.writeln(code);
      }
      buffer.write('Remove the cases for these codes from '
          'FastaErrorReporter.reportMessage.');
    }
    if (buffer.isNotEmpty) {
      fail(buffer.toString());
    }
  }
}

/// A visitor that gathers the names of all the message codes that are generated
/// in the visited AST. This assumes that the codes are accessed via the prefix
/// 'fasta'.
class GeneratedCodesVisitor extends RecursiveAstVisitor {
  /// The names of the message codes that are generated in the visited AST.
  Set<String> generatedNames = <String>{};

  @override
  visitPrefixedIdentifier(PrefixedIdentifier node) {
    if (node.prefix.name == 'fasta') {
      String name = node.identifier.name;
      if (name.startsWith('message')) {
        name = name.substring(7);
      } else if (name.startsWith('template')) {
        name = name.substring(8);
      } else {
        return;
      }
      generatedNames.add(name);
    }
  }
}
