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

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io' as io;

import 'package:observatory/service_io.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';

import 'test_helper.dart';

final dartJITBinary = path.join(path.dirname(io.Platform.executable),
    'dart' + path.extension(io.Platform.executable));

Future setupProcesses() async {
  var dir = await io.Directory.systemTemp.createTemp('file_service');

  var args = [
    ...io.Platform.executableArguments,
    '--pause_isolates_on_start',
    io.Platform.script.toFilePath(),
  ];
  var process1;
  var process2;
  var process3;

  void closeDown() {
    if (process1 != null) {
      process1.kill();
    }
    if (process2 != null) {
      process2.kill();
    }
    if (process3 != null) {
      process3.kill();
    }
    dir.deleteSync(recursive: true);
  }

  Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
    closeDown();
    var result = jsonEncode({'type': 'foobar'});
    return new Future.value(new ServiceExtensionResponse.result(result));
  }

  Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
    try {
      process1 = await io.Process.start(io.Platform.executable, args);
      process2 =
          await io.Process.start(io.Platform.executable, args..add('foobar'));
      var codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
      var codeFile = new io.File(codeFilePath);
      await codeFile.writeAsString('''
          import "dart:io";

          void main() async {
            await stdin.drain();
          }
          ''');
      process3 = await io.Process.start(
          dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
    } catch (e) {
      closeDown();
      throw e;
    }

    var result = jsonEncode({
      'type': 'foobar',
      'pids': [process1.pid, process2.pid, process3.pid]
    });
    return new Future.value(new ServiceExtensionResponse.result(result));
  }

  Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) {
    process3.stdin.close();
    return process3.exitCode.then<ServiceExtensionResponse>((int exit) {
      var result = jsonEncode({'type': 'foobar'});
      return new ServiceExtensionResponse.result(result);
    });
  }

  registerExtension('ext.dart.io.cleanup', cleanup);
  registerExtension('ext.dart.io.setup', setup);
  registerExtension('ext.dart.io.closeStdin', closeStdin);
}

var processTests = <IsolateTest>[
  // Initial.
  (Isolate isolate) async {
    var setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
    try {
      var all =
          await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
      expect(all['type'], equals('_startedprocesses'));

      expect(all['data'].length, equals(3));

      var first = await isolate.invokeRpcNoUpgrade(
          'ext.dart.io.getProcessById', {'id': all['data'][0]['id']});
      expect(first['name'], io.Platform.executable);
      expect(first['pid'], equals(setup['pids'][0]));
      expect(first['arguments'].contains('foobar'), isFalse);
      expect(first['startedAt'], greaterThan(0));

      var second = await isolate.invokeRpcNoUpgrade(
          'ext.dart.io.getProcessById', {'id': all['data'][1]['id']});
      expect(second['name'], io.Platform.executable);
      expect(second['pid'], equals(setup['pids'][1]));
      expect(second['arguments'].contains('foobar'), isTrue);
      expect(second['pid'] != first['pid'], isTrue);
      expect(second['startedAt'], greaterThan(0));
      expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));

      var third = await isolate.invokeRpcNoUpgrade(
          'ext.dart.io.getProcessById', {'id': all['data'][2]['id']});
      expect(third['name'], dartJITBinary);
      expect(third['pid'], equals(setup['pids'][2]));
      expect(third['pid'] != first['pid'], isTrue);
      expect(third['pid'] != second['pid'], isTrue);
      expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));

      await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {});
      all = await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
      expect(all['type'], equals('_startedprocesses'));
      expect(all['data'].length, equals(2));
    } finally {
      await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
    }
  },
];

main(args) async =>
    runIsolateTests(args, processTests, testeeBefore: setupProcesses);
