// Copyright (c) 2024, 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/dart/analysis/session.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_testing/resource_provider_mixin.dart';
import 'package:meta/meta.dart';
import 'package:test/test.dart';

/// A base test framework for writing tests that resolve a String as Dart source
/// code.
// TODO(srawlins): This is all copied from the `AbstractSingleUnitTest` and
// `AbstractContextTest` classes in the analysis_server package. It is pared
// down as the minimum amount of code needed to run the tests in this package.
class SingleUnitTest with ResourceProviderMixin {
  static final ByteStore _byteStore = MemoryByteStore();

  late String testCode;
  late ParsedUnitResult testParsedResult;
  late ResolvedUnitResult testAnalysisResult;
  late FindNode findNode;

  final Map<String, String> _declaredVariables = {};
  AnalysisContextCollectionImpl? _analysisContextCollection;

  File get testFile => getFile(_testFilePath);

  List<String> get _collectionIncludedPaths => [_workspaceRootPath];

  Folder get _sdkRoot => newFolder('/sdk');

  String get _testFilePath => '$_testPackageLibPath/test.dart';

  String get _testPackageLibPath => '$_testPackageRootPath/lib';

  String get _testPackageRootPath => '$_workspaceRootPath/test';

  String get _workspaceRootPath => '/home';

  void addTestSource(String code) {
    testCode = code;
    newFile(testFile.path, code);
  }

  void changeFile(File file) {
    _contextFor(file).driver.changeFile(file.path);
  }

  Future<ParsedUnitResult> getParsedUnit(File file) async {
    var path = file.path;
    var session = await _sessionFor(file);
    var result = session.getParsedUnit(path) as ParsedUnitResult;

    testParsedResult = result;
    testCode = result.content;
    var testUnit = result.unit;
    findNode = FindNode(testCode, testUnit);
    return result;
  }

  Future<ResolvedUnitResult> getResolvedUnit(File file) async {
    var path = file.path;
    var session = await _sessionFor(file);
    var result = await session.getResolvedUnit(path) as ResolvedUnitResult;

    testAnalysisResult = result;
    testCode = result.content;
    var testUnit = result.unit;

    expect(
      result.diagnostics.where((d) {
        return d.diagnosticCode != diag.deadCode &&
            d.diagnosticCode != diag.unusedCatchClause &&
            d.diagnosticCode != diag.unusedCatchStack &&
            d.diagnosticCode != diag.unusedElement &&
            d.diagnosticCode != diag.unusedField &&
            d.diagnosticCode != diag.unusedImport &&
            d.diagnosticCode != diag.unusedLocalVariable;
      }),
      isEmpty,
    );

    findNode = FindNode(testCode, testUnit);
    return result;
  }

  @override
  File newFile(String path, String content) {
    if (_analysisContextCollection != null && !path.endsWith('.dart')) {
      throw StateError('Only dart files can be changed after analysis.');
    }

    var file = super.newFile(path, content);
    _addAnalyzedFileToDrivers(file);
    return file;
  }

  Future<void> parseTestCode(String code) async {
    addTestSource(code);
    await getParsedUnit(testFile);
  }

  Future<void> resolveTestCode(String code) async {
    addTestSource(code);
    await getResolvedUnit(testFile);
  }

  @mustCallSuper
  void setUp() {
    createMockSdk(resourceProvider: resourceProvider, root: _sdkRoot);
  }

  @mustCallSuper
  Future<void> tearDown() async {
    AnalysisEngine.instance.clearCaches();
    await _analysisContextCollection?.dispose();
  }

  void _addAnalyzedFilesToDrivers() {
    for (var analysisContext in _analysisContextCollection!.contexts) {
      for (var path in analysisContext.contextRoot.analyzedFiles()) {
        if (file_paths.isDart(resourceProvider.pathContext, path)) {
          analysisContext.driver.addFile(path);
        }
      }
    }
  }

  void _addAnalyzedFileToDrivers(File file) {
    var collection = _analysisContextCollection;
    if (collection != null) {
      for (var analysisContext in collection.contexts) {
        if (analysisContext.contextRoot.isAnalyzed(file.path)) {
          analysisContext.driver.addFile(file.path);
        }
      }
    }
  }

  DriverBasedAnalysisContext _contextFor(File file) {
    _createAnalysisContexts();
    return _analysisContextCollection!.contextFor(file.path);
  }

  /// Creates all analysis contexts in [_collectionIncludedPaths].
  void _createAnalysisContexts() {
    if (_analysisContextCollection != null) {
      return;
    }

    _analysisContextCollection = AnalysisContextCollectionImpl(
      byteStore: _byteStore,
      declaredVariables: _declaredVariables,
      enableIndex: true,
      includedPaths: _collectionIncludedPaths.map(convertPath).toList(),
      resourceProvider: resourceProvider,
      sdkPath: _sdkRoot.path,
      withFineDependencies: true,
    );

    _addAnalyzedFilesToDrivers();
  }

  Future<AnalysisSession> _sessionFor(File file) async {
    var analysisContext = _contextFor(file);
    await analysisContext.applyPendingFileChanges();
    return analysisContext.currentSession;
  }
}
