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

import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart'
    as macro;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/kernel_compilation_service.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer/src/util/uri.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as package_path;
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../util/feature_sets.dart';
import 'test_strategies.dart';

/// A base for testing building elements.
@reflectiveTest
abstract class ElementsBaseTest with ResourceProviderMixin {
  /// The shared SDK bundle, computed once and shared among test invocations.
  static _SdkBundle? _sdkBundle;

  /// The instance of macro executor that is used for all macros.
  final macro.MultiMacroExecutor _macroExecutor = macro.MultiMacroExecutor();

  /// The set of features enabled in this test.
  FeatureSet featureSet = FeatureSets.latestWithExperiments;

  DeclaredVariables declaredVariables = DeclaredVariables();
  late final SourceFactory sourceFactory;
  late final FolderBasedDartSdk sdk;

  ElementsBaseTest() {
    var sdkRoot = newFolder('/sdk');
    createMockSdk(
      resourceProvider: resourceProvider,
      root: sdkRoot,
    );
    sdk = FolderBasedDartSdk(resourceProvider, sdkRoot);
  }

  /// We need to test both cases - when we keep linking libraries (happens for
  /// new or invalidated libraries), and when we load libraries from bytes
  /// (happens internally in Blaze or when we have cached summaries).
  bool get keepLinkingLibraries;

  Future<_SdkBundle> get sdkBundle async {
    if (_sdkBundle != null) {
      return _sdkBundle!;
    }

    var featureSet = FeatureSet.latestLanguageVersion();
    var inputLibraries = <LinkInputLibrary>[];
    for (var sdkLibrary in sdk.sdkLibraries) {
      var source = sourceFactory.resolveUri(null, sdkLibrary.shortName)!;
      var text = getFile(source.fullName).readAsStringSync();
      var unit = parseText(source, text, featureSet);

      var inputUnits = <LinkInputUnit>[];
      _addLibraryUnits(source, unit, inputUnits, featureSet);
      inputLibraries.add(
        LinkInputLibrary(
          source: source,
          units: inputUnits,
        ),
      );
    }

    var elementFactory = LinkedElementFactory(
      AnalysisContextImpl(
        SynchronousSession(
          AnalysisOptionsImpl(),
          declaredVariables,
        ),
        sourceFactory,
      ),
      _AnalysisSessionForLinking(),
      Reference.root(),
    );

    var sdkLinkResult = await link(elementFactory, inputLibraries);

    return _sdkBundle = _SdkBundle(
      resolutionBytes: sdkLinkResult.resolutionBytes,
    );
  }

  String get testFilePath => '$testPackageLibPath/test.dart';

  String get testPackageLibPath => '$testPackageRootPath/lib';

  String get testPackageRootPath => '$workspaceRootPath/test';

  String get workspaceRootPath => '/home';

  void addSource(String path, String contents) {
    newFile(path, contents);
  }

  Future<LibraryElementImpl> buildLibrary(
    String text, {
    bool allowErrors = false,
    bool dumpSummaries = false,
    List<Set<String>>? preBuildSequence,
  }) async {
    _buildSourceFactory();

    var testFile = newFile(testFilePath, text);
    var testUri = sourceFactory.pathToUri(testFile.path)!;
    var testSource = sourceFactory.forUri2(testUri)!;

    var inputLibraries = <LinkInputLibrary>[];
    _addNonDartLibraries({}, inputLibraries, testSource);

    var unitsInformativeBytes = <Uri, Uint8List>{};
    for (var inputLibrary in inputLibraries) {
      for (var inputUnit in inputLibrary.units) {
        var informativeBytes = writeUnitInformative(inputUnit.unit);
        unitsInformativeBytes[inputUnit.uri] = informativeBytes;
      }
    }

    var analysisContext = AnalysisContextImpl(
      SynchronousSession(
        AnalysisOptionsImpl()..contextFeatures = featureSet,
        declaredVariables,
      ),
      sourceFactory,
    );

    var elementFactory = LinkedElementFactory(
      analysisContext,
      _AnalysisSessionForLinking(),
      Reference.root(),
    );
    elementFactory.addBundle(
      BundleReader(
        elementFactory: elementFactory,
        unitsInformativeBytes: {},
        resolutionBytes: (await sdkBundle).resolutionBytes,
      ),
    );

    await _linkConfiguredLibraries(
      elementFactory,
      inputLibraries,
      preBuildSequence,
    );

    var linkResult = await link(
      elementFactory,
      inputLibraries,
      macroExecutor: _macroExecutor,
    );

    for (var macroUnit in linkResult.macroGeneratedUnits) {
      var informativeBytes = writeUnitInformative(macroUnit.unit);
      unitsInformativeBytes[macroUnit.uri] = informativeBytes;
    }

    if (!keepLinkingLibraries) {
      elementFactory.removeBundle(
        inputLibraries.map((e) => e.uriStr).toSet(),
      );
      elementFactory.addBundle(
        BundleReader(
          elementFactory: elementFactory,
          unitsInformativeBytes: unitsInformativeBytes,
          resolutionBytes: linkResult.resolutionBytes,
        ),
      );
    }

    return elementFactory.libraryOfUri2('$testUri');
  }

  @mustCallSuper
  Future<void> setUp() async {}

  @mustCallSuper
  Future<void> tearDown() async {
    await _macroExecutor.close();
    KernelCompilationService.disposeDelayed(
      const Duration(milliseconds: 100),
    );
  }

  void _addLibraryUnits(
    Source definingSource,
    CompilationUnit definingUnit,
    List<LinkInputUnit> units,
    FeatureSet featureSet,
  ) {
    units.add(
      LinkInputUnit(
        partDirectiveIndex: null,
        source: definingSource,
        isSynthetic: false,
        unit: definingUnit,
      ),
    );

    var partDirectiveIndex = -1;
    for (var directive in definingUnit.directives) {
      if (directive is PartDirective) {
        ++partDirectiveIndex;
        var relativeUriStr = directive.uri.stringValue;

        var partSource = sourceFactory.resolveUri(
          definingSource,
          relativeUriStr,
        );

        if (partSource != null) {
          var text = _readSafely(partSource.fullName);
          var unit = parseText(partSource, text, featureSet);
          units.add(
            LinkInputUnit(
              partDirectiveIndex: partDirectiveIndex,
              partUriStr: relativeUriStr,
              source: partSource,
              isSynthetic: false,
              unit: unit,
            ),
          );
        }
      }
    }
  }

  void _addNonDartLibraries(
    Set<Source> addedLibraries,
    List<LinkInputLibrary> libraries,
    Source source,
  ) {
    if (source.uri.isScheme('dart') || !addedLibraries.add(source)) {
      return;
    }

    var text = _readSafely(source.fullName);
    var unit = parseText(source, text, featureSet);

    var units = <LinkInputUnit>[];
    _addLibraryUnits(source, unit, units, featureSet);
    libraries.add(
      LinkInputLibrary(
        source: source,
        units: units,
      ),
    );

    void addRelativeUriStr(StringLiteral uriNode) {
      var relativeUriStr = uriNode.stringValue;
      if (relativeUriStr == null) {
        return;
      }

      Uri relativeUri;
      try {
        relativeUri = Uri.parse(relativeUriStr);
      } on FormatException {
        return;
      }

      var absoluteUri = resolveRelativeUri(source.uri, relativeUri);
      var rewrittenUri = rewriteToCanonicalUri(sourceFactory, absoluteUri);
      if (rewrittenUri == null) {
        return;
      }

      var uriSource = sourceFactory.forUri2(rewrittenUri);
      if (uriSource == null) {
        return;
      }

      _addNonDartLibraries(addedLibraries, libraries, uriSource);
    }

    for (var directive in unit.directives) {
      if (directive is NamespaceDirective) {
        addRelativeUriStr(directive.uri);
        for (var configuration in directive.configurations) {
          addRelativeUriStr(configuration.uri);
        }
      }
    }
  }

  /// If there are any [macroLibraries], build the kernel and prepare for
  /// execution.
  Future<void> _buildMacroLibraries(
    LinkedElementFactory elementFactory,
    List<MacroLibrary> macroLibraries,
  ) async {
    if (macroLibraries.isEmpty) {
      return;
    }

    final macroKernelBuilder = const MacroKernelBuilder();
    var macroKernelBytes = await macroKernelBuilder.build(
      fileSystem: _MacroFileSystem(resourceProvider),
      libraries: macroLibraries,
    );

    var bundleMacroExecutor = BundleMacroExecutor(
      macroExecutor: _macroExecutor,
      kernelBytes: macroKernelBytes,
      libraries: macroLibraries.map((e) => e.uri).toSet(),
    );

    for (var macroLibrary in macroLibraries) {
      var uriStr = macroLibrary.uriStr;
      var element = elementFactory.libraryOfUri2(uriStr);
      element.bundleMacroExecutor = bundleMacroExecutor;
    }
  }

  void _buildSourceFactory() {
    final packages = parsePackageConfigJsonFile(
      resourceProvider,
      getFile('$testPackageRootPath/.dart_tool/package_config.json'),
    );

    // TODO(scheglov) Can we use Packages instead?
    final packageMap = <String, List<Folder>>{};
    for (final package in packages.packages) {
      packageMap[package.name] = [package.libFolder];
    }

    sourceFactory = SourceFactory([
      DartUriResolver(sdk),
      PackageMapUriResolver(resourceProvider, packageMap),
      ResourceUriResolver(resourceProvider),
    ]);
  }

  /// If there are any libraries in the [uriStrSetList], link these subsets
  /// of [inputLibraries] (and remove from it), build macro kernels, prepare
  /// for executing macros.
  Future<void> _linkConfiguredLibraries(
    LinkedElementFactory elementFactory,
    List<LinkInputLibrary> inputLibraries,
    List<Set<String>>? uriStrSetList,
  ) async {
    if (uriStrSetList == null) {
      return;
    }

    for (var uriStrSet in uriStrSetList) {
      var cycleInputLibraries = <LinkInputLibrary>[];
      var macroLibraries = <MacroLibrary>[];
      for (var inputLibrary in inputLibraries) {
        if (uriStrSet.contains(inputLibrary.uriStr)) {
          cycleInputLibraries.add(inputLibrary);
          _addMacroLibrary(macroLibraries, inputLibrary);
        }
      }

      await link(
        elementFactory,
        cycleInputLibraries,
        macroExecutor: _macroExecutor,
      );

      await _buildMacroLibraries(elementFactory, macroLibraries);

      // Remove libraries that we just linked.
      cycleInputLibraries.forEach(inputLibraries.remove);
    }
  }

  String _readSafely(String path) {
    try {
      var file = resourceProvider.getFile(path);
      return file.readAsStringSync();
    } catch (_) {
      return '';
    }
  }

  /// If there are any macros in the [inputLibrary], add it.
  static void _addMacroLibrary(
    List<MacroLibrary> macroLibraries,
    LinkInputLibrary inputLibrary,
  ) {
    var macroClasses = <MacroClass>[];
    for (var inputUnit in inputLibrary.units) {
      for (var declaration in inputUnit.unit.declarations) {
        if (declaration is ClassDeclarationImpl &&
            declaration.macroKeyword != null) {
          var constructors =
              declaration.members.whereType<ConstructorDeclaration>().toList();
          if (constructors.isEmpty) {
            macroClasses.add(
              MacroClass(
                name: declaration.name.name,
                constructors: [''],
              ),
            );
          } else {
            var constructorNames = constructors
                .map((e) => e.name?.name ?? '')
                .where((e) => !e.startsWith('_'))
                .toList();
            if (constructorNames.isNotEmpty) {
              macroClasses.add(
                MacroClass(
                  name: declaration.name.name,
                  constructors: constructorNames,
                ),
              );
            }
          }
        }
      }
    }
    if (macroClasses.isNotEmpty) {
      macroLibraries.add(
        MacroLibrary(
          uri: inputLibrary.uri,
          path: inputLibrary.source.fullName,
          classes: macroClasses,
        ),
      );
    }
  }
}

class _AnalysisSessionForLinking implements AnalysisSessionImpl {
  @override
  final ClassHierarchy classHierarchy = ClassHierarchy();

  @override
  InheritanceManager3 inheritanceManager = InheritanceManager3();

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/// [MacroFileEntry] adapter for [File].
class _MacroFileEntry implements MacroFileEntry {
  final File file;

  _MacroFileEntry(this.file);

  @override
  String get content => file.readAsStringSync();

  @override
  bool get exists => file.exists;
}

/// [MacroFileSystem] adapter for [ResourceProvider].
class _MacroFileSystem implements MacroFileSystem {
  final ResourceProvider resourceProvider;

  _MacroFileSystem(this.resourceProvider);

  @override
  package_path.Context get pathContext => resourceProvider.pathContext;

  @override
  MacroFileEntry getFile(String path) {
    var file = resourceProvider.getFile(path);
    return _MacroFileEntry(file);
  }
}

class _SdkBundle {
  final Uint8List resolutionBytes;

  _SdkBundle({
    required this.resolutionBytes,
  });
}
