// Copyright (c) 2022, 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:async';

import 'package:_js_interop_checks/src/transformations/static_interop_class_eraser.dart';
import 'package:collection/collection.dart';
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:front_end/src/fasta/kernel/utils.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
import 'package:kernel/target/targets.dart' hide DiagnosticReporter;
import 'package:kernel/type_environment.dart' as ir;
import 'package:kernel/verifier.dart';

import '../../compiler_api.dart' as api;
import '../commandline_options.dart';
import '../common.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../environment.dart';
import '../ir/annotations.dart';
import '../ir/constants.dart';
import '../kernel/dart2js_target.dart'
    show
        Dart2jsConstantsBackend,
        Dart2jsDartLibrarySupport,
        Dart2jsTarget,
        implicitlyUsedLibraries;
import '../kernel/front_end_adapter.dart';
import '../kernel/transformations/global/transform.dart' as globalTransforms;
import '../options.dart';

class Input {
  final CompilerOptions options;
  final api.CompilerInput compilerInput;
  final DiagnosticReporter reporter;

  /// Shared state between compilations. Only used when loading from source.
  final fe.InitializedCompilerState? initializedCompilerState;

  // TODO(johnniwinther): Remove this when #34942 is fixed.
  /// Force in-memory serialization/deserialization of the loaded component.
  ///
  /// This is used for testing.
  final bool forceSerialization;

  Input(this.options, this.compilerInput, this.reporter,
      this.initializedCompilerState, this.forceSerialization);
}

/// Result of invoking the CFE to produce the kernel IR.
class Output {
  final ir.Component component;

  /// The [Uri] of the root library containing main.
  /// Note: rootLibraryUri will be null for some modules, for example in the
  /// case of dependent libraries processed modularly.
  final Uri? rootLibraryUri;

  /// Returns the [Uri]s of all libraries that have been loaded that are
  /// reachable from the [rootLibraryUri].
  ///
  /// Note that [component] may contain some libraries that are excluded here.
  final List<Uri>? libraries;

  final fe.InitializedCompilerState? initializedCompilerState;

  Output withNewComponent(ir.Component component) =>
      Output(component, rootLibraryUri, libraries, initializedCompilerState);

  Output(this.component, this.rootLibraryUri, this.libraries,
      this.initializedCompilerState);
}

Library _findEntryLibrary(Component component, Uri entryUri) {
  final entryLibrary =
      component.libraries.firstWhereOrNull((l) => l.fileUri == entryUri);
  if (entryLibrary == null) {
    throw ArgumentError('Entry uri $entryUri not found in dill.');
  }
  return entryLibrary;
}

ir.Reference _findMainMethod(Library entryLibrary) {
  var mainMethod =
      entryLibrary.procedures.firstWhereOrNull((p) => p.name.text == 'main');

  // In some cases, a main method is defined in another file, and then
  // exported. In these cases, we search for the main method in
  // [additionalExports].
  ir.Reference? mainMethodReference;
  if (mainMethod == null) {
    mainMethodReference = entryLibrary.additionalExports
        .firstWhereOrNull((p) => p.canonicalName?.name == 'main');
  } else {
    mainMethodReference = mainMethod.reference;
  }
  if (mainMethodReference == null) {
    throw ArgumentError(
        'Entry uri ${entryLibrary.fileUri} has no main method.');
  }
  return mainMethodReference;
}

String _getPlatformFilename(CompilerOptions options, String targetName) {
  String unsoundMarker = options.useLegacySubtyping ? "_unsound" : "";
  return "${targetName}_platform$unsoundMarker.dill";
}

class _LoadFromKernelResult {
  final ir.Component? component;
  final Library? entryLibrary;

  _LoadFromKernelResult(this.component, this.entryLibrary);
}

void _simplifyConstConditionals(ir.Component component, CompilerOptions options,
    ir.ClassHierarchy classHierarchy, DiagnosticReporter reporter) {
  void reportMessage(
      fe.LocatedMessage message, List<fe.LocatedMessage>? context) {
    reportLocatedMessage(reporter, message, context);
  }

  bool shouldNotInline(ir.TreeNode node) {
    if (node is! ir.Annotatable) {
      return false;
    }
    return computePragmaAnnotationDataFromIr(node).any((pragma) =>
        pragma == const PragmaAnnotationData('noInline') ||
        pragma == const PragmaAnnotationData('never-inline'));
  }

  fe.ConstConditionalSimplifier(
          const Dart2jsDartLibrarySupport(),
          const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
          component,
          reportMessage,
          environmentDefines: options.environment,
          classHierarchy: classHierarchy,
          evaluationMode: options.useLegacySubtyping
              ? fe.EvaluationMode.weak
              : fe.EvaluationMode.strong,
          shouldNotInline: shouldNotInline)
      .run();
}

// Perform any backend-specific transforms here that can be done on both
// serialized components and components from source.
void _doTransformsOnKernelLoad(
    Component component, CompilerOptions options, DiagnosticReporter reporter) {
  if (options.stage.shouldRunGlobalTransforms) {
    ir.CoreTypes coreTypes = ir.CoreTypes(component);
    // Ignore ambiguous supertypes.
    final classHierarchy = ir.ClassHierarchy(component, coreTypes,
        onAmbiguousSupertypes: (_, __, ___) {});
    ir.TypeEnvironment typeEnvironment =
        ir.TypeEnvironment(coreTypes, classHierarchy);
    final constantsEvaluator = Dart2jsConstantEvaluator(
        component,
        typeEnvironment,
        (fe.LocatedMessage message, List<fe.LocatedMessage>? context) =>
            reportLocatedMessage(reporter, message, context),
        environment: Environment(options.environment),
        evaluationMode: options.useLegacySubtyping
            ? fe.EvaluationMode.weak
            : fe.EvaluationMode.strong);
    StaticInteropClassEraser(coreTypes).visitComponent(component);
    globalTransforms.transformLibraries(
        component.libraries, constantsEvaluator, coreTypes, options);
    _simplifyConstConditionals(component, options, classHierarchy, reporter);
  }
}

Future<_LoadFromKernelResult> _loadFromKernel(
    CompilerOptions options,
    api.CompilerInput compilerInput,
    String targetName,
    DiagnosticReporter reporter) async {
  Library? entryLibrary;
  var resolvedUri = options.compilationTarget;
  ir.Component component = ir.Component();

  Future<void> read(Uri uri) async {
    api.Input<List<int>> input =
        await compilerInput.readFromUri(uri, inputKind: api.InputKind.binary);
    BinaryBuilder(input.data).readComponent(component);
  }

  await read(resolvedUri);

  var isStrongDill =
      component.mode == ir.NonNullableByDefaultCompiledMode.Strong;
  var incompatibleNullSafetyMode =
      isStrongDill ? NullSafetyMode.unsound : NullSafetyMode.sound;
  if (options.nullSafetyMode == incompatibleNullSafetyMode) {
    var dillMode = isStrongDill ? 'sound' : 'unsound';
    var option = isStrongDill ? Flags.noSoundNullSafety : Flags.soundNullSafety;
    throw ArgumentError("$resolvedUri was compiled with $dillMode null "
        "safety and is incompatible with the '$option' option");
  }

  if (options.platformBinaries != null &&
      options.stage.shouldReadPlatformBinaries) {
    var platformUri = options.platformBinaries
        ?.resolve(_getPlatformFilename(options, targetName));
    // TODO(joshualitt): Change how we detect this case so it is less
    // brittle.
    if (platformUri != resolvedUri) await read(platformUri!);
  }

  // Concatenate dills.
  if (options.dillDependencies != null) {
    for (Uri dependency in options.dillDependencies!) {
      await read(dependency);
    }
  }

  if (options.entryUri != null) {
    entryLibrary = _findEntryLibrary(component, options.entryUri!);
    var mainMethod = _findMainMethod(entryLibrary);
    component.setMainMethodAndMode(mainMethod, true, component.mode);
  }

  _doTransformsOnKernelLoad(component, options, reporter);
  registerSources(component, compilerInput);
  return _LoadFromKernelResult(component, entryLibrary);
}

class _LoadFromSourceResult {
  final ir.Component? component;
  final fe.InitializedCompilerState initializedCompilerState;

  _LoadFromSourceResult(this.component, this.initializedCompilerState);
}

Future<_LoadFromSourceResult> _loadFromSource(
    CompilerOptions options,
    api.CompilerInput compilerInput,
    DiagnosticReporter reporter,
    fe.InitializedCompilerState? initializedCompilerState,
    String targetName) async {
  bool verbose = false;
  bool cfeConstants = options.features.cfeConstants.isEnabled;
  Map<String, String>? environment = cfeConstants ? options.environment : null;
  Target target = Dart2jsTarget(
      targetName,
      TargetFlags(
          soundNullSafety: options.nullSafetyMode == NullSafetyMode.sound),
      options: options,
      supportsUnevaluatedConstants: !cfeConstants);
  fe.FileSystem fileSystem = CompilerFileSystem(compilerInput);
  fe.Verbosity verbosity = options.verbosity;
  fe.DiagnosticMessageHandler onDiagnostic = (fe.DiagnosticMessage message) {
    if (fe.Verbosity.shouldPrint(verbosity, message)) {
      reportFrontEndMessage(reporter, message);
    }
  };

  List<Uri> sources = [options.compilationTarget];

  fe.CompilerOptions feOptions = fe.CompilerOptions()
    ..target = target
    ..librariesSpecificationUri = options.librariesSpecificationUri
    ..packagesFileUri = options.packageConfig
    ..explicitExperimentalFlags = options.explicitExperimentalFlags
    ..environmentDefines = environment
    ..verbose = verbose
    ..fileSystem = fileSystem
    ..onDiagnostic = onDiagnostic
    ..verbosity = verbosity;
  Uri resolvedUri = options.compilationTarget;
  bool isLegacy = await fe.uriUsesLegacyLanguageVersion(resolvedUri, feOptions);
  if (isLegacy && options.experimentNullSafetyChecks) {
    reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
      'text': 'The ${Flags.experimentNullSafetyChecks} option may be used '
          'only after all libraries have been migrated to null safety. Some '
          'libraries reached from $resolvedUri are still opted out of null '
          'safety. Please migrate these libraries before passing '
          '${Flags.experimentNullSafetyChecks}.',
    });
  }
  if (isLegacy && options.nullSafetyMode == NullSafetyMode.sound) {
    reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
      'text': "Starting with Dart 3.0, `dart compile js` expects programs to "
          "be null-safe by default. Some libraries reached from $resolvedUri "
          "are opted out of null safety. You can temporarily compile this "
          "application using the deprecated '${Flags.noSoundNullSafety}' "
          "option."
    });
  }

  List<Uri> dependencies = [];
  if (options.platformBinaries != null) {
    dependencies.add(options.platformBinaries!
        .resolve(_getPlatformFilename(options, targetName)));
  }
  if (options.dillDependencies != null) {
    dependencies.addAll(options.dillDependencies!);
  }

  initializedCompilerState = fe.initializeCompiler(
      initializedCompilerState,
      target,
      options.librariesSpecificationUri,
      dependencies,
      options.packageConfig,
      explicitExperimentalFlags: options.explicitExperimentalFlags,
      environmentDefines: environment,
      nnbdMode:
          options.useLegacySubtyping ? fe.NnbdMode.Weak : fe.NnbdMode.Strong,
      invocationModes: options.cfeInvocationModes,
      verbosity: verbosity);
  ir.Component? component = await fe.compile(
      initializedCompilerState, verbose, fileSystem, onDiagnostic, sources);

  if (component != null) {
    assert(() {
      verifyComponent(
          target, VerificationStage.afterModularTransformations, component);
      return true;
    }());

    _doTransformsOnKernelLoad(component, options, reporter);

    registerSources(component, compilerInput);
  }

  return _LoadFromSourceResult(component, initializedCompilerState);
}

Output _createOutput(
    CompilerOptions options,
    DiagnosticReporter reporter,
    Library? entryLibrary,
    ir.Component component,
    fe.InitializedCompilerState? initializedCompilerState) {
  Uri? rootLibraryUri = null;
  Iterable<ir.Library> libraries = component.libraries;
  if (component.mainMethod == null) {
    // TODO(sigmund): move this so that we use the same error template
    // from the CFE.
    reporter.reportError(reporter.createMessage(NO_LOCATION_SPANNABLE,
        MessageKind.GENERIC, {'text': "No 'main' method found."}));
  }

  // If we are building from dill and are passed an [entryUri], then we use
  // that to find the appropriate [entryLibrary]. Otherwise, we fallback to
  // the [enclosingLibrary] of the [mainMethod].
  // NOTE: Under some circumstances, the [entryLibrary] exports the
  // [mainMethod] from another library, and thus the [enclosingLibrary] of
  // the [mainMethod] may not be the same as the [entryLibrary].
  var root = entryLibrary ?? component.mainMethod!.enclosingLibrary;
  rootLibraryUri = root.importUri;

  // Filter unreachable libraries: [Component] was built by linking in the
  // entire SDK libraries, not all of them are used. We include anything
  // that is reachable from `main`. Note that all internal libraries that
  // the compiler relies on are reachable from `dart:core`.
  var seen = Set<Library>();
  void search(ir.Library current) {
    if (!seen.add(current)) return;
    for (ir.LibraryDependency dep in current.dependencies) {
      search(dep.targetLibrary);
    }
  }

  search(root);

  // Libraries dependencies do not show implicit imports to certain internal
  // libraries.
  const Set<String> alwaysInclude = {
    'dart:_internal',
    'dart:core',
    'dart:async',
    ...implicitlyUsedLibraries,
  };
  for (String uri in alwaysInclude) {
    Library library = component.libraries.firstWhere((lib) {
      return '${lib.importUri}' == uri;
    });
    search(library);
  }

  libraries = libraries.where(seen.contains);
  return Output(component, rootLibraryUri,
      libraries.map((lib) => lib.importUri).toList(), initializedCompilerState);
}

/// Loads an entire Kernel [Component] from a file on disk.
Future<Output?> run(Input input) async {
  CompilerOptions options = input.options;
  api.CompilerInput compilerInput = input.compilerInput;
  DiagnosticReporter reporter = input.reporter;

  String targetName = options.compileForServer ? "dart2js_server" : "dart2js";

  Library? entryLibrary;
  ir.Component? component;
  fe.InitializedCompilerState? initializedCompilerState =
      input.initializedCompilerState;
  if (options.shouldLoadFromDill) {
    _LoadFromKernelResult result =
        await _loadFromKernel(options, compilerInput, targetName, reporter);
    component = result.component;
    entryLibrary = result.entryLibrary;
  } else {
    _LoadFromSourceResult result = await _loadFromSource(options, compilerInput,
        reporter, input.initializedCompilerState, targetName);
    component = result.component;
    initializedCompilerState = result.initializedCompilerState;
  }
  if (component == null) return null;
  if (input.forceSerialization) {
    // TODO(johnniwinther): Remove this when #34942 is fixed.
    List<int> data = serializeComponent(component);
    component = ir.Component();
    BinaryBuilder(data).readComponent(component);
    // Ensure we use the new deserialized entry point library.
    entryLibrary = _findEntryLibrary(component, options.entryUri!);
  }
  return _createOutput(
      options, reporter, entryLibrary, component, initializedCompilerState);
}

/// Registers with the dart2js compiler all sources embedded in a kernel
/// component. This may include sources that were read from disk directly as
/// files, but also sources that were embedded in binary `.dill` files (like the
/// platform kernel file).
///
/// This registration improves how locations are presented when errors
/// or crashes are reported by the dart2js compiler.
void registerSources(ir.Component component, api.CompilerInput compilerInput) {
  component.uriToSource.forEach((uri, source) {
    compilerInput.registerUtf8ContentsForDiagnostics(uri, source.source);
  });
}
