// 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/element/element.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
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/fine/library_manifest.dart';
import 'package:analyzer/src/fine/requirements.dart';
import 'package:analyzer/src/summary2/bundle_writer.dart';
import 'package:analyzer/src/summary2/detach_nodes.dart';
import 'package:analyzer/src/summary2/enclosing_type_parameters_flag.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/extension_type.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/linked_element_factory.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';

LinkResult link({
  required LinkedElementFactory elementFactory,
  required OperationPerformanceImpl performance,
  required List<LibraryFileKind> inputLibraries,
  required String apiSignature,
}) {
  var linker = Linker(
    elementFactory: elementFactory,
    apiSignature: apiSignature,
  );
  linker.link(performance: performance, inputLibraries: inputLibraries);

  return LinkResult(resolutionBytes: linker.resolutionBytes);
}

/// Information about a declaring formal parameter, used while linking.
class DeclaringFormalParameterInfo {
  final ast.FormalParameterImpl node;
  final FieldFragmentImpl fieldFragment;
  final FormalParameterFragmentImpl formalFragment;

  DeclaringFormalParameterInfo({
    required this.node,
    required this.fieldFragment,
    required this.formalFragment,
  });
}

class Linker {
  final LinkedElementFactory elementFactory;
  final String apiSignature;

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

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

  final Map<ast.FormalParameterImpl, DeclaringFormalParameterInfo>
  declaringFormalParameters = Map.identity();

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

  Map<Uri, LibraryManifest> newLibraryManifests = {};
  late Uint8List resolutionBytes;

  Linker({required this.elementFactory, required this.apiSignature});

  AnalysisContextImpl get analysisContext {
    return elementFactory.analysisContext;
  }

  DeclaredVariables get declaredVariables {
    return analysisContext.declaredVariables;
  }

  RootReference get rootReference => elementFactory.rootReference;

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

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

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

  bool isLinkingElement(Element element) {
    return builders.containsKey(element.library?.uri);
  }

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

    performance.run('buildOutlines', (performance) {
      _buildOutlines(performance: performance);
    });

    performance.run('writeLibraries', (performance) {
      _writeLibraries(performance: performance);
    });
  }

  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);
      }
    }

    // We keep a queue of export entries to propagate.
    // First we loop over every library that both exports and is exported, but
    // then we only process the export entries that should be propagated.
    var additionalExports = <_AdditionalExport>[];

    void addExport(Export export, ExportEntry entry) {
      if (export.addToExportScope(entry)) {
        // We've added [entry.name] to [export.exporter]s export scope.
        // We need to propagate that to anyone that exports that library.
        additionalExports.add(_AdditionalExport(export.exporter, entry));
      }
    }

    for (var exported in both) {
      for (var export in exported.exports) {
        exported.exportScope.forEach((entry) {
          addExport(export, entry);
        });
      }
    }

    while (additionalExports.isNotEmpty) {
      var additionalExport = additionalExports.removeLast();
      for (var export in additionalExport.exportedLibrary.exports) {
        addExport(export, additionalExport.entry);
      }
    }

    assert(() {
      for (var exported in both) {
        for (var export in exported.exports) {
          exported.exportScope.forEach((entry) {
            if (export.addToExportScope(entry)) {
              throw "Error in export calculation: Assert failed.";
            }
          });
        }
      }
      return true;
    }(), true);

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

  void _buildOutlines({required OperationPerformanceImpl performance}) {
    _createTypeSystemIfNotLinkingDartCore();

    performance.run('computeLibraryScopes', (performance) {
      _computeLibraryScopes(performance: performance);
    });

    globalResultRequirements?.addExcludedLibraries(
      builders.values.map((builder) => builder.uri),
    );

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

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

    _collectMixinSuperInvokedNames();
    EnclosingTypeParameterReferenceFlag(this).perform();
    _buildElementNameUnions();
    _detachNodes();
  }

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

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

  /// Set [InterfaceElementImpl.hasNonFinalField] for classes and mixins.
  ///
  /// We actually use it only for classes (which can have `const` constructors),
  /// but mixins contribute to it.
  void _computeHasNonFinalField() {
    var linkingElements = builders.values
        .expand((builder) => builder.element.children)
        .whereType<InterfaceElementImpl>()
        .toSet();

    var alreadyComputed = Set<InterfaceElementImpl>.identity();

    bool computeFor(InterfaceElementImpl element) {
      if (!linkingElements.contains(element) || !alreadyComputed.add(element)) {
        return element.hasNonFinalField;
      }

      var hasNonFinalField = [
        element.supertype,
        ...element.mixins,
      ].nonNulls.any((type) => computeFor(type.element));

      hasNonFinalField |= !element.fields
          .where((field) => field.isInstanceField)
          .every((field) {
            // If has storage...
            if ((field.isOriginDeclaration && !field.isAbstract) ||
                field.isOriginDeclaringFormalParameter) {
              // ...then must be final
              return field.isFinal || field.isConst;
            }
            // Otherwise we don't care.
            return true;
          });

      return element.hasNonFinalField = hasNonFinalField;
    }

    for (var element in linkingElements) {
      computeFor(element);
    }
  }

  void _computeLibraryScopes({required OperationPerformanceImpl performance}) {
    globalResultRequirements.untracked(
      reason: 'No complete elements yet',
      operation: () {
        for (var library in builders.values) {
          library.buildElements();
        }
      },
    );

    _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 _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({required OperationPerformanceImpl performance}) {
    var bundleWriter = BundleWriter();

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

    var writeWriterResult = performance.run('bundleWriteFinish', (performance) {
      return bundleWriter.finish();
    });
    resolutionBytes = writeWriterResult.resolutionBytes;

    performance.getDataInt('length').add(resolutionBytes.length);
  }
}

class LinkResult {
  final Uint8List resolutionBytes;

  LinkResult({required this.resolutionBytes});
}

class _AdditionalExport {
  final LibraryBuilder exportedLibrary;
  final ExportEntry entry;

  _AdditionalExport(this.exportedLibrary, this.entry);
}
