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

/// A wrapper on top of the [IncrementalKernelGenerator] that tracks
/// file modifications between subsequent compilation requests and only
/// invalidates those files that appear to be modified.
library front_end.example.incremental_reload.compiler_with_invalidation;

import 'dart:io';
import 'dart:async';

import 'package:front_end/compiler_options.dart';
import 'package:front_end/incremental_kernel_generator.dart';
import 'package:front_end/src/byte_store/file_byte_store.dart';
import 'package:front_end/src/byte_store/byte_store.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/binary/limited_ast_to_binary.dart';
import 'package:kernel/target/targets.dart';

/// Create an instance of an [IncrementalCompiler] to compile a program whose
/// main entry point file is [entry]. This uses some default options
/// for the location of the sdk and temporary folder to save intermediate
/// results.
Future<IncrementalCompiler> createIncrementalCompiler(String entry,
    {bool persistent: true, Uri sdkRoot, Target target}) {
  var entryUri = Uri.base.resolve(entry);
  var dartVm = Uri.base.resolve(Platform.resolvedExecutable);
  var tmpDir = Directory.systemTemp.createTempSync('ikg_cache');
  var options = new CompilerOptions()
    ..sdkRoot = sdkRoot ?? dartVm.resolve("patched_sdk/")
    ..packagesFileUri = Uri.base.resolve('.packages')
    ..strongMode = false
    ..target = target
    // Note: we do not report error on the console because the incremental
    // compiler is an ongoing background service that shouldn't polute stdout.
    // TODO(sigmund): do something with the errors.
    ..onError = (_) {}
    ..byteStore =
        persistent ? new FileByteStore(tmpDir.path) : new MemoryByteStore();
  return IncrementalCompiler.create(options, entryUri);
}

/// An incremental compiler that monitors file modifications on disk and
/// invalidates only files that have been modified since the previous time the
/// compiler was invoked.
class IncrementalCompiler {
  /// Underlying incremental compiler implementation.
  IncrementalKernelGenerator _generator;

  /// Last modification for each tracked input file.
  Map<Uri, DateTime> lastModified = {};

  /// Create an instance of [IncrementalCompiler].
  static Future<IncrementalCompiler> create(
      CompilerOptions options, Uri entryUri) async {
    var compiler = new IncrementalCompiler._internal();
    compiler._generator = await IncrementalKernelGenerator
        .newInstance(options, entryUri, watch: compiler._watch);
    return compiler;
  }

  IncrementalCompiler._internal();

  /// Callback for the [IncrementalKernelGenerator] to keep track of relevant
  /// files.
  Future _watch(Uri uri, bool used) {
    if (used) {
      lastModified[uri] ??= new File.fromUri(uri).lastModifiedSync();
    } else {
      lastModified.remove(uri);
    }
    return new Future.value(null);
  }

  /// How many files changed during the last call to [recompile].
  int changed;

  /// Time spent updating time-stamps from disk during the last call to
  /// [recompile].
  int invalidateTime;

  /// Time actually spent compiling the code in the incremental compiler during
  /// the last call to [recompile].
  int compileTime;

  /// Determine which files have been modified, and recompile the program
  /// incrementally based on that information.
  Future<Program> recompile() async {
    changed = 0;
    invalidateTime = 0;
    compileTime = 0;

    var invalidateTimer = new Stopwatch()..start();
    for (var uri in lastModified.keys.toList()) {
      var last = lastModified[uri];
      var current = new File.fromUri(uri).lastModifiedSync();
      if (last != current) {
        lastModified[uri] = current;
        _generator.invalidate(uri);
        changed++;
      }
    }
    invalidateTimer.stop();
    invalidateTime = invalidateTimer.elapsedMilliseconds;
    if (changed == 0 && lastModified.isNotEmpty) return null;

    var compileTimer = new Stopwatch()..start();
    var delta = await _generator.computeDelta();
    _generator.acceptLastDelta();
    compileTimer.stop();
    compileTime = compileTimer.elapsedMilliseconds;
    var program = delta.newProgram;
    return program;
  }
}

/// The result of an incremental compile and metrics collected during the
/// the compilation.
class CompilationResult {
  /// How many files were modified by the time we invoked the compiler again.
  int changed = 0;

  /// How many files are currently being tracked for modifications.
  int totalFiles = 0;

  /// How long it took to invalidate files that have been modified.
  int invalidateTime = 0;

  /// How long it took to build the incremental program.
  int compileTime = 0;

  /// How long it took to do the hot-reload in the VM.
  int reloadTime = 0;

  /// Whether we saw errors during compilation or reload.
  bool errorSeen = false;

  /// Error message when [errorSeen] is true.
  String errorDetails;

  /// The program that was generated by the incremental compiler.
  Program program;
}

/// Request a recompile and possibly a reload, and gather timing metrics.
Future<CompilationResult> rebuild(
    IncrementalCompiler compiler, Uri outputUri) async {
  var result = new CompilationResult();
  try {
    var program = result.program = await compiler.recompile();
    if (program != null && !program.libraries.isEmpty) {
      var sink = new File.fromUri(outputUri).openWrite();
      // TODO(sigmund): should the incremental generator always filter these
      // libraries instead?
      new LimitedBinaryPrinter(
              sink, (library) => library.importUri.scheme != 'dart', false)
          .writeProgramFile(program);
      await sink.close();
    }
  } catch (e, t) {
    result.errorDetails = 'compilation error: $e, $t';
    result.errorSeen = true;
  }

  result.changed = compiler.changed;
  result.totalFiles = compiler.lastModified.length;
  result.invalidateTime = compiler.invalidateTime;
  result.compileTime = compiler.compileTime;
  result.reloadTime = 0;
  return result;
}
