// Copyright (c) 2019, 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:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/name_union.dart';
import 'package:analyzer/src/summary2/bundle_writer.dart';
import 'package:analyzer/src/summary2/detach_nodes.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/macro_declarations.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/simply_bounded.dart';
import 'package:analyzer/src/summary2/super_constructor_resolver.dart';
import 'package:analyzer/src/summary2/top_level_inference.dart';
import 'package:analyzer/src/summary2/type_alias.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/summary2/variance_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/uri_cache.dart';
import 'package:macros/src/executor/multi_executor.dart' as macro;

Future<LinkResult> link({
  required LinkedElementFactory elementFactory,
  required OperationPerformanceImpl performance,
  required List<LibraryFileKind> inputLibraries,
  macro.MultiMacroExecutor? macroExecutor,
}) async {
  var linker = Linker(elementFactory, macroExecutor);
  await linker.link(
    performance: performance,
    inputLibraries: inputLibraries,
  );
  return LinkResult(
    resolutionBytes: linker.resolutionBytes,
  );
}

class Linker {
  final LinkedElementFactory elementFactory;
  final macro.MultiMacroExecutor? macroExecutor;
  late final DeclarationBuilder macroDeclarationBuilder;

  /// Libraries that are being linked.
  final Map<Uri, LibraryBuilder> builders = {};

  final Map<ElementImpl, ast.AstNode> elementNodes = Map.identity();

  late InheritanceManager3 inheritance; // TODO(scheglov): cache it

  late Uint8List resolutionBytes;

  LibraryMacroApplier? _macroApplier;

  Linker(this.elementFactory, this.macroExecutor) {
    macroDeclarationBuilder = DeclarationBuilder(
      nodeOfElement: (element) => elementNodes[element],
    );
  }

  AnalysisContextImpl get analysisContext {
    return elementFactory.analysisContext;
  }

  DeclaredVariables get declaredVariables {
    return analysisContext.declaredVariables;
  }

  LibraryMacroApplier? get macroApplier => _macroApplier;

  Reference get rootReference => elementFactory.rootReference;

  bool get _isLinkingDartCore {
    var dartCoreUri = uriCache.parse('dart:core');
    return builders.containsKey(dartCoreUri);
  }

  /// If the [element] is part of a library being linked, return the node
  /// from which it was created.
  ast.AstNode? getLinkingNode(Element element) {
    return elementNodes[element];
  }

  Future<void> link({
    required OperationPerformanceImpl performance,
    required List<LibraryFileKind> inputLibraries,
  }) async {
    for (var inputLibrary in inputLibraries) {
      LibraryBuilder.build(this, inputLibrary);
    }

    await _buildOutlines(
      performance: performance,
    );

    _writeLibraries();
  }

  void _buildClassSyntheticConstructors() {
    for (var library in builders.values) {
      library.buildClassSyntheticConstructors();
    }
  }

  void _buildElementNameUnions() {
    for (var builder in builders.values) {
      var element = builder.element;
      element.nameUnion = ElementNameUnion.forLibrary(element);
    }
  }

  void _buildEnumChildren() {
    for (var library in builders.values) {
      library.buildEnumChildren();
    }
  }

  void _buildEnumSyntheticConstructors() {
    for (var library in builders.values) {
      library.buildEnumSyntheticConstructors();
    }
  }

  void _buildExportScopes() {
    for (var library in builders.values) {
      library.buildInitialExportScope();
    }

    var exportingBuilders = <LibraryBuilder>{};
    var exportedBuilders = <LibraryBuilder>{};

    for (var library in builders.values) {
      library.addExporters();
    }

    for (var library in builders.values) {
      if (library.exports.isNotEmpty) {
        exportedBuilders.add(library);
        for (var export in library.exports) {
          exportingBuilders.add(export.exporter);
        }
      }
    }

    var both = <LibraryBuilder>{};
    for (var exported in exportedBuilders) {
      if (exportingBuilders.contains(exported)) {
        both.add(exported);
      }
      for (var export in exported.exports) {
        exported.exportScope.forEach(export.addToExportScope);
      }
    }

    while (true) {
      var hasChanges = false;
      for (var exported in both) {
        for (var export in exported.exports) {
          exported.exportScope.forEach((name, reference) {
            if (export.addToExportScope(name, reference)) {
              hasChanges = true;
            }
          });
        }
      }
      if (!hasChanges) break;
    }

    for (var library in builders.values) {
      library.storeExportScope();
    }
  }

  Future<LibraryMacroApplier?> _buildMacroApplier() async {
    var macroExecutor = this.macroExecutor;
    if (macroExecutor == null) {
      return null;
    }

    var macroApplier = LibraryMacroApplier(
      elementFactory: elementFactory,
      macroExecutor: macroExecutor,
      isLibraryBeingLinked: (uri) => builders.containsKey(uri),
      declarationBuilder: macroDeclarationBuilder,
      runDeclarationsPhase: _executeMacroDeclarationsPhase,
    );

    for (var library in builders.values) {
      await library.fillMacroApplier(macroApplier);
    }

    return _macroApplier = macroApplier;
  }

  Future<void> _buildOutlines({
    required OperationPerformanceImpl performance,
  }) async {
    _createTypeSystemIfNotLinkingDartCore();

    await performance.runAsync(
      'computeLibraryScopes',
      (performance) async {
        await _computeLibraryScopes(
          performance: performance,
        );
      },
    );

    _createTypeSystem();
    _resolveTypes();
    _setDefaultSupertypes();

    await performance.runAsync(
      'executeMacroDeclarationsPhase',
      (performance) async {
        await _executeMacroDeclarationsPhase(
          targetElement: null,
          performance: performance,
        );
      },
    );

    _buildClassSyntheticConstructors();
    _buildEnumSyntheticConstructors();
    _replaceConstFieldsIfNoConstConstructor();
    _resolveConstructorFieldFormals();
    _buildEnumChildren();
    _computeFieldPromotability();
    SuperConstructorResolver(this).perform();
    _performTopLevelInference();
    _resolveConstructors();
    _resolveConstantInitializers();
    _resolveDefaultValues();
    _resolveMetadata();

    // TODO(scheglov): verify if any resolutions should happen after
    await performance.runAsync(
      'executeMacroDefinitionsPhase',
      (performance) async {
        await _executeMacroDefinitionsPhase(
          performance: performance,
        );
      },
    );

    _collectMixinSuperInvokedNames();
    _buildElementNameUnions();
    _detachNodes();

    await performance.runAsync(
      'mergeMacroAugmentations',
      (performance) async {
        await _mergeMacroAugmentations(
          performance: performance,
        );
      },
    );

    _disposeMacroApplications();
  }

  void _collectMixinSuperInvokedNames() {
    for (var library in builders.values) {
      library.collectMixinSuperInvokedNames();
    }
  }

  void _computeFieldPromotability() {
    for (var library in builders.values) {
      library.computeFieldPromotability();
    }
  }

  Future<void> _computeLibraryScopes({
    required OperationPerformanceImpl performance,
  }) async {
    for (var library in builders.values) {
      library.buildElements();
    }

    await performance.runAsync(
      'buildMacroApplier',
      (performance) async {
        await _buildMacroApplier();
      },
    );

    await performance.runAsync(
      'executeMacroTypesPhase',
      (performance) async {
        for (var library in builders.values) {
          await library.executeMacroTypesPhase(
            performance: performance,
          );
        }
      },
    );

    _buildExportScopes();
  }

  void _createTypeSystem() {
    elementFactory.createTypeProviders(
      elementFactory.dartCoreElement,
      elementFactory.dartAsyncElement,
    );

    inheritance = InheritanceManager3();
  }

  /// To resolve macro annotations we need to access exported namespaces of
  /// imported (and already linked) libraries. While computing it we might
  /// need `Null` from `dart:core` (to convert null safe types to legacy).
  void _createTypeSystemIfNotLinkingDartCore() {
    if (!_isLinkingDartCore) {
      _createTypeSystem();
    }
  }

  void _detachNodes() {
    for (var builder in builders.values) {
      detachElementsFromNodes(builder.element);
    }
  }

  void _disposeMacroApplications() {
    for (var library in builders.values) {
      library.disposeMacroApplications();
    }
  }

  Future<void> _executeMacroDeclarationsPhase({
    required ElementImpl? targetElement,
    required OperationPerformanceImpl performance,
  }) async {
    while (true) {
      var hasProgress = false;
      for (var library in builders.values) {
        var stepResult = await library.executeMacroDeclarationsPhase(
          targetElement: targetElement,
          performance: performance,
        );
        switch (stepResult) {
          case MacroDeclarationsPhaseStepResult.nothing:
            break;
          case MacroDeclarationsPhaseStepResult.otherProgress:
            hasProgress = true;
          case MacroDeclarationsPhaseStepResult.topDeclaration:
            hasProgress = true;
            _buildExportScopes();
        }
      }
      if (!hasProgress) {
        break;
      }
    }
  }

  Future<void> _executeMacroDefinitionsPhase({
    required OperationPerformanceImpl performance,
  }) async {
    for (var library in builders.values) {
      await library.executeMacroDefinitionsPhase(
        performance: performance,
      );
    }
  }

  Future<void> _mergeMacroAugmentations({
    required OperationPerformanceImpl performance,
  }) async {
    for (var library in builders.values) {
      await library.mergeMacroAugmentations(
        performance: performance,
      );
    }
  }

  void _performTopLevelInference() {
    TopLevelInference(this).infer();
  }

  void _replaceConstFieldsIfNoConstConstructor() {
    for (var library in builders.values) {
      library.replaceConstFieldsIfNoConstConstructor();
    }
  }

  void _resolveConstantInitializers() {
    ConstantInitializersResolver(this).perform();
  }

  void _resolveConstructorFieldFormals() {
    for (var library in builders.values) {
      library.resolveConstructorFieldFormals();
    }
  }

  void _resolveConstructors() {
    for (var library in builders.values) {
      library.resolveConstructors();
    }
  }

  void _resolveDefaultValues() {
    for (var library in builders.values) {
      library.resolveDefaultValues();
    }
  }

  void _resolveMetadata() {
    for (var library in builders.values) {
      library.resolveMetadata();
    }
  }

  void _resolveTypes() {
    var nodesToBuildType = NodesToBuildType();
    for (var library in builders.values) {
      library.resolveTypes(nodesToBuildType);
    }
    VarianceBuilder(this).perform();
    computeSimplyBounded(this);
    TypeAliasSelfReferenceFinder().perform(this);
    TypesBuilder(this).build(nodesToBuildType);
  }

  void _setDefaultSupertypes() {
    for (var library in builders.values) {
      library.setDefaultSupertypes();
    }
  }

  void _writeLibraries() {
    var bundleWriter = BundleWriter(
      elementFactory.dynamicRef,
    );

    for (var builder in builders.values) {
      bundleWriter.writeLibraryElement(builder.element);
    }

    var writeWriterResult = bundleWriter.finish();
    resolutionBytes = writeWriterResult.resolutionBytes;
  }
}

class LinkResult {
  final Uint8List resolutionBytes;

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