// 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/error/codes.g.dart';
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.errors.where((error) {
      return error.errorCode != WarningCode.DEAD_CODE &&
          error.errorCode != WarningCode.UNUSED_CATCH_CLAUSE &&
          error.errorCode != WarningCode.UNUSED_CATCH_STACK &&
          error.errorCode != WarningCode.UNUSED_ELEMENT &&
          error.errorCode != WarningCode.UNUSED_FIELD &&
          error.errorCode != WarningCode.UNUSED_IMPORT &&
          error.errorCode != WarningCode.UNUSED_LOCAL_VARIABLE;
    }), 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,
    );

    _addAnalyzedFilesToDrivers();
  }

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