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

import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;

import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/utils.dart';

const String _kActivityId = 'io.flutter.examples.named_isolates/com.example.view.MainActivity';
const String _kFirstIsolateName = 'first isolate name';
const String _kSecondIsolateName = 'second isolate name';

void main() {
  task(() async {
    final AndroidDevice device = await devices.workingDevice;
    await device.unlock();

    section('Compile and run the tester app');
    Completer<void> firstNameFound = Completer<void>();
    Completer<void> secondNameFound = Completer<void>();
    final Process runProcess = await _run(device: device, command:
        <String>['run', '--disable-service-auth-codes'], stdoutListener: (String line) {
      if (line.contains(_kFirstIsolateName)) {
        firstNameFound.complete();
      } else if (line.contains(_kSecondIsolateName)) {
        secondNameFound.complete();
      }
    });

    section('Verify all the debug isolate names are set');
    runProcess.stdin.write('l');
    await Future.wait<dynamic>(<Future<dynamic>>[firstNameFound.future, secondNameFound.future])
                .timeout(const Duration(seconds: 1), onTimeout: () => throw 'Isolate names not found.');
    await _quitRunner(runProcess);

    section('Attach to the second debug isolate');
    firstNameFound = Completer<void>();
    secondNameFound = Completer<void>();
    final String currentTime = (await device.shellEval('date', <String>['"+%F %R:%S.000"'])).trim();
    await device.shellExec('am', <String>['start', '-n', _kActivityId]);
    final String observatoryLine = await device.adb(<String>['logcat', '-e', 'Observatory listening on http:', '-m', '1', '-T', currentTime]);
    print('Found observatory line: $observatoryLine');
    final String observatoryUri = RegExp('Observatory listening on ((http|\/\/)[a-zA-Z0-9:/=_\\-\.\\[\\]]+)').firstMatch(observatoryLine)[1];
    print('Extracted observatory port: $observatoryUri');
    final Process attachProcess =
      await _run(device: device, command: <String>['attach', '--debug-uri',
          observatoryUri, '--isolate-filter', '$_kSecondIsolateName'], stdoutListener: (String line) {
        if (line.contains(_kFirstIsolateName)) {
          firstNameFound.complete();
        } else if (line.contains(_kSecondIsolateName)) {
          secondNameFound.complete();
        }
      });
    attachProcess.stdin.write('l');
    await secondNameFound.future;
    if (firstNameFound.isCompleted)
      throw '--isolate-filter failed to attach to a specific isolate';
    await _quitRunner(attachProcess);

    return TaskResult.success(null);
  });
}

Future<Process> _run({@required Device device, @required List<String> command, @required Function(String) stdoutListener}) async {
  final Directory appDir = dir(path.join(flutterDirectory.path, 'dev/integration_tests/named_isolates'));
  Process runner;
  bool observatoryConnected = false;
  await inDirectory(appDir, () async {
  runner = await startProcess(
      path.join(flutterDirectory.path, 'bin', 'flutter'),
      <String>['--suppress-analytics', '-d', device.deviceId] + command,
      isBot: false, // we just want to test the output, not have any debugging info
    );
    final StreamController<String> stdout = StreamController<String>.broadcast();

    // Mirror output to stdout, listen for ready message
    final Completer<void> appReady = Completer<void>();
    runner.stdout
      .transform<String>(utf8.decoder)
      .transform<String>(const LineSplitter())
      .listen((String line) {
        print('run:stdout: $line');
        stdout.add(line);
        if (parseServicePort(line) != null) {
          appReady.complete();
          observatoryConnected = true;
        }
        stdoutListener(line);
      });
    runner.stderr
      .transform<String>(utf8.decoder)
      .transform<String>(const LineSplitter())
      .listen((String line) {
        stderr.writeln('run:stderr: $line');
      });

    // Wait for either the process to fail or for the run to begin.
    await Future.any<dynamic>(<Future<dynamic>>[ appReady.future, runner.exitCode ]);
    if (!observatoryConnected)
      throw 'Failed to find service port when running `${command.join(' ')}`';
  });
  return runner;
}

Future<void> _quitRunner(Process runner) async {
  runner.stdin.write('q');
  final int result = await runner.exitCode;
  if (result != 0)
    throw 'Received unexpected exit code $result when quitting process.';
}
