// 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: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:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
import 'package:kernel/target/targets.dart' hide DiagnosticReporter;

import '../../compiler.dart' as api;
import '../commandline_options.dart';
import '../common.dart';
import '../kernel/front_end_adapter.dart';
import '../kernel/dart2js_target.dart' show Dart2jsTarget;
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;

  /// When running only dart2js modular analysis, returns the [Uri]s for
  /// libraries loaded in the input module.
  ///
  /// This excludes other libraries reachable from them that were loaded as
  /// dependencies. The result of [moduleLibraries] is always a subset of
  /// [libraries].
  final List<Uri> moduleLibraries;

  final fe.InitializedCompilerState initializedCompilerState;

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

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

ir.Reference _findMainMethod(Library entryLibrary) {
  var mainMethod = entryLibrary.procedures
      .firstWhere((p) => p.name.text == 'main', orElse: () => null);

  // 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
        .firstWhere((p) => p.canonicalName.name == 'main', orElse: () => null);
  } 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";
}

void _inferNullSafetyMode(CompilerOptions options, bool isSound) {
  if (options.nullSafetyMode == NullSafetyMode.unspecified) {
    options.nullSafetyMode =
        isSound ? NullSafetyMode.sound : NullSafetyMode.unsound;
  }
}

void _validateNullSafetyMode(CompilerOptions options) {
  assert(options.nullSafetyMode != NullSafetyMode.unspecified);
}

class _LoadFromKernelResult {
  final ir.Component component;
  final Library entryLibrary;
  final List<Uri> moduleLibraries;

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

Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options,
    api.CompilerInput compilerInput, String targetName) async {
  Library entryLibrary;
  var resolvedUri = options.compilationTarget;
  ir.Component component = ir.Component();
  List<Uri> moduleLibraries = [];

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

  await read(resolvedUri);

  if (options.modularMode) {
    moduleLibraries = component.libraries.map((lib) => lib.importUri).toList();
  }

  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");
  }
  _inferNullSafetyMode(options, isStrongDill);
  _validateNullSafetyMode(options);

  // Modular compiles do not include the platform on the input dill
  // either.
  if (options.platformBinaries != null) {
    var platformUri = options.platformBinaries
        .resolve(_getPlatformFilename(options, targetName));
    // Modular analysis can be run on the sdk by providing directly the
    // path to the platform.dill file. In that case, we do not load the
    // platform file implicitly.
    // 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);
  }
  return _LoadFromKernelResult(component, entryLibrary, moduleLibraries);
}

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;
  Target target = Dart2jsTarget(targetName, TargetFlags(), options: options);
  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);
    }
  };
  fe.CompilerOptions feOptions = fe.CompilerOptions()
    ..target = target
    ..librariesSpecificationUri = options.librariesSpecificationUri
    ..packagesFileUri = options.packageConfig
    ..explicitExperimentalFlags = options.explicitExperimentalFlags
    ..verbose = verbose
    ..fileSystem = fileSystem
    ..onDiagnostic = onDiagnostic
    ..verbosity = verbosity;
  Uri resolvedUri = options.compilationTarget;
  bool isLegacy = await fe.uriUsesLegacyLanguageVersion(resolvedUri, feOptions);
  _inferNullSafetyMode(options, !isLegacy);

  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,
      nnbdMode:
          options.useLegacySubtyping ? fe.NnbdMode.Weak : fe.NnbdMode.Strong,
      invocationModes: options.cfeInvocationModes,
      verbosity: verbosity);
  ir.Component component = await fe.compile(
      initializedCompilerState, verbose, fileSystem, onDiagnostic, resolvedUri);
  _validateNullSafetyMode(options);
  return _LoadFromSourceResult(component, initializedCompilerState);
}

Output _createOutput(
    CompilerOptions options,
    DiagnosticReporter reporter,
    Library entryLibrary,
    ir.Component component,
    List<Uri> moduleLibraries,
    fe.InitializedCompilerState initializedCompilerState) {
  Uri rootLibraryUri = null;
  Iterable<ir.Library> libraries = component.libraries;
  if (!options.modularMode) {
    // For non-modular builds we should always have a [mainMethod] at this
    // point.
    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>();
    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 `dart:core`.
    var dartCore = component.libraries.firstWhere((lib) {
      return lib.importUri.isScheme('dart') && lib.importUri.path == 'core';
    });
    search(dartCore);

    libraries = libraries.where(seen.contains);
  }
  return Output(
      component,
      rootLibraryUri,
      libraries.map((lib) => lib.importUri).toList(),
      moduleLibraries,
      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;
  List<Uri> moduleLibraries = const [];
  fe.InitializedCompilerState initializedCompilerState =
      input.initializedCompilerState;
  if (options.fromDill) {
    _LoadFromKernelResult result =
        await _loadFromKernel(options, compilerInput, targetName);
    component = result.component;
    entryLibrary = result.entryLibrary;
    moduleLibraries = result.moduleLibraries;
  } 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);
  }
  return _createOutput(options, reporter, entryLibrary, component,
      moduleLibraries, initializedCompilerState);
}
