// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:args/args.dart';
import 'package:dds/devtools_server.dart';
import 'package:dds_service_extensions/dds_service_extensions.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:vm_service/vm_service.dart';
import 'package:vm_service/vm_service_io.dart';

import '../core.dart';
import '../dds_runner.dart';
import '../sdk.dart';
import '../utils.dart';

class DevToolsCommand extends DartdevCommand {
  DevToolsCommand({this.customDevToolsPath, bool verbose = false})
    : argParser = DevToolsServer.buildArgParser(
        verbose: verbose,
        includeHelpOption: false,
        usageLineLength: dartdevUsageLineLength,
      ),
      super('devtools', DevToolsServer.commandDescription, verbose);

  final String? customDevToolsPath;

  @override
  final ArgParser argParser;

  @override
  String get name => 'devtools';

  @override
  CommandCategory get commandCategory => CommandCategory.tools;

  @override
  String get description => DevToolsServer.commandDescription;

  @override
  String get invocation => '${super.invocation} [service protocol uri]';

  @override
  Future<int> run() async {
    final args = argResults!;

    final sdkDir = path.dirname(sdk.dart);
    final fullSdk = sdkDir.endsWith('bin');
    final devToolsBinaries = fullSdk
        ? sdk.devToolsBinaries
        : path.absolute(sdkDir, 'devtools');

    final argList = await _performDDSCheck(args);
    final server = await DevToolsServer().serveDevToolsWithArgs(
      argList,
      customDevToolsPath: devToolsBinaries,
    );
    return server == null ? -1 : 0;
  }

  /// Attempts to start a DDS instance if there isn't one running for the
  /// target application.
  ///
  /// Returns the argument list from [args], which is modified to include the
  /// DDS URI instead of the VM service URI if DDS is started by this method
  /// or a redirect to DDS would be followed.
  Future<List<String>> _performDDSCheck(ArgResults args) async {
    String? serviceProtocolUri;
    bool positionalServiceUri = false;
    if (args.rest.isNotEmpty) {
      serviceProtocolUri = args.rest.first;
      positionalServiceUri = true;
    } else if (args.wasParsed(DevToolsServer.argVmUri)) {
      serviceProtocolUri = args.option(DevToolsServer.argVmUri)!;
    }

    final argList = args.arguments.toList();

    // No VM service URI was provided, so the user is going to manually connect
    // to their application from DevTools or only use offline tooling.
    //
    // TODO(bkonyi): we should consider having devtools_server try and spawn
    // DDS if users try to connect to an application without a DDS instance.
    if (serviceProtocolUri == null) {
      return argList;
    }

    final originalUri = Uri.parse(serviceProtocolUri);
    var uri = originalUri;
    // The VM service doesn't like it when there's no trailing forward slash at
    // the end of the path. Add one if it's missing.
    uri = _ensureUriHasTrailingForwardSlash(uri);

    // Check to see if the URI is a VM service URI for a VM service instance
    // that already has a DDS instance connected.
    uri = await checkForRedirectToExistingDDSInstance(uri);

    // If this isn't a URI for a VM service with an active DDS instance,
    // check to see if this URI points to a running DDS instance. If not, try
    // and start DDS.
    if (uri == originalUri) {
      uri = await maybeStartDDS(
        uri: uri,
        ddsHost: args.option(DevToolsServer.argDdsHost)!,
        ddsPort: args.option(DevToolsServer.argDdsPort)!,
        machineMode: args.wasParsed(DevToolsServer.argMachine),
      );
    }

    // If we ended up starting DDS or redirecting to an existing instance,
    // update the argument list to include the actual URI for DevTools to
    // connect to.
    if (uri != originalUri) {
      if (positionalServiceUri) {
        argList.removeLast();
      }
      argList.add(uri.toString());
    }

    return argList;
  }

  Uri _ensureUriHasTrailingForwardSlash(Uri uri) {
    if (uri.pathSegments.isNotEmpty) {
      final pathSegments = uri.pathSegments.toList();
      if (pathSegments.last.isNotEmpty) {
        pathSegments.add('');
      }
      uri = uri.replace(pathSegments: pathSegments);
    }
    return uri;
  }

  @visibleForTesting
  static Future<Uri> checkForRedirectToExistingDDSInstance(Uri uri) async {
    final request = http.Request('GET', uri)..followRedirects = false;
    final response = await request.send();
    await response.stream.drain();

    // If we're redirected that means that we attempted to speak directly to
    // the VM service even though there's an active DDS instance already
    // connected to it. In this case, DevTools will fail to connect to the VM
    // service directly so we need to modify the target URI in the args list to
    // instead point to the DDS instance.
    if (response.isRedirect) {
      final redirectUri = Uri.parse(response.headers['location']!);
      final ddsWsUri = Uri.parse(redirectUri.queryParameters['uri']!);

      // Remove '/ws' from the path, add a trailing '/'
      var pathSegments = ddsWsUri.pathSegments.toList()
        ..removeLast()
        ..add('');
      if (pathSegments.length == 1) {
        pathSegments.add('');
      }
      uri = ddsWsUri.replace(scheme: 'http', pathSegments: pathSegments);
    }
    return uri;
  }

  @visibleForTesting
  static Future<Uri> maybeStartDDS({
    required Uri uri,
    required String ddsHost,
    required String ddsPort,
    bool machineMode = false,
  }) async {
    final pathSegments = uri.pathSegments.toList();
    if (pathSegments.isNotEmpty && pathSegments.last.isEmpty) {
      // There's a trailing '/' at the end of the parsed URI, so there's an
      // empty string at the end of the path segments list that needs to be
      // removed.
      pathSegments.removeLast();
    }

    final authCodesEnabled = pathSegments.isNotEmpty;
    final wsUri = uri.replace(
      scheme: 'ws',
      pathSegments: [...pathSegments, 'ws'],
    );

    final vmService = await vmServiceConnectUri(wsUri.toString());

    try {
      // If this request throws a RPC error, DDS isn't running and we should
      // try and start it.
      await vmService.getDartDevelopmentServiceVersion();
    } on RPCError {
      // If the user wants to start a debugging session we need to do some extra
      // work and spawn a Dart Development Service (DDS) instance. DDS is a VM
      // service intermediary which implements the VM service protocol and
      // provides non-VM specific extensions (e.g., log caching, client
      // synchronization).
      final debugSession = DDSRunner();
      if (await debugSession.start(
        vmServiceUri: uri,
        ddsHost: ddsHost,
        ddsPort: ddsPort,
        debugDds: false,
        disableServiceAuthCodes: !authCodesEnabled,
        // TODO(bkonyi): should we just have DDS serve its own duplicate
        // DevTools instance? It shouldn't add much, if any, overhead but will
        // allow for developers to access DevTools directly through the VM
        // service URI at a later point. This would probably be a fairly niche
        // workflow.
        enableDevTools: false,
        enableServicePortFallback: true,
      )) {
        uri = debugSession.ddsUri!;
        if (!machineMode) {
          print('Started the Dart Development Service (DDS) at $uri');
        }
      } else if (!machineMode) {
        print(
          'WARNING: Failed to start the Dart Development Service (DDS). '
          'Some development features may be disabled or degraded.',
        );
      }
    } finally {
      await vmService.dispose();
    }
    return uri;
  }
}
