// 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 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart' hide DirectiveUri;
import 'package:analyzer/src/dart/analysis/file_state.dart' as file_state;
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
import 'package:analyzer/src/summary2/default_value_resolver.dart';
import 'package:analyzer/src/summary2/element_builder.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/metadata_resolver.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/reference_resolver.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';

class ImplicitEnumNodes {
  final EnumElementImpl element;
  final ast.NamedTypeImpl valuesTypeNode;
  final ConstFieldElementImpl valuesField;

  ImplicitEnumNodes({
    required this.element,
    required this.valuesTypeNode,
    required this.valuesField,
  });
}

class LibraryBuilder {
  final Linker linker;
  final LibraryFileStateKind kind;
  final Uri uri;
  final Reference reference;
  final LibraryElementImpl element;
  final List<LinkingUnit> units;

  final List<ImplicitEnumNodes> implicitEnumNodes = [];

  /// Local declarations.
  final Map<String, Reference> _declaredReferences = {};

  /// The export scope of the library.
  final ExportScope exportScope = ExportScope();

  /// The `export` directives that export this library.
  final List<Export> exports = [];

  late final LibraryMacroApplier? _macroApplier = () {
    if (!element.featureSet.isEnabled(Feature.macros)) {
      return null;
    }

    final macroExecutor = linker.macroExecutor;
    if (macroExecutor == null) {
      return null;
    }

    return LibraryMacroApplier(
      macroExecutor: macroExecutor,
      declarationBuilder: linker.macroDeclarationBuilder,
      libraryBuilder: this,
    );
  }();

  LibraryBuilder._({
    required this.linker,
    required this.kind,
    required this.uri,
    required this.reference,
    required this.element,
    required this.units,
  });

  SourceFactory get _sourceFactory {
    return linker.elementFactory.analysisContext.sourceFactory;
  }

  void addExporters() {
    final exportElements = element.exports;
    for (var i = 0; i < exportElements.length; i++) {
      final exportElement = exportElements[i];

      final exportedLibrary = exportElement.exportedLibrary;
      if (exportedLibrary is! LibraryElementImpl) {
        continue;
      }

      final combinators = exportElement.combinators.map((combinator) {
        if (combinator is ShowElementCombinator) {
          return Combinator.show(combinator.shownNames);
        } else if (combinator is HideElementCombinator) {
          return Combinator.hide(combinator.hiddenNames);
        } else {
          throw UnimplementedError();
        }
      }).toList();

      final exportedUri = exportedLibrary.source.uri;
      final exportedBuilder = linker.builders[exportedUri];

      final export = Export(this, i, combinators);
      if (exportedBuilder != null) {
        exportedBuilder.exports.add(export);
      } else {
        final exportedReferences = exportedLibrary.exportedReferences;
        for (final exported in exportedReferences) {
          final reference = exported.reference;
          final name = reference.name;
          if (reference.isSetter) {
            export.addToExportScope('$name=', exported);
          } else {
            export.addToExportScope(name, exported);
          }
        }
      }
    }
  }

  /// Build elements for declarations in the library units, add top-level
  /// declarations to the local scope, for combining into export scopes.
  void buildElements() {
    element.imports2 = kind.imports.map(_buildImport).toList();

    for (var linkingUnit in units) {
      var elementBuilder = ElementBuilder(
        libraryBuilder: this,
        unitReference: linkingUnit.reference,
        unitElement: linkingUnit.element,
      );
      if (linkingUnit.isDefiningUnit) {
        elementBuilder.buildLibraryElementChildren(linkingUnit.node);
      }
      elementBuilder.buildDeclarationElements(linkingUnit.node);
    }
    _declareDartCoreDynamicNever();
  }

  void buildEnumChildren() {
    var typeProvider = element.typeProvider;
    for (var enum_ in implicitEnumNodes) {
      enum_.element.supertype =
          typeProvider.enumType ?? typeProvider.objectType;
      var valuesType = typeProvider.listType(
        element.typeSystem.instantiateToBounds2(
          classElement: enum_.element,
          nullabilitySuffix: typeProvider.objectType.nullabilitySuffix,
        ),
      );
      enum_.valuesTypeNode.type = valuesType;
      enum_.valuesField.type = valuesType;
    }
  }

  void buildInitialExportScope() {
    _declaredReferences.forEach((name, reference) {
      if (name.startsWith('_')) return;
      if (reference.isPrefix) return;
      exportScope.declare(name, reference);
    });
  }

  void collectMixinSuperInvokedNames() {
    for (var linkingUnit in units) {
      for (var declaration in linkingUnit.node.declarations) {
        if (declaration is ast.MixinDeclaration) {
          var names = <String>{};
          var collector = MixinSuperInvokedNamesCollector(names);
          for (var executable in declaration.members) {
            if (executable is ast.MethodDeclaration) {
              executable.body.accept(collector);
            }
          }
          var element = declaration.declaredElement as MixinElementImpl;
          element.superInvokedNames = names.toList();
        }
      }
    }
  }

  void declare(String name, Reference reference) {
    _declaredReferences[name] = reference;
  }

  Future<void> executeMacroDeclarationsPhase() async {
    final macroApplier = _macroApplier;
    if (macroApplier == null) {
      return;
    }

    final augmentationLibrary = await macroApplier.executeDeclarationsPhase();
    if (augmentationLibrary == null) {
      return;
    }

    final parseResult = parseString(
      content: augmentationLibrary,
      featureSet: element.featureSet,
      throwIfDiagnostics: false,
    );
    final unitNode = parseResult.unit as ast.CompilationUnitImpl;

    // We don't actually keep this unit, but we need it for now as a container.
    // Eventually we will use actual augmentation libraries.
    final unitUri = uri.resolve('_macro_declarations.dart');
    final unitReference = reference.getChild('@unit').getChild('$unitUri');
    final unitElement = CompilationUnitElementImpl(
      source: _sourceFactory.forUri2(unitUri)!,
      librarySource: element.source,
      lineInfo: parseResult.lineInfo,
    )
      ..enclosingElement = element
      ..isSynthetic = true
      ..uri = unitUri.toString();

    final elementBuilder = ElementBuilder(
      libraryBuilder: this,
      unitReference: unitReference,
      unitElement: unitElement,
    );
    elementBuilder.buildDeclarationElements(unitNode);

    // We move elements, so they don't have real offsets.
    unitElement.accept(_FlushElementOffsets());

    final nodesToBuildType = NodesToBuildType();
    final resolver = ReferenceResolver(linker, nodesToBuildType, element);
    unitNode.accept(resolver);
    TypesBuilder(linker).build(nodesToBuildType);

    // Transplant built elements as if the augmentation was applied.
    final augmentedUnitElement = element.definingCompilationUnit;
    for (final augmentation in unitElement.classes) {
      // TODO(scheglov) if augmentation
      final augmented = element.getType(augmentation.name);
      if (augmented is ClassElementImpl) {
        augmented.accessors = [
          ...augmented.accessors,
          ...augmentation.accessors,
        ];
        augmented.constructors = [
          ...augmented.constructors,
          ...augmentation.constructors.where((e) => !e.isSynthetic),
        ];
        augmented.fields = [
          ...augmented.fields,
          ...augmentation.fields,
        ];
        augmented.methods = [
          ...augmented.methods,
          ...augmentation.methods,
        ];
      }
    }
    augmentedUnitElement.accessors = [
      ...augmentedUnitElement.accessors,
      ...unitElement.accessors,
    ];
    augmentedUnitElement.topLevelVariables = [
      ...augmentedUnitElement.topLevelVariables,
      ...unitElement.topLevelVariables,
    ];
  }

  Future<void> executeMacroTypesPhase({
    required OperationPerformanceImpl performance,
  }) async {
    final macroApplier = _macroApplier;
    if (macroApplier == null) {
      return;
    }

    await performance.runAsync(
      'buildApplications',
      (performance) async {
        await macroApplier.buildApplications(
          performance: performance,
        );
      },
    );

    final augmentationLibrary = await performance.runAsync(
      'executeTypesPhase',
      (performance) async {
        return await macroApplier.executeTypesPhase();
      },
    );

    if (augmentationLibrary == null) {
      return;
    }

    var parseResult = parseString(
      content: augmentationLibrary,
      featureSet: element.featureSet,
      throwIfDiagnostics: false,
    );
    var unitNode = parseResult.unit as ast.CompilationUnitImpl;

    // For now we model augmentation libraries as parts.
    var unitUri = uri.resolve('_macro_types.dart');
    final unitSource = _sourceFactory.forUri2(unitUri)!;
    var unitElement = CompilationUnitElementImpl(
      source: unitSource,
      librarySource: element.source,
      lineInfo: parseResult.lineInfo,
    )
      ..enclosingElement = element
      ..isSynthetic = true
      ..uri = unitUri.toString();

    var unitReference = reference.getChild('@unit').getChild('$unitUri');
    _bindReference(unitReference, unitElement);

    element.parts2.add(
      PartElementImpl(
        uri: DirectiveUriWithUnitImpl(
          relativeUriString: '_macro_types.dart',
          relativeUri: unitUri,
          unit: unitElement,
        ),
      ),
    );

    ElementBuilder(
      libraryBuilder: this,
      unitReference: unitReference,
      unitElement: unitElement,
    ).buildDeclarationElements(unitNode);

    // We move elements, so they don't have real offsets.
    unitElement.accept(_FlushElementOffsets());

    units.add(
      LinkingUnit(
        isDefiningUnit: false,
        reference: unitReference,
        node: unitNode,
        element: unitElement,
      ),
    );

    linker.macroGeneratedUnits.add(
      LinkMacroGeneratedUnit(
        uri: unitUri,
        content: parseResult.content,
        unit: parseResult.unit,
      ),
    );
  }

  void resolveConstructors() {
    ConstructorInitializerResolver(linker, element).resolve();
  }

  void resolveDefaultValues() {
    DefaultValueResolver(linker, element).resolve();
  }

  void resolveMetadata() {
    for (var linkingUnit in units) {
      var resolver = MetadataResolver(linker, element, linkingUnit.element);
      linkingUnit.node.accept(resolver);
    }
  }

  void resolveTypes(NodesToBuildType nodesToBuildType) {
    for (var linkingUnit in units) {
      var resolver = ReferenceResolver(linker, nodesToBuildType, element);
      linkingUnit.node.accept(resolver);
    }
  }

  void storeExportScope() {
    element.exportedReferences = exportScope.map.values.toList();

    var definedNames = <String, Element>{};
    for (var entry in exportScope.map.entries) {
      var reference = entry.value.reference;
      var element = linker.elementFactory.elementOfReference(reference);
      if (element != null) {
        definedNames[entry.key] = element;
      }
    }

    var namespace = Namespace(definedNames);
    element.exportNamespace = namespace;

    var entryPoint = namespace.get(FunctionElement.MAIN_FUNCTION_NAME);
    if (entryPoint is FunctionElement) {
      element.entryPoint = entryPoint;
    }
  }

  ImportElement2Impl _buildImport(ImportDirectiveState state) {
    final importPrefix = state.directive.prefix.mapOrNull((unlinked) {
      if (unlinked.deferredOffset != null) {
        return DeferredImportElementPrefixImpl(
          element: _buildPrefix(
            name: unlinked.name,
            nameOffset: unlinked.nameOffset,
          ),
        );
      } else {
        return ImportElementPrefixImpl(
          element: _buildPrefix(
            name: unlinked.name,
            nameOffset: unlinked.nameOffset,
          ),
        );
      }
    });

    final combinators = state.directive.combinators.map((unlinked) {
      if (unlinked.isShow) {
        return ShowElementCombinatorImpl()
          ..offset = unlinked.keywordOffset
          ..end = unlinked.endOffset
          ..shownNames = unlinked.names;
      } else {
        // TODO(scheglov) Why no offsets?
        return HideElementCombinatorImpl()..hiddenNames = unlinked.names;
      }
    }).toList();

    final DirectiveUri uri;
    if (state is ImportDirectiveWithFile) {
      final importedLibraryKind = state.importedLibrary;
      if (importedLibraryKind != null) {
        final importedFile = importedLibraryKind.file;
        final importedUri = importedFile.uri;
        final elementFactory = linker.elementFactory;
        final importedLibrary = elementFactory.libraryOfUri2(importedUri);
        uri = DirectiveUriWithLibraryImpl(
          relativeUriString: state.selectedUri.relativeUriStr,
          relativeUri: state.selectedUri.relativeUri,
          source: importedLibrary.source,
          library: importedLibrary,
        );
      } else {
        uri = DirectiveUriWithSourceImpl(
          relativeUriString: state.selectedUri.relativeUriStr,
          relativeUri: state.selectedUri.relativeUri,
          source: state.importedSource,
        );
      }
    } else if (state is ImportDirectiveWithInSummarySource) {
      final importedLibrarySource = state.importedLibrarySource;
      if (importedLibrarySource != null) {
        final importedUri = importedLibrarySource.uri;
        final elementFactory = linker.elementFactory;
        final importedLibrary = elementFactory.libraryOfUri2(importedUri);
        uri = DirectiveUriWithLibraryImpl(
          relativeUriString: state.selectedUri.relativeUriStr,
          relativeUri: state.selectedUri.relativeUri,
          source: importedLibrary.source,
          library: importedLibrary,
        );
      } else {
        uri = DirectiveUriWithSourceImpl(
          relativeUriString: state.selectedUri.relativeUriStr,
          relativeUri: state.selectedUri.relativeUri,
          source: state.importedSource,
        );
      }
    } else {
      final selectedUri = state.selectedUri;
      if (selectedUri is file_state.DirectiveUriWithUri) {
        uri = DirectiveUriWithRelativeUriImpl(
          relativeUriString: selectedUri.relativeUriStr,
          relativeUri: selectedUri.relativeUri,
        );
      } else if (selectedUri is file_state.DirectiveUriWithString) {
        uri = DirectiveUriWithRelativeUriStringImpl(
          relativeUriString: selectedUri.relativeUriStr,
        );
      } else {
        uri = DirectiveUriImpl();
      }
    }

    return ImportElement2Impl(
      importKeywordOffset: state.directive.importKeywordOffset,
      uri: uri,
      prefix: importPrefix,
    )
      ..combinators = combinators
      ..isSynthetic = state.isSyntheticDartCore;
  }

  PrefixElementImpl _buildPrefix({
    required String name,
    required int nameOffset,
  }) {
    final reference = this.reference.getChild('@prefix').getChild(name);
    final existing = reference.element;
    if (existing is PrefixElementImpl) {
      return existing;
    } else {
      final result = PrefixElementImpl(
        name,
        nameOffset,
        reference: reference,
      );
      element.encloseElement(result);
      return result;
    }
  }

  /// These elements are implicitly declared in `dart:core`.
  void _declareDartCoreDynamicNever() {
    if (reference.name == 'dart:core') {
      var dynamicRef = reference.getChild('dynamic');
      dynamicRef.element = DynamicElementImpl.instance;
      declare('dynamic', dynamicRef);

      var neverRef = reference.getChild('Never');
      neverRef.element = NeverElementImpl.instance;
      declare('Never', neverRef);
    }
  }

  static void build(Linker linker, LibraryFileStateKind inputLibrary) {
    final elementFactory = linker.elementFactory;
    final rootReference = linker.rootReference;

    final libraryFile = inputLibrary.file;
    final libraryUriStr = libraryFile.uriStr;
    final libraryReference = rootReference.getChild(libraryUriStr);

    final libraryUnitNode = libraryFile.parse();

    var name = '';
    var nameOffset = -1;
    var nameLength = 0;
    for (final directive in libraryUnitNode.directives) {
      if (directive is ast.LibraryDirective) {
        name = directive.name.components.map((e) => e.name).join('.');
        nameOffset = directive.name.offset;
        nameLength = directive.name.length;
        break;
      }
    }

    final libraryElement = LibraryElementImpl(
      elementFactory.analysisContext,
      elementFactory.analysisSession,
      name,
      nameOffset,
      nameLength,
      libraryUnitNode.featureSet,
    );
    libraryElement.isSynthetic = !libraryFile.exists;
    libraryElement.languageVersion = libraryUnitNode.languageVersion!;
    _bindReference(libraryReference, libraryElement);
    elementFactory.setLibraryTypeSystem(libraryElement);

    final unitContainerRef = libraryReference.getChild('@unit');

    final linkingUnits = <LinkingUnit>[];
    {
      final unitElement = CompilationUnitElementImpl(
        source: libraryFile.source,
        librarySource: libraryFile.source,
        lineInfo: libraryUnitNode.lineInfo,
      );
      unitElement.isSynthetic = !libraryFile.exists;
      unitElement.setCodeRange(0, libraryUnitNode.length);

      final unitReference = unitContainerRef.getChild(libraryFile.uriStr);
      _bindReference(unitReference, unitElement);

      linkingUnits.add(
        LinkingUnit(
          isDefiningUnit: true,
          reference: unitReference,
          node: libraryUnitNode,
          element: unitElement,
        ),
      );

      libraryElement.definingCompilationUnit = unitElement;
    }

    final parts = <PartElementImpl>[];
    for (final partState in inputLibrary.parts) {
      final uriState = partState.uri;

      final DirectiveUri directiveUri;
      if (partState is PartDirectiveWithFile) {
        final includedPart = partState.includedPart;
        if (includedPart != null) {
          final partFile = includedPart.file;
          final partUnitNode = partFile.parse();
          final unitElement = CompilationUnitElementImpl(
            source: partFile.source,
            librarySource: libraryFile.source,
            lineInfo: partUnitNode.lineInfo,
          );
          unitElement.isSynthetic = !partFile.exists;
          unitElement.uri = partFile.uriStr;
          unitElement.setCodeRange(0, partUnitNode.length);

          final unitReference = unitContainerRef.getChild(partFile.uriStr);
          _bindReference(unitReference, unitElement);

          linkingUnits.add(
            LinkingUnit(
              isDefiningUnit: false,
              reference: unitReference,
              node: partUnitNode,
              element: unitElement,
            ),
          );

          directiveUri = DirectiveUriWithUnitImpl(
            relativeUriString: partState.uri.relativeUriStr,
            relativeUri: partState.uri.relativeUri,
            unit: unitElement,
          );
        } else {
          directiveUri = DirectiveUriWithSourceImpl(
            relativeUriString: partState.uri.relativeUriStr,
            relativeUri: partState.uri.relativeUri,
            source: partState.includedFile.source,
          );
        }
      } else if (uriState is file_state.DirectiveUriWithSource) {
        directiveUri = DirectiveUriWithSourceImpl(
          relativeUriString: uriState.relativeUriStr,
          relativeUri: uriState.relativeUri,
          source: uriState.source,
        );
      } else if (uriState is file_state.DirectiveUriWithUri) {
        directiveUri = DirectiveUriWithRelativeUriImpl(
          relativeUriString: uriState.relativeUriStr,
          relativeUri: uriState.relativeUri,
        );
      } else if (uriState is file_state.DirectiveUriWithString) {
        directiveUri = DirectiveUriWithRelativeUriStringImpl(
          relativeUriString: uriState.relativeUriStr,
        );
      } else {
        directiveUri = DirectiveUriImpl();
      }

      parts.add(
        PartElementImpl(
          uri: directiveUri,
        ),
      );
    }

    libraryElement.parts2 = parts;

    final builder = LibraryBuilder._(
      linker: linker,
      kind: inputLibrary,
      uri: libraryFile.uri,
      reference: libraryReference,
      element: libraryElement,
      units: linkingUnits,
    );

    linker.builders[builder.uri] = builder;
  }

  static void _bindReference(Reference reference, ElementImpl element) {
    reference.element = element;
    element.reference = reference;
  }
}

class LinkingUnit {
  final bool isDefiningUnit;
  final Reference reference;
  final ast.CompilationUnitImpl node;
  final CompilationUnitElementImpl element;

  LinkingUnit({
    required this.isDefiningUnit,
    required this.reference,
    required this.node,
    required this.element,
  });
}

class _FlushElementOffsets extends GeneralizingElementVisitor<void> {
  @override
  void visitElement(covariant ElementImpl element) {
    element.isTempAugmentation = true;
    element.nameOffset = -1;
    if (element is ConstructorElementImpl) {
      element.periodOffset = null;
      element.nameEnd = null;
    }
    super.visitElement(element);
  }
}

extension<T> on T? {
  R? mapOrNull<R>(R Function(T) mapper) {
    final self = this;
    return self != null ? mapper(self) : null;
  }
}
