// Copyright (c) 2017, 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.

// ignore_for_file: analyzer_use_new_elements

/// @docImport 'package:analyzer/src/generated/engine.dart';
library;

import 'dart:collection';
import 'dart:typed_data';

import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement;
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/analysis_options_map.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/exception/exception.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary2/bundle_reader.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/macro_cache.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart';

/// Context information necessary to analyze one or more libraries within an
/// [AnalysisDriver].
///
/// Currently this is implemented as a wrapper around [AnalysisContext].
class LibraryContext {
  final LibraryContextTestData? testData;
  final PerformanceLog logger;
  final ByteStore byteStore;
  final InfoDeclarationStore infoDeclarationStore;
  final FileSystemState fileSystemState;
  final MacroSupport? macroSupport;
  final File? packagesFile;
  final SummaryDataStore store = SummaryDataStore();

  late final AnalysisContextImpl analysisContext;
  late final LinkedElementFactory elementFactory;

  Set<LibraryCycle> loadedBundles = Set.identity();

  LibraryContext({
    required this.testData,
    required AnalysisSessionImpl analysisSession,
    required this.logger,
    required this.byteStore,
    required this.infoDeclarationStore,
    required this.fileSystemState,
    required AnalysisOptionsMap analysisOptionsMap,
    required DeclaredVariables declaredVariables,
    required SourceFactory sourceFactory,
    required this.macroSupport,
    required this.packagesFile,
    required SummaryDataStore? externalSummaries,
  }) {
    analysisContext = AnalysisContextImpl(
      analysisOptionsMap: analysisOptionsMap,
      declaredVariables: declaredVariables,
      sourceFactory: sourceFactory,
    );

    elementFactory = LinkedElementFactory(
      analysisContext,
      analysisSession,
      Reference.root(),
      macroSupport,
    );
    if (externalSummaries != null) {
      for (var bundle in externalSummaries.bundles) {
        elementFactory.addBundle(
          BundleReader(
            elementFactory: elementFactory,
            resolutionBytes: bundle.resolutionBytes,
            unitsInformativeBytes: {},
            infoDeclarationStore: infoDeclarationStore,
          ),
        );
      }
    }
  }

  /// Computes a [CompilationUnitElement] for the given library/unit pair.
  CompilationUnitElementImpl computeUnitElement(
    LibraryFileKind library,
    FileState unit,
  ) {
    var reference = elementFactory.rootReference
        .getChild(library.file.uriStr)
        .getChild('@fragment')
        .getChild(unit.uriStr);
    var element = elementFactory.elementOfReference(reference);
    return element as CompilationUnitElementImpl;
  }

  /// Notifies this object that it is about to be discarded.
  ///
  /// Returns the keys of the artifacts that are no longer used.
  Set<String> dispose() {
    var keys = unloadAll();
    elementFactory.dispose();
    return keys;
  }

  /// Get the [LibraryElementImpl] for the given library.
  LibraryElementImpl getLibraryElement(Uri uri) {
    _createElementFactoryTypeProvider();
    return elementFactory.libraryOfUri2(uri);
  }

  /// Load data required to access elements of the given [targetLibrary].
  Future<void> load({
    required LibraryFileKind targetLibrary,
    required OperationPerformanceImpl performance,
  }) async {
    addToLogRing('[load][targetLibrary: ${targetLibrary.file}]');
    var librariesTotal = 0;
    var librariesLoaded = 0;
    var librariesLinked = 0;
    var librariesLinkedTimer = Stopwatch();
    var bytesGet = 0;
    var bytesPut = 0;

    Future<void> loadBundle(LibraryCycle cycle) async {
      if (!loadedBundles.add(cycle)) return;

      performance.getDataInt('cycleCount').increment();
      performance.getDataInt('libraryCount').add(cycle.libraries.length);

      librariesTotal += cycle.libraries.length;

      for (var directDependency in cycle.directDependencies) {
        await loadBundle(directDependency);
      }

      var unitsInformativeBytes = <Uri, Uint8List>{};
      var macroLibraries = <MacroLibrary>[];
      for (var library in cycle.libraries) {
        var macroClasses = <MacroClass>[];
        for (var file in library.files) {
          unitsInformativeBytes[file.uri] = file.unlinked2.informativeBytes;
          for (var macroClass in file.unlinked2.macroClasses) {
            macroClasses.add(
              MacroClass(
                name: macroClass.name,
                constructors: macroClass.constructors,
              ),
            );
          }
        }
        if (macroClasses.isNotEmpty) {
          macroLibraries.add(
            MacroLibrary(
              uri: library.file.uri,
              path: library.file.path,
              classes: macroClasses,
            ),
          );
        }
      }

      var macroResultKey = cycle.cachedMacrosKey;
      var inputMacroResults = <LibraryFileKind, MacroResultInput>{};
      if (byteStore.get(macroResultKey) case var bytes?) {
        _readMacroResults(
          cycle: cycle,
          bytes: bytes,
          macroResults: inputMacroResults,
        );
      }

      var linkedBytes = byteStore.get(cycle.linkedKey);

      if (linkedBytes == null) {
        librariesLinkedTimer.start();

        testData?.linkedCycles.add(
          cycle.libraries.map((e) => e.file.path).toSet(),
        );

        LinkResult linkResult;
        try {
          linkResult = await performance.runAsync(
            'link',
            (performance) async {
              return await link(
                elementFactory: elementFactory,
                performance: performance,
                inputLibraries: cycle.libraries,
                inputMacroResults: inputMacroResults,
                macroExecutor: this.macroSupport?.executor,
              );
            },
          );
          librariesLinked += cycle.libraries.length;
        } catch (exception, stackTrace) {
          _throwLibraryCycleLinkException(cycle, exception, stackTrace);
        }

        linkedBytes = linkResult.resolutionBytes;
        byteStore.putGet(cycle.linkedKey, linkedBytes);
        performance.getDataInt('bytesPut').add(linkedBytes.length);
        testData?.forCycle(cycle).putKeys.add(cycle.linkedKey);
        bytesPut += linkedBytes.length;

        _writeMacroResults(
          cycle: cycle,
          linkResult: linkResult,
          macroResultKey: macroResultKey,
        );

        librariesLinkedTimer.stop();
      } else {
        testData?.forCycle(cycle).getKeys.add(cycle.linkedKey);
        performance.getDataInt('bytesGet').add(linkedBytes.length);
        performance.getDataInt('libraryLoadCount').add(cycle.libraries.length);
        // TODO(scheglov): Take / clear parsed units in files.
        bytesGet += linkedBytes.length;
        librariesLoaded += cycle.libraries.length;
        var bundleReader = BundleReader(
          elementFactory: elementFactory,
          unitsInformativeBytes: unitsInformativeBytes,
          resolutionBytes: linkedBytes,
          infoDeclarationStore: infoDeclarationStore,
        );
        elementFactory.addBundle(bundleReader);
        _addMacroParts(cycle, bundleReader);
      }

      // If we can compile to kernel, check if there are macros.
      var macroSupport = this.macroSupport;
      var packagesFile = this.packagesFile;
      if (macroSupport is KernelMacroSupport &&
          packagesFile != null &&
          macroLibraries.isNotEmpty) {
        var kernelBytes = byteStore.get(cycle.macroKey);
        if (kernelBytes == null) {
          kernelBytes = await performance.runAsync<Uint8List>(
            'macroCompileKernel',
            (performance) async {
              return await macroSupport.builder.build(
                fileSystem: _MacroFileSystem(fileSystemState),
                packageFilePath: packagesFile.path,
                libraries: macroLibraries,
              );
            },
          );
          byteStore.putGet(cycle.macroKey, kernelBytes);
          bytesPut += kernelBytes.length;
        } else {
          bytesGet += kernelBytes.length;
        }

        elementFactory.addKernelMacroBundle(
          macroSupport: macroSupport,
          kernelBytes: kernelBytes,
          libraries: cycle.libraries.map((e) => e.file.uri).toSet(),
        );
      }
    }

    await logger.runAsync('Prepare linked bundles', () async {
      var libraryCycle = performance.run('libraryCycle', (performance) {
        fileSystemState.newFileOperationPerformance = performance;
        try {
          return targetLibrary.libraryCycle;
        } finally {
          fileSystemState.newFileOperationPerformance = null;
        }
      });
      await loadBundle(libraryCycle);
      logger.writeln(
        '[librariesTotal: $librariesTotal]'
        '[librariesLoaded: $librariesLoaded]'
        '[librariesLinked: $librariesLinked]'
        '[librariesLinkedTimer: ${librariesLinkedTimer.elapsedMilliseconds} ms]'
        '[bytesGet: $bytesGet][bytesPut: $bytesPut]',
      );
    });

    // There might be a rare (and wrong) situation, when the external summaries
    // already include the [targetLibrary]. When this happens, [loadBundle]
    // exists without doing any work. But the type provider must be created.
    _createElementFactoryTypeProvider();
  }

  /// Remove libraries represented by the [removed] files.
  /// If we need these libraries later, we will relink and reattach them.
  void remove(Set<FileState> removed, Set<String> removedKeys) {
    elementFactory.removeLibraries(
      removed.map((e) => e.uri).toSet(),
    );

    loadedBundles.removeWhere((cycle) {
      var cycleFiles = cycle.libraries.map((e) => e.file);
      if (cycleFiles.any(removed.contains)) {
        removedKeys.add(cycle.linkedKey);
        return true;
      }
      return false;
    });
  }

  /// Unloads all loaded bundles.
  ///
  /// Returns the keys of the artifacts that are no longer used.
  Set<String> unloadAll() {
    var keySet = <String>{};
    var uriSet = <Uri>{};

    for (var cycle in loadedBundles) {
      keySet.add(cycle.linkedKey);
      uriSet.addAll(cycle.libraries.map((e) => e.file.uri));
    }

    elementFactory.removeLibraries(uriSet);
    loadedBundles.clear();

    return keySet;
  }

  /// Create files with macro generated parts.
  void _addMacroParts(LibraryCycle cycle, BundleReader bundleReader) {
    for (var libraryReader in bundleReader.libraryMap.values) {
      var macroGeneratedCode = libraryReader.macroGeneratedCode;
      if (macroGeneratedCode != null) {
        for (var libraryKind in cycle.libraries) {
          if (libraryKind.file.uri == libraryReader.uri) {
            libraryKind.addMacroPart(
              macroGeneratedCode,
              partialIndex: null,
              performance: OperationPerformanceImpl('<root>'),
            );
          }
        }
      }
    }
  }

  /// Ensure that type provider is created.
  void _createElementFactoryTypeProvider() {
    if (!analysisContext.hasTypeProvider) {
      elementFactory.createTypeProviders(
        elementFactory.dartCoreElement,
        elementFactory.dartAsyncElement,
      );
    }
  }

  /// Fills [macroResults] with results that can be reused.
  void _readMacroResults({
    required LibraryCycle cycle,
    required Uint8List bytes,
    required Map<LibraryFileKind, MacroResultInput> macroResults,
  }) {
    var bundle = MacroCacheBundle.fromBytes(cycle, bytes);
    var testUsedList = <File>[];
    for (var library in bundle.libraries) {
      // If the library itself changed, then declarations that macros see
      // could be different now.
      if (!ListEquality<int>().equals(
        library.apiSignature,
        library.kind.apiSignature,
      )) {
        continue;
      }

      // TODO(scheglov): Record more specific dependencies.
      if (library.hasAnyIntrospection) {
        continue;
      }

      testUsedList.add(library.kind.file.resource);

      macroResults[library.kind] = MacroResultInput(
        code: library.code,
      );
    }

    if (testUsedList.isNotEmpty) {
      var cycleTestData = testData?.forCycle(cycle);
      cycleTestData?.macrosUsedCached.add(testUsedList);
    }
  }

  /// The [exception] was caught during the [cycle] linking.
  ///
  /// Throw another exception that wraps the given one, with more information.
  Never _throwLibraryCycleLinkException(
    LibraryCycle cycle,
    Object exception,
    StackTrace stackTrace,
  ) {
    var fileContentMap = <String, String>{};
    for (var library in cycle.libraries) {
      for (var file in library.files) {
        fileContentMap[file.path] = file.content;
      }
    }
    throw CaughtExceptionWithFiles(exception, stackTrace, fileContentMap);
  }

  void _writeMacroResults({
    required LibraryCycle cycle,
    required LinkResult linkResult,
    required String macroResultKey,
  }) {
    var results = linkResult.macroResults;
    if (results.isEmpty) {
      return;
    }

    testData?.forCycle(cycle).macrosGenerated.add(
          linkResult.macroResults
              .map((result) => result.library.file.resource)
              .toList(),
        );

    var bundle = MacroCacheBundle(
      libraries: results.map((result) {
        return MacroCacheLibrary(
          kind: result.library,
          apiSignature: result.library.apiSignature,
          hasAnyIntrospection: result.processing.hasAnyIntrospection,
          code: result.code,
        );
      }).toList(),
    );

    var bytes = bundle.toBytes();
    byteStore.putGet(macroResultKey, bytes);
  }
}

class LibraryContextTestData {
  final FileSystemTestData fileSystemTestData;

  // TODO(scheglov): Use [libraryCycles] and textual dumps for the driver too.
  final List<Set<String>> linkedCycles = [];

  /// Keys: the sorted list of library files.
  final Map<List<FileTestData>, LibraryCycleTestData> libraryCycles =
      LinkedHashMap(
    hashCode: Object.hashAll,
    equals: const ListEquality<FileTestData>().equals,
  );

  LibraryContextTestData({
    required this.fileSystemTestData,
  });

  LibraryCycleTestData forCycle(LibraryCycle cycle) {
    var files = cycle.libraries.map((library) {
      var file = library.file;
      return fileSystemTestData.forFile(file.resource, file.uri);
    }).toList();
    files.sortBy((fileData) => fileData.file.path);

    return libraryCycles[files] ??= LibraryCycleTestData();
  }
}

class LibraryCycleTestData {
  final List<String> getKeys = [];
  final List<String> putKeys = [];
  final List<List<File>> macrosUsedCached = [];
  final List<List<File>> macrosGenerated = [];
}

class _MacroFileEntry implements MacroFileEntry {
  @override
  final String content;

  @override
  final bool exists;

  _MacroFileEntry({
    required this.content,
    required this.exists,
  });
}

class _MacroFileSystem implements MacroFileSystem {
  final FileSystemState fileSystemState;

  _MacroFileSystem(this.fileSystemState);

  @override
  Context get pathContext => fileSystemState.pathContext;

  @override
  MacroFileEntry getFile(String path) {
    var fileState = fileSystemState.getExistingFromPath(path);
    if (fileState != null) {
      return _MacroFileEntry(
        content: fileState.content,
        exists: fileState.exists,
      );
    }

    var fileContent = fileSystemState.fileContentStrategy.get(path);
    return _MacroFileEntry(
      content: fileContent.content,
      exists: fileContent.exists,
    );
  }
}
