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

/// Integration test that runs the incremental compiler, runs the compiled
/// program, incrementally rebuild portions of the app, and triggers a hot
/// reload on the running program.
library front_end.incremental.hot_reload_e2e_test;

import 'dart:async' show Completer, Future;

import 'dart:convert' show LineSplitter, utf8;

import 'dart:io' show Directory, File, Platform, Process;

import 'package:async_helper/async_helper.dart' show asyncTest;

import 'package:expect/expect.dart' show Expect;

import 'package:kernel/ast.dart' show Component;

import 'package:kernel/binary/ast_to_binary.dart';

import 'package:front_end/src/api_prototype/compiler_options.dart'
    show CompilerOptions;

import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;

import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
    show IncrementalKernelGenerator;

import 'package:front_end/src/api_prototype/memory_file_system.dart'
    show MemoryFileSystem;

import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

import 'package:front_end/src/fasta/hybrid_file_system.dart'
    show HybridFileSystem;

import 'tool/reload.dart' show RemoteVm;

abstract class TestCase {
  IncrementalKernelGenerator compiler;
  MemoryFileSystem fs;
  Directory outDir;
  Uri outputUri;
  List<Future<String>> lines;
  Future programIsDone;

  String get name;

  Future run();

  Future test() async {
    await setUp();
    try {
      await run();
      print("$name done");
    } finally {
      await tearDown();
    }
  }

  setUp() async {
    outDir = Directory.systemTemp.createTempSync('hotreload_test');
    outputUri = outDir.uri.resolve('test.dill');
    var root = Uri.parse('org-dartlang-test:///');
    fs = new MemoryFileSystem(root);
    fs.entityForUri(root).createDirectory();
    writeFile(fs, 'a.dart', sourceA);
    writeFile(fs, 'b.dart', sourceB);
    writeFile(fs, 'c.dart', sourceC);
    writeFile(fs, '.packages', '');
    compiler = createIncrementalCompiler(
        'org-dartlang-test:///a.dart', new HybridFileSystem(fs));
    await rebuild(compiler, outputUri); // this is a full compile.
  }

  tearDown() async {
    outDir.deleteSync(recursive: true);
    lines = null;
  }

  Future<int> computeVmPort() async {
    var portLine = await lines[0];
    Expect.isTrue(observatoryPortRegExp.hasMatch(portLine));
    var match = observatoryPortRegExp.firstMatch(portLine);
    return int.parse(match.group(1));
  }

  /// Request vm to resume execution
  Future resume() async {
    var port = await computeVmPort();
    var remoteVm = new RemoteVm(port);
    await remoteVm.resume();
  }

  /// Start the VM with the first version of the program compiled by the
  /// incremental compiler.
  startProgram(int reloadCount) async {
    var vmArgs = [
      '--enable-vm-service=0', // Note: use 0 to avoid port collisions.
      '--pause_isolates_on_start',
      '--disable-service-auth-codes',
      outputUri.toFilePath()
    ];
    vmArgs.add('$reloadCount');
    var vm = await Process.start(Platform.executable, vmArgs);
    var splitter = new LineSplitter();

    /// The program prints at most 2 + reloadCount lines:
    ///  - a line displaying the observatory port
    ///  - a line before waiting for a reload
    ///  - a line after each hot-reload
    int i = 0;
    int expectedLines = 2 + reloadCount;
    var completers =
        new List.generate(expectedLines, (_) => new Completer<String>());
    lines = completers.map((c) => c.future).toList();
    vm.stdout.transform(utf8.decoder).transform(splitter).listen((line) {
      Expect.isTrue(i < expectedLines);
      completers[i++].complete(line);
    }, onDone: () {
      Expect.equals(expectedLines, i);
    });

    // ignore: unawaited_futures
    vm.stderr.transform(utf8.decoder).transform(splitter).toList().then((err) {
      Expect.isTrue(err.isEmpty, err.join('\n'));
    });

    programIsDone = vm.exitCode;
    await resume();
  }

  /// Request a hot reload on the running program.
  Future hotReload() async {
    var port = await computeVmPort();
    var remoteVm = new RemoteVm(port);
    var reloadResult = await remoteVm.reload(outputUri);
    Expect.isTrue(reloadResult['success']);
    await remoteVm.disconnect();
  }
}

class InitialProgramIsValid extends TestCase {
  @override
  String get name => 'initial program is valid';

  @override
  Future run() async {
    await startProgram(0);
    await programIsDone;
    Expect.stringEquals("part1 part2", await lines[1]);
  }
}

class ReloadAfterLeafLibraryModification extends TestCase {
  @override
  String get name => 'reload after leaf library modification';

  @override
  Future run() async {
    await startProgram(1);
    Expect.stringEquals("part1 part2", await lines[1]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part3"));
    await rebuild(compiler, outputUri);
    await hotReload();
    await programIsDone;
    Expect.stringEquals("part3 part2", await lines[2]);
  }
}

class ReloadAfterNonLeafLibraryModification extends TestCase {
  @override
  String get name => "reload after non-leaf library modification";

  @override
  Future run() async {
    await startProgram(1);
    Expect.stringEquals("part1 part2", await lines[1]);

    writeFile(fs, 'a.dart', sourceA.replaceAll("part2", "part4"));
    await rebuild(compiler, outputUri);
    await hotReload();
    await programIsDone;
    Expect.stringEquals("part1 part4", await lines[2]);
  }
}

class ReloadAfterWholeProgramModification extends TestCase {
  @override
  String get name => "reload after whole program modification";

  @override
  Future run() async {
    await startProgram(1);
    Expect.stringEquals("part1 part2", await lines[1]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part5"));
    writeFile(fs, 'a.dart', sourceA.replaceAll("part2", "part6"));
    await rebuild(compiler, outputUri);
    await hotReload();
    await programIsDone;
    Expect.stringEquals("part5 part6", await lines[2]);
  }
}

class ReloadTwice extends TestCase {
  @override
  String get name => "reload twice";

  @override
  Future run() async {
    await startProgram(2);
    Expect.stringEquals("part1 part2", await lines[1]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part5"));
    writeFile(fs, 'a.dart', sourceA.replaceAll("part2", "part6"));
    await rebuild(compiler, outputUri);
    await hotReload();
    Expect.stringEquals("part5 part6", await lines[2]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part7"));
    writeFile(fs, 'a.dart', sourceA.replaceAll("part2", "part8"));
    await rebuild(compiler, outputUri);
    await hotReload();
    await programIsDone;
    Expect.stringEquals("part7 part8", await lines[3]);
  }
}

class ReloadToplevelField extends TestCase {
  @override
  String get name => "reload top level field";

  @override
  Future run() async {
    await startProgram(2);
    Expect.stringEquals("part1 part2", await lines[1]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part3"));
    writeFile(fs, 'c.dart', r"""
      void g() {
        bField.a("a");
      }

      class B {
        dynamic a;
        B({this.a});
      }

      var bField = new B(a: (String s) => "$s");
    """);

    await rebuild(compiler, outputUri);
    await hotReload();
    Expect.stringEquals("part3 part2", await lines[2]);

    writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part4"));
    writeFile(fs, 'c.dart', r"""
      void g() {
        bField.a("a");
      }

      class B {
        dynamic a;
        dynamic b;
        B({this.a});
      }

      var bField = new B(a: (String s) => "$s");
    """);

    await rebuild(compiler, outputUri);
    await hotReload();
    Expect.stringEquals("part4 part2", await lines[3]);
    await programIsDone;
  }
}

main() {
  asyncTest(() async {
    await new InitialProgramIsValid().test();
    await new ReloadAfterLeafLibraryModification().test();
    await new ReloadAfterNonLeafLibraryModification().test();
    await new ReloadAfterWholeProgramModification().test();
    await new ReloadTwice().test();
    await new ReloadToplevelField().test();
  });
}

final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);

IncrementalKernelGenerator createIncrementalCompiler(
    String entry, FileSystem fs) {
  var entryUri = Uri.base.resolve(entry);
  var options = new CompilerOptions()
    ..sdkRoot = sdkRoot
    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
    ..fileSystem = fs;
  return new IncrementalKernelGenerator(options, entryUri);
}

Future<bool> rebuild(IncrementalKernelGenerator compiler, Uri outputUri) async {
  compiler.invalidate(Uri.parse("org-dartlang-test:///a.dart"));
  compiler.invalidate(Uri.parse("org-dartlang-test:///b.dart"));
  compiler.invalidate(Uri.parse("org-dartlang-test:///c.dart"));
  var component = await compiler.computeDelta();
  if (component != null && !component.libraries.isEmpty) {
    await writeProgram(component, outputUri);
    return true;
  }
  return false;
}

Future<Null> writeProgram(Component component, Uri outputUri) async {
  var sink = new File.fromUri(outputUri).openWrite();
  // TODO(sigmund): the incremental generator should always filter these
  // libraries instead.
  new BinaryPrinter(sink,
          libraryFilter: (library) => library.importUri.scheme != 'dart')
      .writeComponentFile(component);
  await sink.close();
}

void writeFile(MemoryFileSystem fs, String fileName, String contents) {
  fs
      .entityForUri(Uri.parse('org-dartlang-test:///$fileName'))
      .writeAsStringSync(contents);
}

/// This program calls a function periodically and tracks when the function
/// returns a different value than before (which only happens after a
/// hot-reload). The program exits after certain number of reloads, specified as
/// an argument to main.
const sourceA = r'''
import 'dart:async';
import 'b.dart';
import 'c.dart';

void main(List<String> args) {
  var last = f();
  print(last);
  g();

  // The argument indicates how many "visible" hot-reloads to run
  int reloadCount = 0;
  if (args.length > 0) {
    reloadCount = int.parse(args[0]);
  }
  if (reloadCount == 0) return;

  new Timer.periodic(new Duration(milliseconds: 100), (timer) {
    var result = f();
    if (last != result) {
      print(result);
      g();
      last = result;
      if (--reloadCount == 0) timer.cancel();
    }
  });
}

f() => "$line part2";
''';

const sourceB = r'''
get line => "part1";
''';

const sourceC = r'''
void g() {}
''';

RegExp observatoryPortRegExp =
    new RegExp("Observatory listening on http://127.0.0.1:\([0-9]*\)/");
