// 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.

// @dart = 2.10

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, implicitlyUsedLibraries;
import '../kernel/transformations/clone_mixin_methods_with_super.dart'
    as transformMixins show transformLibraries;
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 withNewComponent(ir.Component component) => Output(component,
      rootLibraryUri, libraries, moduleLibraries, 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);
}

void _doGlobalTransforms(Component component) {
  transformMixins.transformLibraries(component.libraries);
}

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);

  // When compiling modularly, a dill for the SDK will be provided. In those
  // cases we ignore the implicit platform binary.
  bool platformBinariesIncluded =
      options.modularMode || options.hasModularAnalysisInputs;
  if (options.platformBinaries != null && !platformBinariesIncluded) {
    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);
  }

  // We apply global transforms when running phase 0.
  if (options.cfeOnly) {
    _doGlobalTransforms(component);
  }
  return _LoadFromKernelResult(component, entryLibrary, moduleLibraries);
}

class _LoadFromSourceResult {
  final ir.Component component;
  final fe.InitializedCompilerState initializedCompilerState;
  final List<Uri> moduleLibraries;

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

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(),
      options: options,
      canPerformGlobalTransforms: true,
      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);
    }
  };

  // If we are passed a list of sources, then we are performing a modular
  // compile. In this case, we cannot infer null safety from the source files
  // and must instead rely on the options passed in on the command line.
  bool isModularCompile = false;
  List<Uri> sources = [];
  if (options.sources != null) {
    isModularCompile = true;
    sources.addAll(options.sources);
  } else {
    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);
    _inferNullSafetyMode(options, !isLegacy);
    sources.add(options.compilationTarget);
  }

  // If we are performing a modular compile, we expect the platform binary to be
  // supplied along with other dill dependencies.
  List<Uri> dependencies = [];
  if (options.platformBinaries != null && !isModularCompile) {
    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, isModularCompile);
  _validateNullSafetyMode(options);

  // We have to compute canonical names on the component here to avoid missing
  // canonical names downstream.
  if (isModularCompile) {
    component.computeCanonicalNames();
  }
  return _LoadFromSourceResult(
      component, initializedCompilerState, isModularCompile ? sources : []);
}

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 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(),
      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;
    moduleLibraries = result.moduleLibraries;
  }
  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);
}
