// Copyright 2020 The Dart Authors. 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 'dart:convert';
import 'dart:io';

import 'package:frontend_server_client/frontend_server_client.dart';
import 'package:path/path.dart' as p;
import 'package:vm_service/vm_service.dart';
import 'package:vm_service/vm_service_io.dart';

void main(List<String> args) async {
  try {
    watch.start();
    if (args.isNotEmpty) {
      throw ArgumentError('No command line args are supported');
    }

    var client = await FrontendServerClient.start(
        'org-dartlang-root:///$app',
        outputDill,
        p.join(sdkDir, 'lib', '_internal', 'vm_platform_strong.dill'),
        target: 'vm',
        fileSystemRoots: [p.url.current],
        fileSystemScheme: 'org-dartlang-root',
        verbose: true);
    _print('compiling $app');
    var result = await client.compile();
    client.accept();
    _print('done compiling $app');

    Process appProcess;
    final vmServiceCompleter = Completer<VmService>();
    appProcess = await Process.start(Platform.resolvedExecutable,
        ['--enable-vm-service', result.dillOutput!]);
    final sawHelloWorld = Completer();
    appProcess.stdout
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen((line) {
      stdout.writeln('APP -> $line');
      if (line == 'hello/world') {
        sawHelloWorld.complete();
      }
      if (line.startsWith(
          'The Dart DevTools debugger and profiler is available at:')) {
        var observatoryUri =
            '${line.split(' ').last.replaceFirst('http', 'ws')}ws';
        vmServiceCompleter.complete(vmServiceConnectUri(observatoryUri));
      }
    });
    appProcess.stderr
        .transform(utf8.decoder)
        .transform(const LineSplitter())
        .listen((line) {
      stderr.writeln('APP -> $line');
    });

    final vmService = await vmServiceCompleter.future;
    await sawHelloWorld.future;

    _print('editing $app');
    var appFile = File(app);
    var originalContent = await appFile.readAsString();
    var newContent = originalContent.replaceFirst('hello', 'goodbye');
    await appFile.writeAsString(newContent);

    _print('recompiling $app with edits');
    result = await client.compile([Uri.parse('org-dartlang-root:///$app')]);
    client.accept();
    _print('done recompiling $app');
    _print('reloading $app');
    var vm = await vmService.getVM();
    await vmService.reloadSources(vm.isolates!.first.id!,
        rootLibUri: result.dillOutput!);

    _print('restoring $app to original contents');
    await appFile.writeAsString(originalContent);
    _print('exiting');
    await client.shutdown().timeout(const Duration(seconds: 1), onTimeout: () {
      client.kill();
      return 1;
    });
  } finally {
    Directory(p.join('.dart_tool', 'out')).deleteSync(recursive: true);
  }
}

void _print(String message) {
  print('${watch.elapsed}: $message');
}

final app = 'example/app/main.dart';
final outputDill = p.join('.dart_tool', 'out', 'example_app.dill');
final sdkDir = p.dirname(p.dirname(Platform.resolvedExecutable));
final watch = Stopwatch();
