// 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 '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();
    }
  }
}
