// 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.

// @dart = 2.8

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';

import 'base/bot_detector.dart';
import 'base/common.dart';
import 'base/io.dart' as io;
import 'base/logger.dart';
import 'convert.dart';
import 'resident_runner.dart';

/// An implementation of the devtools launcher that uses `pub global activate` to
/// start a server instance.
class DevtoolsServerLauncher extends DevtoolsLauncher {
  DevtoolsServerLauncher({
    @required ProcessManager processManager,
    @required String dartExecutable,
    @required Logger logger,
    @required BotDetector botDetector,
  })  : _processManager = processManager,
        _dartExecutable = dartExecutable,
        _logger = logger,
        _botDetector = botDetector;

  final ProcessManager _processManager;
  final String _dartExecutable;
  final Logger _logger;
  final BotDetector _botDetector;
  final Completer<void> _processStartCompleter = Completer<void>();

  io.Process _devToolsProcess;
  bool _devToolsProcessKilled = false;
  @visibleForTesting
  Future<void> devToolsProcessExit;

  static final RegExp _serveDevToolsPattern =
      RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');

  @override
  Future<void> get processStart => _processStartCompleter.future;

  @override
  Future<void> launch(Uri vmServiceUri, {List<String> additionalArguments}) async {
    // Place this entire method in a try/catch that swallows exceptions because
    // this method is guaranteed not to return a Future that throws.
    try {
      _devToolsProcess = await _processManager.start(<String>[
        _dartExecutable,
        'devtools',
        '--no-launch-browser',
        if (vmServiceUri != null) '--vm-uri=$vmServiceUri',
        ...?additionalArguments,
      ]);
      _processStartCompleter.complete();
      final Completer<Uri> completer = Completer<Uri>();
      _devToolsProcess.stdout
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .listen((String line) {
            final Match match = _serveDevToolsPattern.firstMatch(line);
            if (match != null) {
              final String url = match[1];
              completer.complete(Uri.parse(url));
            }
         });
      _devToolsProcess.stderr
          .transform(utf8.decoder)
          .transform(const LineSplitter())
          .listen(_logger.printError);

      final bool runningOnBot = await _botDetector.isRunningOnBot;
      devToolsProcessExit = _devToolsProcess.exitCode.then(
        (int exitCode) {
          if (!_devToolsProcessKilled && runningOnBot) {
            throwToolExit('DevTools process failed: exitCode=$exitCode');
          }
        }
      );

      devToolsUrl = await completer.future;
    } on Exception catch (e, st) {
      _logger.printError('Failed to launch DevTools: $e', stackTrace: st);
    }
  }

  @override
  Future<DevToolsServerAddress> serve() async {
    if (activeDevToolsServer == null) {
      await launch(null);
    }
    return activeDevToolsServer;
  }

  @override
  Future<void> close() async {
    if (devToolsUrl != null) {
      devToolsUrl = null;
    }
    if (_devToolsProcess != null) {
      _devToolsProcessKilled = true;
      _devToolsProcess.kill();
    }
  }
}
