// Copyright (c) 2017, 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.

/// An entrypoint used to measure performance of the incremental compiler.
///
/// Given an input a program and a .json file describing edits, this script will
/// first compile the program, then apply edits, recompile the
/// program, and report relevant metrics.
///
/// The edits are encoded as a JSON array:
///  - Each entry in the array is an iteration of edits and holds a list of
///  individual edits. All changes in one iteration are applied at once
///  before calling [IncrementalKernelGenerator.computeDelta].
///
///  - Each edit is a triple declaring a string replacement operation:
///       [uri, from, to]
///
///    Edits are applied in order, so more than on edit is allowed on the same
///    file.
///
///  For example:
///  [
///    {
///      "name" : "big_change",
///      "edits" : [
///        ["input1.dart", "black", "green"],
///        ["input1.dart", "30px", "10px"],
///        ["input2.dart", "a.toString()", ""$a""]
///      ]
///    },
///    {
///      "name" : "small_change",
///      "edits" : [
///        ["input1.dart", "green", "blue"]
///      ]
///    }
///  ]
///
///  Is interpreted as 2 iterations, the first iteration updates input1.dart
///  with 2 changes, and input2.dart with one change. The second iteration
///  updates input1.dart a second time.
library front_end.tool.incremental_perf;

import 'dart:convert';
import 'dart:io' hide FileSystemEntity;

import 'package:args/args.dart';
import 'package:front_end/src/api_prototype/front_end.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
import 'package:front_end/src/api_prototype/memory_file_system.dart';
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:front_end/src/base/nnbd_mode.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/fasta/uri_translator.dart';

import 'perf_common.dart';

Future<void> main(List<String> args) async {
  var options = argParser.parse(args);
  if (options.rest.length != 2) {
    throw """
usage: incremental_perf.dart [options] <entry.dart> <edits.json>
${argParser.usage}""";
  }

  var entryUri = _resolveOverlayUri(options.rest[0]);
  var editsUri = Uri.base.resolve(options.rest[1]);
  var changeSets =
      parse(jsonDecode(new File.fromUri(editsUri).readAsStringSync()));
  bool verbose = options["verbose"];
  bool verboseCompilation = options["verbose-compilation"];
  bool isFlutter = options["target"] == "flutter";
  bool useMinimalGenerator = options["implementation"] == "minimal";
  TimingsCollector collector = new TimingsCollector(verbose);

  for (int i = 0; i < 8; i++) {
    await benchmark(
        collector,
        entryUri,
        isFlutter,
        useMinimalGenerator,
        verbose,
        verboseCompilation,
        changeSets,
        options["sdk-summary"],
        options["sdk-library-specification"],
        options["cache"]);
    if (!options["loop"]) break;
  }
  collector.printTimings();
}

Future benchmark(
    TimingsCollector collector,
    Uri entryUri,
    bool isFlutter,
    bool useMinimalGenerator,
    bool verbose,
    bool verboseCompilation,
    List<ChangeSet> changeSets,
    String? sdkSummary,
    String? sdkLibrarySpecification,
    String cache) async {
  var overlayFs = new OverlayFileSystem();
  var compilerOptions = new CompilerOptions()
    ..verbose = verboseCompilation
    ..fileSystem = overlayFs
    ..onDiagnostic = onDiagnosticMessageHandler()
    ..target = createTarget(isFlutter: isFlutter)
    ..nnbdMode = NnbdMode.Weak
    ..environmentDefines = const {};
  if (sdkSummary != null) {
    compilerOptions.sdkSummary = _resolveOverlayUri(sdkSummary);
  }
  if (sdkLibrarySpecification != null) {
    compilerOptions.librariesSpecificationUri =
        _resolveOverlayUri(sdkLibrarySpecification);
  }

  var dir = Directory.systemTemp.createTempSync("ikg-cache");

  final processedOptions =
      new ProcessedOptions(options: compilerOptions, inputs: [entryUri]);
  final UriTranslator uriTranslator = await processedOptions.getUriTranslator();

  collector.start("Initial compilation");
  var generator = new IncrementalKernelGenerator(compilerOptions, [entryUri]);

  var compilerResult = await generator.computeDelta();
  var component = compilerResult.component;
  collector.stop("Initial compilation");
  if (verbose) {
    print("Libraries changed: ${component.libraries.length}");
  }
  if (component.libraries.length < 1) {
    throw "No libraries were changed";
  }

  for (final ChangeSet changeSet in changeSets) {
    String name = "Change '${changeSet.name}' - Incremental compilation";
    await applyEdits(
        changeSet.edits, overlayFs, generator, uriTranslator, verbose);
    collector.start(name);
    compilerResult = await generator.computeDelta();
    component = compilerResult.component;
    collector.stop(name);
    if (verbose) {
      print("Change '${changeSet.name}' - "
          "Libraries changed: ${component.libraries.length}");
    }
    if (component.libraries.length < 1) {
      throw "No libraries were changed";
    }
  }

  dir.deleteSync(recursive: true);
}

/// Apply all edits of a single iteration by updating the copy of the file in
/// the memory file system.
Future<void> applyEdits(
    List<Edit> edits,
    OverlayFileSystem fs,
    IncrementalKernelGenerator generator,
    UriTranslator uriTranslator,
    bool verbose) async {
  for (var edit in edits) {
    if (verbose) {
      print('edit $edit');
    }
    var uri = edit.uri;
    if (uri.isScheme('package')) uri = uriTranslator.translate(uri)!;
    generator.invalidate(uri);
    OverlayFileSystemEntity entity =
        fs.entityForUri(uri) as OverlayFileSystemEntity;
    var contents = await entity.readAsString();
    entity.writeAsStringSync(
        contents.replaceAll(edit.original, edit.replacement));
  }
}

/// Parse a set of edits from a JSON array. See library comment above for
/// details on the format.
List<ChangeSet> parse(List json) {
  final changeSets = <ChangeSet>[];
  for (final Map jsonChangeSet in json) {
    final edits = <Edit>[];
    for (final jsonEdit in jsonChangeSet['edits']) {
      edits.add(new Edit(jsonEdit[0], jsonEdit[1], jsonEdit[2]));
    }
    changeSets.add(new ChangeSet(jsonChangeSet['name'], edits));
  }
  return changeSets;
}

/// An overlay file system that reads the original contents from the physical
/// file system, but performs updates to those files in memory.
///
/// All files in this file system use a custom URI of the form:
///
///   org-dartlang-overlay:///path/to/file.dart
///
/// This special scheme is mainly used to make it clear that the file belongs to
/// this file system and may not correspond to the contents on disk. However,
/// when the file is read for the first time, it will be retrieved from the
/// underlying file system by using the corresponding `file:*` URI:
///
///   file:///path/to/file.dart
class OverlayFileSystem implements FileSystem {
  final MemoryFileSystem memory =
      new MemoryFileSystem(Uri.parse('org-dartlang-overlay:///'));
  final StandardFileSystem physical = StandardFileSystem.instance;

  @override
  FileSystemEntity entityForUri(Uri uri) {
    if (uri.isScheme('org-dartlang-overlay')) {
      return new OverlayFileSystemEntity(uri, this);
    } else if (uri.isScheme('file')) {
      // The IKG compiler reads ".dart_tool/package_config.json" which might
      // contain absolute file URIs (which it will then try to use on the FS).
      // We therefore replace them with overlay-fs URIs as usual.
      return new OverlayFileSystemEntity(_resolveOverlayUri('$uri'), this);
    } else {
      throw "Unsupported scheme: ${uri.scheme}."
          " The OverlayFileSystem only accepts URIs"
          " with the 'org-dartlang-overlay' scheme";
    }
  }
}

class OverlayFileSystemEntity implements FileSystemEntity {
  @override
  final Uri uri;
  FileSystemEntity? _delegate;
  final OverlayFileSystem _fs;

  OverlayFileSystemEntity(this.uri, this._fs);

  Future<FileSystemEntity> get delegate async {
    if (_delegate != null) return _delegate!;
    FileSystemEntity entity = _fs.memory.entityForUri(uri);
    if (await entity.exists()) {
      _delegate = entity;
      return _delegate!;
    }
    return _delegate = _fs.physical.entityForUri(uri.replace(scheme: 'file'));
  }

  @override
  Future<bool> exists() async => (await delegate).exists();

  @override
  Future<bool> existsAsyncIfPossible() async =>
      (await delegate).existsAsyncIfPossible();

  @override
  Future<List<int>> readAsBytes() async => (await delegate).readAsBytes();

  @override
  Future<List<int>> readAsBytesAsyncIfPossible() async =>
      (await delegate).readAsBytesAsyncIfPossible();

  @override
  Future<String> readAsString() async => (await delegate).readAsString();

  void writeAsStringSync(String contents) =>
      _fs.memory.entityForUri(uri).writeAsStringSync(contents);
}

/// A string replacement edit in a source file.
class Edit {
  final Uri uri;
  final String original;
  final String replacement;

  Edit(String uriString, this.original, this.replacement)
      : uri = _resolveOverlayUri(uriString);

  @override
  String toString() => 'Edit($uri, "$original" -> "$replacement")';
}

/// A named set of changes applied together.
class ChangeSet {
  final String name;
  final List<Edit> edits;

  ChangeSet(this.name, this.edits);

  @override
  String toString() => 'ChangeSet($name, $edits)';
}

Uri _resolveOverlayUri(String uriString) {
  Uri result = Uri.base.resolve(uriString);
  return result.isScheme("file")
      ? result.replace(scheme: 'org-dartlang-overlay')
      : result;
}

ArgParser argParser = new ArgParser()
  ..addFlag('verbose-compilation',
      help: 'make the compiler verbose', defaultsTo: false)
  ..addFlag('verbose', help: 'print additional information', defaultsTo: false)
  ..addFlag('loop', help: 'run benchmark 8 times', defaultsTo: true)
  ..addOption('target',
      help: 'target platform', defaultsTo: 'vm', allowed: ['vm', 'flutter'])
  ..addOption('cache',
      help: 'caching policy used by the compiler',
      defaultsTo: 'protected',
      allowed: ['evicting', 'memory', 'protected'])
  // TODO(johnniwinther): Remove mode option. Legacy mode is no longer
  // supported.
  ..addOption('mode',
      help: 'whether to run in strong or legacy mode',
      defaultsTo: 'strong',
      allowed: ['legacy', 'strong'])
  ..addOption('implementation',
      help: 'incremental compiler implementation to use',
      defaultsTo: 'default',
      allowed: ['default', 'minimal'])
  ..addOption('sdk-summary', help: 'Location of the sdk outline.dill file')
  ..addOption('sdk-library-specification',
      help: 'Location of the '
          'sdk/lib/libraries.json file');
