// 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');
    }

    final 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:')) {
        final 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');
    final appFile = File(app);
    final originalContent = await appFile.readAsString();
    final 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');
    final 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();
