// Copyright (c) 2021, 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';

import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer_testing/package_root.dart';

class BulkFixDetails {
  Future<Map<String, CorrectionDetails>> collectOverrides() async {
    var overrideDetails = <String, CorrectionDetails>{};

    var pkgRootPath = PhysicalResourceProvider.INSTANCE.pathContext.normalize(
      packageRoot,
    );
    var directory = Directory(
      '$pkgRootPath/analysis_server/lib/src/services/correction/dart',
    );
    var collection = AnalysisContextCollection(
      includedPaths: [directory.absolute.path],
      resourceProvider: PhysicalResourceProvider.INSTANCE,
    );
    var context = collection.contexts[0];

    for (var file in directory.listSync()) {
      var resolvedFile =
          await context.currentSession.getResolvedUnit(file.absolute.path)
              as ResolvedUnitResult;
      for (var classDecl
          in resolvedFile.unit.declarations.whereType<ClassDeclaration>()) {
        var classElement = classDecl.declaredFragment?.element;
        if (classElement != null &&
            classElement.allSupertypes.any(
              (element) => element.element.name == 'CorrectionProducer',
            )) {
          var correctionName = classDecl.namePart.typeName.lexeme;

          for (var method
              in classDecl.body.members.whereType<MethodDeclaration>()) {
            if (method.name.lexeme == 'canBeAppliedInBulk') {
              var hasComment =
                  method.returnType?.beginToken.precedingComments != null;

              var body = method.body;
              if (body is BlockFunctionBody) {
                var last = body.block.statements.last;
                if (last is ReturnStatement) {
                  var canBeBulkApplied =
                      (last.expression as BooleanLiteral).value;
                  overrideDetails[correctionName] = CorrectionDetails(
                    canBeBulkApplied: canBeBulkApplied,
                    hasComment: hasComment,
                  );
                }
              } else if (body is ExpressionFunctionBody) {
                var expression = body.expression;
                var canBeBulkApplied = (expression as BooleanLiteral).value;
                overrideDetails[correctionName] = CorrectionDetails(
                  canBeBulkApplied: canBeBulkApplied,
                  hasComment: hasComment,
                );
              }
            }
          }
        }
      }
    }
    return overrideDetails;
  }
}

class CorrectionDetails {
  bool canBeBulkApplied;
  bool hasComment;

  new({required this.canBeBulkApplied, required this.hasComment});
}
