// Copyright (c) 2016, 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:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:kernel/ast.dart' show Library, Version;

import '../base/export.dart' show Export;
import '../base/loader.dart' show Loader;
import '../base/messages.dart'
    show
        FormattedMessage,
        LocatedMessage,
        Message,
        ProblemReporting,
        templateInternalProblemConstructorNotFound,
        templateInternalProblemNotFoundIn,
        templateInternalProblemPrivateConstructorAccess;
import '../base/name_space.dart';
import '../base/problems.dart' show internalProblem;
import '../source/name_scheme.dart';
import 'builder.dart';
import 'compilation_unit.dart';
import 'constructor_builder.dart';
import 'declaration_builders.dart';
import 'factory_builder.dart';
import 'member_builder.dart';
import 'type_builder.dart';

abstract class LibraryBuilder implements Builder, ProblemReporting {
  NameSpace get libraryNameSpace;

  ComputedNameSpace get exportNameSpace;

  List<Export> get exporters;

  LibraryBuilder? get partOfLibrary;

  LibraryBuilder get nameOriginBuilder;

  bool get mayImplementRestrictedTypes;

  bool get isPart;

  Loader get loader;

  /// Returns the [Library] built by this builder.
  Library get library;

  LibraryName get libraryName;

  @override
  Uri get fileUri;

  /// Returns the [Uri]s for the libraries that this library depend upon, either
  /// through import or export.
  Iterable<Uri> get dependencies;

  /// Returns the import uri for the library.
  ///
  /// This is the canonical uri for the library, for instance 'dart:core'.
  Uri get importUri;

  /// Returns the language [Version] used for this library.
  Version get languageVersion;

  /// If true, the library is not supported through the 'dart.library.*' value
  /// used in conditional imports and `bool.fromEnvironment` constants.
  bool get isUnsupported;

  /// [Iterator] for all declarations declared in this library of type [T].
  ///
  /// If [includeDuplicates] is `true`, duplicate declarations are included.
  Iterator<T> filteredMembersIterator<T extends NamedBuilder>(
      {required bool includeDuplicates});

  /// Looks up [constructorName] in the class named [className].
  ///
  /// The class is looked up in this library's export scope unless
  /// [bypassLibraryPrivacy] is true, in which case it is looked up in the
  /// library scope of this library.
  ///
  /// It is an error if no such class is found, or if the class doesn't have a
  /// matching constructor (or factory).
  ///
  /// If [constructorName] is null or the empty string, it's assumed to be an
  /// unnamed constructor. it's an error if [constructorName] starts with
  /// `"_"`, and [bypassLibraryPrivacy] is false.
  MemberBuilder getConstructor(String className,
      {String constructorName, bool bypassLibraryPrivacy = false});

  void becomeCoreLibrary();

  /// Lookups the member [name] declared in this library.
  ///
  /// If [required] is `true` and no member is found an internal problem is
  /// reported.
  NamedBuilder? lookupLocalMember(String name, {bool required = false});

  void recordAccess(
      CompilationUnit accessor, int charOffset, int length, Uri fileUri);

  /// Returns `true` if [typeDeclarationBuilder] is the 'Function' class defined
  /// in [coreLibrary].
  static bool isFunction(TypeDeclarationBuilder? typeDeclarationBuilder,
      LibraryBuilder coreLibrary) {
    return typeDeclarationBuilder is ClassBuilder &&
        typeDeclarationBuilder.name == 'Function' &&
        typeDeclarationBuilder.libraryBuilder == coreLibrary;
  }

  /// Returns `true` if [typeDeclarationBuilder] is the 'Record' class defined
  /// in [coreLibrary].
  static bool isRecord(TypeDeclarationBuilder? typeDeclarationBuilder,
      LibraryBuilder coreLibrary) {
    return typeDeclarationBuilder is ClassBuilder &&
        typeDeclarationBuilder.name == 'Record' &&
        typeDeclarationBuilder.libraryBuilder == coreLibrary;
  }
}

abstract class LibraryBuilderImpl extends BuilderImpl
    implements LibraryBuilder {
  @override
  final Uri fileUri;

  LibraryBuilderImpl(this.fileUri);

  @override
  // Coverage-ignore(suite): Not run.
  bool get isSynthetic => false;

  @override
  // Coverage-ignore(suite): Not run.
  Builder? get parent => null;

  @override
  int get fileOffset => -1;

  @override
  bool get isPart => false;

  @override
  Loader get loader;

  @override
  Uri get importUri;

  @override
  FormattedMessage? addProblem(
      Message message, int charOffset, int length, Uri? fileUri,
      {bool wasHandled = false,
      List<LocatedMessage>? context,
      Severity? severity,
      bool problemOnLibrary = false}) {
    fileUri ??= this.fileUri;

    return loader.addProblem(message, charOffset, length, fileUri,
        wasHandled: wasHandled,
        context: context,
        severity: severity,
        problemOnLibrary: true);
  }

  @override
  MemberBuilder getConstructor(String className,
      {String? constructorName, bool bypassLibraryPrivacy = false}) {
    constructorName ??= "";
    if (constructorName.startsWith("_") && !bypassLibraryPrivacy) {
      return internalProblem(
          templateInternalProblemPrivateConstructorAccess
              .withArguments(constructorName),
          -1,
          null);
    }
    Builder? cls = (bypassLibraryPrivacy ? libraryNameSpace : exportNameSpace)
        .lookupLocalMember(className)
        ?.getable;
    if (cls is TypeAliasBuilder) {
      // Coverage-ignore-block(suite): Not run.
      TypeAliasBuilder aliasBuilder = cls;
      // No type arguments are available, but this method is only called in
      // order to find constructors of specific non-generic classes (errors),
      // so we can pass the empty list.
      cls = aliasBuilder.unaliasDeclaration(const <TypeBuilder>[]);
    }
    if (cls is ClassBuilder) {
      // TODO(ahe): This code is similar to code in `endNewExpression` in
      // `body_builder.dart`, try to share it.
      MemberBuilder? constructor =
          cls.findConstructorOrFactory(constructorName, -1, fileUri, this);
      if (constructor == null) {
        // Fall-through to internal error below.
      } else if (constructor is ConstructorBuilder) {
        if (!cls.isAbstract) {
          return constructor;
        }
      }
      // Coverage-ignore(suite): Not run.
      else if (constructor is FactoryBuilder) {
        return constructor;
      }
    }
    // Coverage-ignore-block(suite): Not run.
    throw internalProblem(
        templateInternalProblemConstructorNotFound.withArguments(
            "$className.$constructorName", importUri),
        -1,
        null);
  }

  @override
  NamedBuilder? lookupLocalMember(String name, {bool required = false}) {
    NamedBuilder? builder = libraryNameSpace.lookupLocalMember(name)?.getable;
    if (required && builder == null) {
      internalProblem(
          templateInternalProblemNotFoundIn.withArguments(
              name, fullNameForErrors),
          -1,
          null);
    }
    return builder;
  }

  @override
  void recordAccess(
      CompilationUnit accessor, int charOffset, int length, Uri fileUri) {}

  @override
  String toString() {
    return '$runtimeType(${isPart ? fileUri : importUri})';
  }
}
