// Copyright (c) 2020, 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
import 'package:nnbd_migration/src/front_end/info_builder.dart';
import 'package:nnbd_migration/src/front_end/instrumentation_listener.dart';
import 'package:nnbd_migration/src/front_end/migration_info.dart';
import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
import 'package:nnbd_migration/src/hint_action.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../utilities/test_logger.dart';
import 'analysis_abstract.dart';

class ListenerClient implements DartFixListenerClient {
  @override
  void onException(String detail) {
    fail('Unexpected call to onException($detail)');
  }

  @override
  void onFatalError(String detail) {
    fail('Unexpected call to onFatalError($detail)');
  }

  @override
  void onMessage(String detail) {
    fail('Unexpected call to onMessage($detail)');
  }
}

@reflectiveTest
class NnbdMigrationTestBase extends AbstractAnalysisTest {
  /// The information produced by the InfoBuilder, or `null` if [buildInfo] has
  /// not yet completed.
  Set<UnitInfo> infos;
  NodeMapper nodeMapper;

  /// Assert that some target in [targets] has various properties.
  void assertInTargets(
      {@required Iterable<NavigationTarget> targets,
      int offset,
      int length,
      OffsetMapper offsetMapper}) {
    var failureReasons = [
      if (offset != null) 'offset: $offset',
      if (length != null) 'length: $length',
      if (offsetMapper != null) 'match a custom offset mapper',
    ].join(' and ');
    offsetMapper ??= OffsetMapper.identity;
    expect(targets.any((t) {
      return (offset == null || offset == offsetMapper.map(t.offset)) &&
          (length == null || length == t.length);
    }), isTrue, reason: 'Expected one of $targets to contain $failureReasons');
  }

  /// Assert various properties of the given [region]. If an [offset] is
  /// provided but no [length] is provided, a default length of `1` will be
  /// used.
  void assertRegion(
      {@required RegionInfo region,
      int offset,
      int length,
      Object explanation = anything,
      Object edits = anything,
      Object traces = anything,
      Object kind = NullabilityFixKind.makeTypeNullable}) {
    if (offset != null) {
      expect(region.offset, offset);
      expect(region.length, length ?? 1);
    } else if (length != null) {
      expect(region.length, length);
    }
    expect(region.kind, kind);
    expect(region.edits, edits);
    expect(region.explanation, explanation);
    expect(region.traces, traces);
  }

  /// Asserts various properties of the pair of [regions], `regions[index]` and
  /// `regions[index + 1]`.  The expected offsets and lengths are specified
  /// separately; everything else is asserted using the same matcher.
  void assertRegionPair(List<RegionInfo> regions, int index,
      {int offset1,
      int length1,
      int offset2,
      int length2,
      Object explanation = anything,
      Object edits = anything,
      Object traces = anything,
      Object kind = anything}) {
    assertRegion(
        region: regions[index],
        offset: offset1,
        length: length1,
        explanation: explanation,
        edits: edits,
        traces: traces,
        kind: kind);
    assertRegion(
        region: regions[index + 1],
        offset: offset2,
        length: length2,
        explanation: explanation,
        edits: edits,
        traces: traces,
        kind: kind);
  }

  void assertTraceEntry(UnitInfo unit, TraceEntryInfo entryInfo,
      String function, int offset, Object descriptionMatcher,
      {Set<HintActionKind> hintActions}) {
    if (offset == null) {
      expect(entryInfo.target, isNull);
    } else {
      assert(offset >= 0);
      var lineInfo = LineInfo.fromContent(unit.content);
      var expectedLocation = lineInfo.getLocation(offset);
      expect(entryInfo.target.filePath, unit.path);
      expect(entryInfo.target.line, expectedLocation.lineNumber);
      expect(unit.offsetMapper.map(entryInfo.target.offset), offset);
    }
    expect(entryInfo.function, function);
    expect(entryInfo.description, descriptionMatcher);
    if (hintActions != null) {
      assertTraceHintActions(unit, entryInfo, hintActions, offset);
    }
  }

  void assertTraceHintActions(UnitInfo unit, TraceEntryInfo traceEntry,
      Set<HintActionKind> expectedHints, int nodeOffset) {
    final actionsByKind = Map<HintActionKind, HintAction>.fromIterables(
        traceEntry.hintActions.map((action) => action.kind),
        traceEntry.hintActions);
    expect(actionsByKind, hasLength(expectedHints.length));
    for (final expectedHint in expectedHints) {
      final action = actionsByKind[expectedHint];
      expect(action, isNotNull);
      final node = nodeMapper.nodeForId(action.nodeId);
      expect(node, isNotNull);
      expect(unit.offsetMapper.map(node.codeReference.offset), nodeOffset);
    }
  }

  /// Uses the InfoBuilder to build information for [testFile].
  ///
  /// The information is stored in [infos].
  Future<void> buildInfo(
      {bool removeViaComments = true, bool warnOnWeakCode = false}) async {
    var includedRoot = resourceProvider.pathContext.dirname(testFile);
    await _buildMigrationInfo([testFile],
        includedRoot: includedRoot,
        shouldBeMigratedFunction: (String path) => true,
        pathsToProcess: [testFile],
        removeViaComments: removeViaComments,
        warnOnWeakCode: warnOnWeakCode);
  }

  /// Uses the InfoBuilder to build information for a single test file.
  ///
  /// Asserts that [originalContent] is migrated to [migratedContent]. Returns
  /// the singular UnitInfo which was built.
  Future<UnitInfo> buildInfoForSingleTestFile(String originalContent,
      {@required String migratedContent,
      bool removeViaComments = true,
      bool warnOnWeakCode = false}) async {
    addTestFile(originalContent);
    await buildInfo(
        removeViaComments: removeViaComments, warnOnWeakCode: warnOnWeakCode);
    // Ignore info for dart:core.
    var filteredInfos = [
      for (var info in infos)
        if (!info.path.contains('core.dart')) info
    ];
    expect(filteredInfos, hasLength(1));
    var unit = filteredInfos[0];
    expect(unit.path, testFile);
    expect(unit.content, migratedContent);
    return unit;
  }

  /// Uses the [InfoBuilder] to build information for test files.
  ///
  /// Returns the singular [UnitInfo] which was built.
  Future<List<UnitInfo>> buildInfoForTestFiles(Map<String, String> files,
      {@required String includedRoot,
      bool Function(String) shouldBeMigratedFunction,
      Iterable<String> pathsToProcess}) async {
    shouldBeMigratedFunction ??= (String path) => true;
    var testPaths = <String>[];
    files.forEach((String path, String content) {
      newFile(path, content: content);
      testPaths.add(path);
    });
    pathsToProcess ??= testPaths;
    await _buildMigrationInfo(testPaths,
        includedRoot: includedRoot,
        shouldBeMigratedFunction: shouldBeMigratedFunction,
        pathsToProcess: pathsToProcess);
    // Ignore info for dart:core.
    var filteredInfos = [
      for (var info in infos)
        if (!info.path.contains('core.dart')) info
    ];
    return filteredInfos;
  }

  void setUp() {
    super.setUp();
    nodeMapper = SimpleNodeMapper();
  }

  /// Uses the InfoBuilder to build information for files at [testPaths], which
  /// should all share a common parent directory, [includedRoot].
  Future<void> _buildMigrationInfo(Iterable<String> testPaths,
      {@required String includedRoot,
      @required bool Function(String) shouldBeMigratedFunction,
      @required Iterable<String> pathsToProcess,
      bool removeViaComments = true,
      bool warnOnWeakCode = false}) async {
    // Compute the analysis results.
    var server = DriverProviderImpl(resourceProvider, driver.analysisContext);
    // Run the migration engine.
    var listener = DartFixListener(server, ListenerClient());
    var instrumentationListener = InstrumentationListener();
    var adapter = NullabilityMigrationAdapter(listener);
    var migration = NullabilityMigration(adapter, getLineInfo,
        permissive: false,
        instrumentation: instrumentationListener,
        removeViaComments: removeViaComments,
        warnOnWeakCode: warnOnWeakCode);
    Future<void> _forEachPath(
        void Function(ResolvedUnitResult) callback) async {
      for (var testPath in testPaths) {
        var result = await driver.currentSession.getResolvedUnit2(testPath)
            as ResolvedUnitResult;
        callback(result);
      }
    }

    await _forEachPath(migration.prepareInput);
    expect(migration.unmigratedDependencies, isEmpty);
    await _forEachPath(migration.processInput);
    await _forEachPath(migration.finalizeInput);
    migration.finish();
    // Build the migration info.
    var info = instrumentationListener.data;
    var logger = TestLogger(false);
    var builder = InfoBuilder(
        resourceProvider,
        includedRoot,
        info,
        listener,
        migration,
        nodeMapper,
        logger,
        shouldBeMigratedFunction,
        pathsToProcess);
    infos = await builder.explainMigration();
  }
}
