// 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 'dart:collection' show Queue;

import 'package:_fe_analyzer_shared/src/messages/severity.dart'
    show CfeSeverity;
import 'package:kernel/ast.dart'
    show Class, Component, DartType, ExtensionTypeDeclaration, Library;

import '../base/crash.dart' show firstSourceUri;
import '../base/loader.dart';
import '../base/messages.dart'
    show
        FormattedMessage,
        LocatedMessage,
        Message,
        noLength,
        SummaryTemplate,
        Template,
        codePlatformPrivateLibraryAccess,
        codeInternalProblemContextSeverity;
import '../base/problems.dart' show internalProblem;
import '../base/ticker.dart' show Ticker;
import '../base/uris.dart';
import '../builder/compilation_unit.dart';
import '../builder/declaration_builders.dart';
import '../builder/library_builder.dart';
import '../builder/type_builder.dart';
import '../codes/cfe_codes.dart'
    show SummaryTemplate, Template, codeDillOutlineSummary;
import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
import '../source/source_loader.dart' show SourceLoader;
import 'dill_library_builder.dart' show DillLibraryBuilder;
import 'dill_target.dart' show DillTarget;

class DillLoader extends Loader {
  SourceLoader? currentSourceLoader;

  final Map<Uri, DillLibraryBuilder> _knownLibraryBuilders =
      <Uri, DillLibraryBuilder>{};

  final Map<Uri, DillLibraryBuilder> _builders = <Uri, DillLibraryBuilder>{};

  final Queue<DillLibraryBuilder> _unparsedLibraries =
      new Queue<DillLibraryBuilder>();

  final List<Library> libraries = <Library>[];

  final DillTarget target;

  /// List of all handled compile-time errors seen so far by libraries loaded
  /// by this loader.
  ///
  /// A handled error is an error that has been added to the generated AST
  /// already, for example, as a throw expression.
  final List<LocatedMessage> handledErrors = <LocatedMessage>[];

  /// List of all unhandled compile-time errors seen so far by libraries loaded
  /// by this loader.
  ///
  /// An unhandled error is an error that hasn't been handled, see
  /// [handledErrors].
  final List<LocatedMessage> unhandledErrors = <LocatedMessage>[];

  final Set<String> seenMessages = new Set<String>();

  DillLibraryBuilder? _coreLibrary;

  /// The first compilation unit loaded by this [DillLoader].
  // TODO(johnniwinther): Do we need this?
  CompilationUnit? first;

  int byteCount = 0;

  DillLoader(this.target);

  @override
  LibraryBuilder get coreLibrary => _coreLibrary!;

  @override
  CompilationUnit get coreLibraryCompilationUnit =>
      _coreLibrary!.mainCompilationUnit;

  Ticker get ticker => target.ticker;

  void registerKnownLibrary(Library library) {
    _knownLibraryBuilders[library.importUri] = new DillLibraryBuilder(
      library,
      this,
    );
  }

  /// Look up a library builder by the [uri], or if such doesn't exist, create
  /// one. The canonical URI of the library is [uri], and its actual location is
  /// [fileUri].
  ///
  /// Canonical URIs have schemes like "dart", or "package", and the actual
  /// location is often a file URI.
  ///
  /// The [accessor] is the library that's trying to import, export, or include
  /// as part [uri], and [charOffset] is the location of the corresponding
  /// directive. If [accessor] isn't allowed to access [uri], it's a
  /// compile-time error.
  DillLibraryBuilder read(
    Uri uri,
    int charOffset, {
    CompilationUnit? accessor,
  }) {
    DillLibraryBuilder? libraryBuilder = _builders[uri];
    if (libraryBuilder == null) {
      libraryBuilder = _knownLibraryBuilders.remove(uri);
      assert(libraryBuilder != null, "No library found for $uri.");
      _builders[uri] = libraryBuilder!;
      assert(libraryBuilder.loader == this);
      if (uri.isScheme("dart")) {
        if (uri.path == "core") {
          _coreLibrary = libraryBuilder;
        }
      }
      {
        // Add any additional logic after this block. Setting the
        // firstSourceUri and first library should be done as early as
        // possible.
        firstSourceUri ??= uri;
        first ??= libraryBuilder.mainCompilationUnit;
      }
      if (_coreLibrary == libraryBuilder) {
        target.loadExtraRequiredLibraries(this);
      }
      if (target.backendTarget.mayDefineRestrictedType(uri)) {
        libraryBuilder.mayImplementRestrictedTypes = true;
      }
      _unparsedLibraries.addLast(libraryBuilder);
    }
    if (accessor != null) {
      libraryBuilder.recordAccess(
        accessor,
        charOffset,
        noLength,
        accessor.fileUri,
      );
      if (!accessor.isAugmenting &&
          !accessor.isPart &&
          !target.backendTarget.allowPlatformPrivateLibraryAccess(
            accessor.importUri,
            uri,
          )) {
        // Coverage-ignore-block(suite): Not run.
        accessor.addProblem(
          codePlatformPrivateLibraryAccess,
          charOffset,
          noLength,
          accessor.fileUri,
        );
      }
    }
    return libraryBuilder;
  }

  void _ensureCoreLibrary() {
    if (_coreLibrary == null) {
      // Coverage-ignore-block(suite): Not run.
      read(Uri.parse("dart:core"), 0, accessor: first);
      // TODO(askesc): When all backends support set literals, we no longer
      // need to index dart:collection, as it is only needed for desugaring of
      // const sets. We can remove it from this list at that time.
      read(Uri.parse("dart:collection"), 0, accessor: first);
      assert(_coreLibrary != null);
    }
  }

  void buildOutlines() {
    _ensureCoreLibrary();
    while (_unparsedLibraries.isNotEmpty) {
      DillLibraryBuilder library = _unparsedLibraries.removeFirst();
      buildOutline(library);
    }
    _logSummary(outlineSummaryTemplate);
  }

  void _logSummary(Template<SummaryTemplate, Function> template) {
    ticker.log(
      // Coverage-ignore(suite): Not run.
      (Duration elapsed, Duration sinceStart) {
        int libraryCount = 0;
        for (DillLibraryBuilder library in libraryBuilders) {
          assert(library.loader == this);
          libraryCount++;
        }
        double ms =
            elapsed.inMicroseconds / Duration.microsecondsPerMillisecond;
        Message message = template.withArgumentsOld(
          libraryCount,
          byteCount,
          ms,
          byteCount / ms,
          ms / libraryCount,
        );
        print("$sinceStart: ${message.problemMessage}");
      },
    );
  }

  /// Register [message] as a problem with a severity determined by the
  /// intrinsic severity of the message.
  // TODO(johnniwinther): Avoid the need for this. If this is ever used, it is
  // inconsistent with messages reported through the [SourceLoader] since they
  // each have their own list of unhandled/unhandled errors and seen messages,
  // and only those of the [SourceLoader] are used elsewhere. Use
  // [currentSourceLoader] to forward messages to the [SourceLoader] instead.
  @override
  FormattedMessage? addProblem(
    Message message,
    int charOffset,
    int length,
    Uri? fileUri, {
    bool wasHandled = false,
    List<LocatedMessage>? context,
    CfeSeverity? severity,
    bool problemOnLibrary = false,
    List<Uri>? involvedFiles,
  }) {
    return _addMessage(
      message,
      charOffset,
      length,
      fileUri,
      severity,
      wasHandled: wasHandled,
      context: context,
      problemOnLibrary: problemOnLibrary,
      involvedFiles: involvedFiles,
    );
  }

  /// All messages reported by the compiler (errors, warnings, etc.) are routed
  /// through this method.
  ///
  /// Returns a FormattedMessage if the message is new, that is, not previously
  /// reported. This is important as some parser errors may be reported up to
  /// three times by `OutlineBuilder`, `DietListener`, and `BodyBuilder`.
  /// If the message is not new, [null] is reported.
  ///
  /// If [severity] is `Severity.error`, the message is added to
  /// [handledErrors] if [wasHandled] is true or to [unhandledErrors] if
  /// [wasHandled] is false.
  FormattedMessage? _addMessage(
    Message message,
    int charOffset,
    int length,
    Uri? fileUri,
    CfeSeverity? severity, {
    bool wasHandled = false,
    List<LocatedMessage>? context,
    bool problemOnLibrary = false,
    List<Uri>? involvedFiles,
  }) {
    assert(
      fileUri != missingUri,
      "Message unexpectedly reported on missing uri.",
    );
    severity ??= message.code.severity;
    if (severity == CfeSeverity.ignored) return null;
    String trace =
        """
message: ${message.problemMessage}
charOffset: $charOffset
fileUri: $fileUri
severity: $severity
""";
    if (!seenMessages.add(trace)) return null;
    if (message.code.severity == CfeSeverity.context) {
      internalProblem(
        codeInternalProblemContextSeverity.withArgumentsOld(message.code.name),
        charOffset,
        fileUri,
      );
    }
    target.context.report(
      fileUri != null
          ? message.withLocation(fileUri, charOffset, length)
          :
            // Coverage-ignore(suite): Not run.
            message.withoutLocation(),
      severity,
      context: context,
      involvedFiles: involvedFiles,
    );
    if (severity == CfeSeverity.error) {
      (wasHandled
              ?
                // Coverage-ignore(suite): Not run.
                handledErrors
              : unhandledErrors)
          .add(
            fileUri != null
                ? message.withLocation(fileUri, charOffset, length)
                :
                  // Coverage-ignore(suite): Not run.
                  message.withoutLocation(),
          );
    }
    FormattedMessage formattedMessage = target.createFormattedMessage(
      message,
      charOffset,
      length,
      fileUri,
      context,
      severity,
      involvedFiles: involvedFiles,
    );
    return formattedMessage;
  }

  Template<SummaryTemplate, Function> get outlineSummaryTemplate =>
      codeDillOutlineSummary;

  /// Append compiled libraries from the given [component]. If the [filter] is
  /// provided, append only libraries whose [Uri] is accepted by the [filter].
  List<DillLibraryBuilder> appendLibraries(
    Component component, {
    bool Function(Uri uri)? filter,
    int byteCount = 0,
  }) {
    List<Library> componentLibraries = component.libraries;
    List<Uri> requestedLibraries = <Uri>[];
    for (int i = 0; i < componentLibraries.length; i++) {
      Library library = componentLibraries[i];
      Uri uri = library.importUri;
      if (filter == null ||
          // Coverage-ignore(suite): Not run.
          filter(library.importUri)) {
        libraries.add(library);
        registerKnownLibrary(library);
        requestedLibraries.add(uri);
      }
    }
    List<DillLibraryBuilder> result = <DillLibraryBuilder>[];
    for (int i = 0; i < requestedLibraries.length; i++) {
      result.add(read(requestedLibraries[i], -1));
    }
    target.uriToSource.addAll(component.uriToSource);
    this.byteCount += byteCount;
    return result;
  }

  /// Append single compiled library.
  ///
  /// Note that as this only takes a library, no new sources is added to the
  /// uriToSource map.
  DillLibraryBuilder appendLibrary(Library library) {
    // Add to list of libraries in the loader, used for e.g. linking.
    libraries.add(library);

    // Weird interaction begins.
    //
    // Create dill library builder (adds it to a map where it's fetched
    // again momentarily).
    registerKnownLibrary(library);
    // Set up the dill library builder (fetch it from the map again, add it to
    // another map and setup some auxiliary things).
    return read(library.importUri, -1);
  }

  void buildOutline(DillLibraryBuilder builder) {
    builder.markAsReadyToBuild();
  }

  void finalizeExports({bool suppressFinalizationErrors = false}) {
    for (DillLibraryBuilder builder in libraryBuilders) {
      builder.markAsReadyToFinalizeExports(
        suppressFinalizationErrors: suppressFinalizationErrors,
      );
    }
  }

  @override
  ClassBuilder computeClassBuilderFromTargetClass(Class cls) {
    ClassBuilder? classBuilder = currentSourceLoader?.referenceMap
        .lookupClassBuilder(cls.reference);
    if (classBuilder != null) {
      return classBuilder;
    }
    Library kernelLibrary = cls.enclosingLibrary;
    LibraryBuilder? library = lookupLibraryBuilder(kernelLibrary.importUri);
    if (library == null) {
      // Coverage-ignore-block(suite): Not run.
      library = currentSourceLoader?.lookupLoadedLibraryBuilder(
        kernelLibrary.importUri,
      );
    }
    return library!.lookupRequiredLocalMember(cls.name) as ClassBuilder;
  }

  @override
  ExtensionTypeDeclarationBuilder
  computeExtensionTypeBuilderFromTargetExtensionType(
    ExtensionTypeDeclaration extensionType,
  ) {
    ExtensionTypeDeclarationBuilder? extensionTypeDeclarationBuilder =
        currentSourceLoader?.referenceMap.lookupExtensionTypeDeclarationBuilder(
          extensionType.reference,
        );
    if (extensionTypeDeclarationBuilder != null) {
      return extensionTypeDeclarationBuilder;
    }
    Library library = extensionType.enclosingLibrary;
    LibraryBuilder? libraryBuilder = lookupLibraryBuilder(library.importUri);
    if (libraryBuilder == null) {
      // Coverage-ignore-block(suite): Not run.
      libraryBuilder = currentSourceLoader?.lookupLoadedLibraryBuilder(
        library.importUri,
      );
    }
    return libraryBuilder!.lookupRequiredLocalMember(extensionType.name)
        as ExtensionTypeDeclarationBuilder;
  }

  late TypeBuilderComputer _typeBuilderComputer = new TypeBuilderComputer(this);

  @override
  TypeBuilder computeTypeBuilder(DartType type) {
    return _typeBuilderComputer.visit(type);
  }

  // Coverage-ignore(suite): Not run.
  bool containsLibraryBuilder(Uri importUri) =>
      _builders.containsKey(importUri);

  DillLibraryBuilder? lookupLibraryBuilder(Uri importUri) =>
      _builders[importUri];

  Iterable<DillLibraryBuilder> get libraryBuilders => _builders.values;

  // Coverage-ignore(suite): Not run.
  Iterable<Uri> get libraryImportUris => _builders.keys;

  // Coverage-ignore(suite): Not run.
  void registerLibraryBuilder(DillLibraryBuilder libraryBuilder) {
    Uri importUri = libraryBuilder.importUri;
    libraryBuilder.loader = this;
    if (importUri.isScheme("dart") && importUri.path == "core") {
      _coreLibrary = libraryBuilder;
    }
    _builders[importUri] = libraryBuilder;
  }

  DillLibraryBuilder? deregisterLibraryBuilder(Uri importUri) {
    return _builders.remove(importUri);
  }
}
