// 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 'package:path/path.dart' as path;

import '../framework/framework.dart';
import '../framework/utils.dart';

final Directory _editedFlutterGalleryDir = dir(path.join(Directory.systemTemp.path, 'edited_flutter_gallery'));
final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'dev/integration_tests/flutter_gallery'));

const String kInitialStartupTime = 'InitialStartupTime';
const String kFirstRestartTime = 'FistRestartTime';
const String kFirstRecompileTime  = 'FirstRecompileTime';
const String kSecondStartupTime = 'SecondStartupTime';
const String kSecondRestartTime = 'SecondRestartTime';


abstract class WebDevice {
  static const String chrome = 'chrome';
  static const String webServer = 'web-server';
}

TaskFunction createWebDevModeTest(String webDevice, bool enableIncrementalCompiler) {
  return () async {
    final List<String> options = <String>[
      '--hot', '-d', webDevice, '--verbose', '--resident', '--target=lib/main.dart',
    ];
    int hotRestartCount = 0;
    final String expectedMessage = webDevice == WebDevice.webServer
      ? 'Recompile complete'
      : 'Reloaded application';
    final Map<String, int> measurements = <String, int>{};
    await inDirectory<void>(flutterDirectory, () async {
      rmTree(_editedFlutterGalleryDir);
      mkdirs(_editedFlutterGalleryDir);
      recursiveCopy(flutterGalleryDir, _editedFlutterGalleryDir);
      await inDirectory<void>(_editedFlutterGalleryDir, () async {
        {
          final Process packagesGet = await startProcess(
              path.join(flutterDirectory.path, 'bin', 'flutter'),
              <String>['packages', 'get'],
              environment: <String, String>{
                'FLUTTER_WEB': 'true',
                if (enableIncrementalCompiler)
                  'WEB_INCREMENTAL_COMPILER': 'true',
              },
          );
          await packagesGet.exitCode;
          final Process process = await startProcess(
              path.join(flutterDirectory.path, 'bin', 'flutter'),
              flutterCommandArgs('run', options),
              environment: <String, String>{
                'FLUTTER_WEB': 'true',
                if (enableIncrementalCompiler)
                  'WEB_INCREMENTAL_COMPILER': 'true',
              },
          );

          final Completer<void> stdoutDone = Completer<void>();
          final Completer<void> stderrDone = Completer<void>();
          final Stopwatch sw = Stopwatch()..start();
          bool restarted = false;
          process.stdout
              .transform<String>(utf8.decoder)
              .transform<String>(const LineSplitter())
              .listen((String line) {
            // TODO(jonahwilliams): non-dwds builds do not know when the browser is loaded.
            if (line.contains('Ignoring terminal input')) {
              Future<void>.delayed(const Duration(seconds: 1)).then((void _) {
                process.stdin.write(restarted ? 'q' : 'r');
              });
              return;
            }
            if (line.contains('To hot restart')) {
              // measure clean start-up time.
              sw.stop();
              measurements[kInitialStartupTime] = sw.elapsedMilliseconds;
              sw
                ..reset()
                ..start();
              process.stdin.write('r');
              return;
            }
            if (line.contains(expectedMessage)) {
              if (hotRestartCount == 0) {
                measurements[kFirstRestartTime] = sw.elapsedMilliseconds;
                // Update the file and reload again.
                final File appDartSource = file(path.join(
                    _editedFlutterGalleryDir.path, 'lib/gallery/app.dart',
                ));
                appDartSource.writeAsStringSync(
                    appDartSource.readAsStringSync().replaceFirst(
                        "'Flutter Gallery'", "'Updated Flutter Gallery'",
                    )
                );
                sw
                  ..reset()
                  ..start();
                process.stdin.writeln('r');
                ++hotRestartCount;
              } else {
                restarted = true;
                measurements[kFirstRecompileTime] = sw.elapsedMilliseconds;
                // Quit after second hot restart.
                process.stdin.writeln('q');
              }
            }
            print('stdout: $line');
          }, onDone: () {
            stdoutDone.complete();
          });
          process.stderr
              .transform<String>(utf8.decoder)
              .transform<String>(const LineSplitter())
              .listen((String line) {
            print('stderr: $line');
          }, onDone: () {
            stderrDone.complete();
          });

          await Future.wait<void>(<Future<void>>[
            stdoutDone.future,
            stderrDone.future,
          ]);
          await process.exitCode;

        }

        // Start `flutter run` again to make sure it loads from the previous
        // state. dev compilers loads up from previously compiled JavaScript.
        {

          final Stopwatch sw = Stopwatch()..start();
          final Process process = await startProcess(
              path.join(flutterDirectory.path, 'bin', 'flutter'),
              flutterCommandArgs('run', options),
              environment: <String, String>{
                'FLUTTER_WEB': 'true',
                if (enableIncrementalCompiler)
                  'WEB_INCREMENTAL_COMPILER': 'true',
              },
          );
          final Completer<void> stdoutDone = Completer<void>();
          final Completer<void> stderrDone = Completer<void>();
          bool restarted = false;
          process.stdout
              .transform<String>(utf8.decoder)
              .transform<String>(const LineSplitter())
              .listen((String line) {
            // TODO(jonahwilliams): non-dwds builds do not know when the browser is loaded.
            if (line.contains('Ignoring terminal input')) {
              Future<void>.delayed(const Duration(seconds: 1)).then((void _) {
                process.stdin.write(restarted ? 'q' : 'r');
              });
              return;
            }
            if (line.contains('To hot restart')) {
              measurements[kSecondStartupTime] = sw.elapsedMilliseconds;
              sw
                ..reset()
                ..start();
              process.stdin.write('r');
              return;
            }
            if (line.contains(expectedMessage)) {
              restarted = true;
              measurements[kSecondRestartTime] = sw.elapsedMilliseconds;
              process.stdin.writeln('q');
            }
            print('stdout: $line');
          }, onDone: () {
            stdoutDone.complete();
          });
          process.stderr
              .transform<String>(utf8.decoder)
              .transform<String>(const LineSplitter())
              .listen((String line) {
            print('stderr: $line');
          }, onDone: () {
            stderrDone.complete();
          });

          await Future.wait<void>(<Future<void>>[
            stdoutDone.future,
            stderrDone.future,
          ]);
          await process.exitCode;
        }
      });
    });
    if (hotRestartCount != 1) {
      return TaskResult.failure(null);
    }
    return TaskResult.success(measurements, benchmarkScoreKeys: <String>[
      kInitialStartupTime,
      kFirstRestartTime,
      kFirstRecompileTime,
      kSecondStartupTime,
      kSecondRestartTime,
    ]);
  };
}
