// Copyright 2014 The Flutter 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 'dart:math';

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';

void generateMain(Directory appDir, String sentinel) {
  final String mainCode = '''
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_driver/driver_extension.dart';

class ReassembleListener extends StatefulWidget {
  const ReassembleListener({Key key, this.child})
      : super(key: key);

  final Widget child;

  @override
  _ReassembleListenerState createState() => _ReassembleListenerState();
}

class _ReassembleListenerState extends State<ReassembleListener> {
  @override
  initState() {
    super.initState();
    print('$sentinel');
  }

  @override
  void reassemble() {
    super.reassemble();
    print('$sentinel');
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

void main() {
  runApp(
    ReassembleListener(
      child: Text(
        'Hello, word!',
        textDirection: TextDirection.rtl,
      )
    )
  );
}
''';
  File(path.join(appDir.path, 'lib', 'fuchsia_main.dart'))
    .writeAsStringSync(mainCode, flush: true);
}

void main() {
  deviceOperatingSystem = DeviceOperatingSystem.fuchsia;

  task(() async {
    section('Checking environment variables');

    if (Platform.environment['FUCHSIA_SSH_CONFIG'] == null &&
        Platform.environment['FUCHSIA_BUILD_DIR'] == null) {
      throw Exception('No FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR set');
    }

    final String flutterBinary = path.join(flutterDirectory.path, 'bin', 'flutter');

    section('Downloading Fuchsia SDK and flutter runner');

    // Download the Fuchsia SDK.
    final int precacheResult = await exec(
      flutterBinary,
      <String>[
        'precache',
        '--fuchsia',
        '--flutter_runner',
      ]
    );

    if (precacheResult != 0) {
      throw Exception('flutter precache failed with exit code $precacheResult');
    }

    final Directory fuchsiaToolDirectory =
      Directory(path.join(flutterDirectory.path, 'bin', 'cache', 'artifacts', 'fuchsia', 'tools'));
    if (!fuchsiaToolDirectory.existsSync()) {
      throw Exception('Expected Fuchsia tool directory at ${fuchsiaToolDirectory.path}');
    }

    final Device device = await devices.workingDevice;
    final Directory appDir = dir(path.join(
      flutterDirectory.path,
      'dev',
      'integration_tests',
      'ui',
    ));

    await inDirectory(appDir, () async {
      final Random random = Random();
      final Map<String, Completer<void>> sentinelMessage = <String, Completer<void>>{
        'sentinel-${random.nextInt(1<<32)}': Completer<void>(),
        'sentinel-${random.nextInt(1<<32)}': Completer<void>(),
      };

      Process runProcess;
      Process logsProcess;

      try {
        section('Creating lib/fuchsia_main.dart');

        generateMain(appDir, sentinelMessage.keys.toList()[0]);

        section('Launching `flutter run` in ${appDir.path}');

        runProcess = await startProcess(
          flutterBinary,
          <String>[
            'run',
            '--suppress-analytics',
            '-d', device.deviceId,
            '-t', 'lib/fuchsia_main.dart',
          ],
          isBot: false, // We just want to test the output, not have any debugging info.
        );

        logsProcess = await startProcess(
          flutterBinary,
          <String>['logs', '--suppress-analytics', '-d', device.deviceId],
          isBot: false, // We just want to test the output, not have any debugging info.
        );

        Future<dynamic> eventOrExit(Future<void> event) {
          return Future.any<dynamic>(<Future<dynamic>>[
            event,
            runProcess.exitCode,
            logsProcess.exitCode,
          ]);
        }

        logsProcess.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String log) {
            print('logs:stdout: $log');
            for (final String sentinel in sentinelMessage.keys) {
              if (log.contains(sentinel)) {
                if (sentinelMessage[sentinel].isCompleted) {
                  throw Exception(
                    'Expected a single `$sentinel` message in the device log, but found more than one'
                  );
                }
                sentinelMessage[sentinel].complete();
                break;
              }
            }
          });

        final Completer<void> hotReloadCompleter = Completer<void>();
        final Completer<void> reloadedCompleter = Completer<void>();
        final RegExp observatoryRegexp = RegExp('An Observatory debugger and profiler on .+ is available at');
        runProcess.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
            print('run:stdout: $line');
            if (observatoryRegexp.hasMatch(line)) {
              hotReloadCompleter.complete();
            } else if (line.contains('Reloaded')) {
              reloadedCompleter.complete();
            }
          });

        final List<String> runStderr = <String>[];
        runProcess.stderr
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
            runStderr.add(line);
            print('run:stderr: $line');
          });

        section('Waiting for hot reload availability');
        await eventOrExit(hotReloadCompleter.future);

        section('Waiting for Dart VM');
        // Wait for the first message in the log from the Dart VM.
        await eventOrExit(sentinelMessage.values.toList()[0].future);

        // Change the dart file.
        generateMain(appDir, sentinelMessage.keys.toList()[1]);

        section('Hot reload');
        runProcess.stdin.write('r');
        runProcess.stdin.flush();
        await eventOrExit(reloadedCompleter.future);

        section('Waiting for Dart VM');
        // Wait for the second message in the log from the Dart VM.
        await eventOrExit(sentinelMessage.values.toList()[1].future);

        section('Quitting flutter run');

        runProcess.stdin.write('q');
        runProcess.stdin.flush();

        final int runExitCode = await runProcess.exitCode;
        if (runExitCode != 0 || runStderr.isNotEmpty) {
          throw Exception(
            'flutter run exited with code $runExitCode and errors: ${runStderr.join('\n')}.'
          );
        }
      } finally {
        runProcess.kill();
        logsProcess.kill();
        File(path.join(appDir.path, 'lib', 'fuchsia_main.dart')).deleteSync();
      }

      for (final String sentinel in sentinelMessage.keys) {
        if (!sentinelMessage[sentinel].isCompleted) {
          throw Exception('Expected $sentinel in the device logs.');
        }
      }
    });

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