// Copyright (c) 2015, 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 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:coverage/coverage.dart';
import 'package:path/path.dart' as p;
import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
import 'package:test_core/src/util/io.dart'; // ignore: implementation_imports
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

import '../executable_settings.dart';
import 'browser.dart';
import 'chromium.dart';
import 'default_settings.dart';

/// A class for running an instance of Chrome.
///
/// Most of the communication with the browser is expected to happen via HTTP,
/// so this exposes a bare-bones API. The browser starts as soon as the class is
/// constructed, and is killed when [close] is called.
///
/// Any errors starting or running the process are reported through [onExit].
class Chrome extends Browser {
  @override
  final name = 'Chrome';

  @override
  final Future<Uri?> remoteDebuggerUrl;

  final Future<WipConnection> _tabConnection;
  final Map<String, String> _idToUrl;

  /// Starts a new instance of Chrome open to the given [url], which may be a
  /// [Uri] or a [String].
  factory Chrome(
    Uri url,
    Configuration configuration, {
    ExecutableSettings? settings,
  }) {
    settings ??= defaultSettings[Runtime.chrome]!;
    var remoteDebuggerCompleter = Completer<Uri?>.sync();
    var connectionCompleter = Completer<WipConnection>();
    var idToUrl = <String, String>{};
    return Chrome._(
      () async {
        Future<Process> tryPort([int? port]) async {
          var process = await ChromiumBasedBrowser.chrome.spawn(
            url,
            configuration,
            settings: settings,
            additionalArgs: [
              if (port != null)
                // Chrome doesn't provide any way of ensuring that this port was
                // successfully bound. It produces an error if the binding fails,
                // but without a reliable and fast way to tell if it succeeded
                // that doesn't provide us much. It's very unlikely that this port
                // will fail, though.
                '--remote-debugging-port=$port',
            ],
          );

          if (port != null) {
            remoteDebuggerCompleter.complete(
              getRemoteDebuggerUrl(Uri.parse('http://localhost:$port')),
            );

            connectionCompleter.complete(_connect(process, port, idToUrl, url));
          } else {
            remoteDebuggerCompleter.complete(null);
          }

          return process;
        }

        if (!configuration.debug) return tryPort();
        return getUnusedPort<Process>(tryPort);
      },
      remoteDebuggerCompleter.future,
      connectionCompleter.future,
      idToUrl,
    );
  }

  /// Returns a Dart based hit-map containing coverage report, suitable for use
  /// with `package:coverage`.
  Future<Map<String, dynamic>> gatherCoverage() async {
    var tabConnection = await _tabConnection;
    var response = await tabConnection.debugger.connection.sendCommand(
      'Profiler.takePreciseCoverage',
      {},
    );
    var result = (response.result!['result'] as List)
        .cast<Map<String, dynamic>>();
    var httpClient = HttpClient();
    var coverage = await parseChromeCoverage(
      result,
      (scriptId) => _sourceProvider(scriptId, httpClient),
      (scriptId) => _sourceMapProvider(scriptId, httpClient),
      _sourceUriProvider,
    );
    httpClient.close(force: true);
    return coverage;
  }

  Chrome._(
    super.startBrowser,
    this.remoteDebuggerUrl,
    this._tabConnection,
    this._idToUrl,
  );

  Future<Uri?> _sourceUriProvider(String sourceUrl, String scriptId) async {
    var script = _idToUrl[scriptId];
    if (script == null) return null;
    var sourceUri = Uri.parse(sourceUrl);
    if (sourceUri.scheme == 'file') return sourceUri;
    // If the provided sourceUrl is relative, determine the package path.
    var uri = Uri.parse(script);
    var path = p.join(
      p.joinAll(uri.pathSegments.sublist(1, uri.pathSegments.length - 1)),
      sourceUrl,
    );
    return path.contains('/packages/')
        ? Uri(scheme: 'package', path: path.split('/packages/').last)
        : null;
  }

  Future<String?> _sourceMapProvider(
    String scriptId,
    HttpClient httpClient,
  ) async {
    var script = _idToUrl[scriptId];
    if (script == null) return null;
    return await httpClient.getString('$script.map');
  }

  Future<String?> _sourceProvider(
    String scriptId,
    HttpClient httpClient,
  ) async {
    var script = _idToUrl[scriptId];
    if (script == null) return null;
    return await httpClient.getString(script);
  }
}

Future<WipConnection> _connect(
  Process process,
  int port,
  Map<String, String> idToUrl,
  Uri url,
) async {
  // Wait for Chrome to be in a ready state.
  await process.stderr
      .transform(utf8.decoder)
      .transform(const LineSplitter())
      .firstWhere((line) => line.startsWith('DevTools listening'));

  var chromeConnection = ChromeConnection('localhost', port);
  ChromeTab? tab;
  var attempt = 0;
  while (tab == null) {
    attempt++;
    var tabs = await chromeConnection.getTabs();
    tab = tabs.firstWhereOrNull((tab) => tab.url == url.toString());
    if (tab == null) {
      await Future<void>.delayed(const Duration(milliseconds: 100));
      if (attempt > 5) {
        throw StateError('Could not connect to test tab with url: $url');
      }
    }
  }
  var tabConnection = await tab.connect();

  // Enable debugging.
  await tabConnection.debugger.enable();

  // Coverage reports are in terms of scriptIds so keep note of URLs.
  tabConnection.debugger.onScriptParsed.listen((data) {
    var script = data.script;
    if (script.url.isNotEmpty) idToUrl[script.scriptId] = script.url;
  });

  // Enable coverage collection.
  await tabConnection.debugger.connection.sendCommand('Profiler.enable', {});
  await tabConnection.debugger.connection.sendCommand(
    'Profiler.startPreciseCoverage',
    {'detailed': true, 'callCount': false},
  );

  return tabConnection;
}

extension on HttpClient {
  Encoding determineEncoding(HttpHeaders headers) {
    final contentType = headers.contentType?.charset;

    /// Using the `charset` property of the `contentType` if available.
    /// If it's unavailable or if the encoding name is unknown, [latin1] is used by default,
    /// as per [RFC 2616][].
    ///
    /// [RFC 2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
    return Encoding.getByName(contentType) ?? latin1;
  }

  Future<String?> getString(String url) async {
    final request = await getUrl(Uri.parse(url));
    final response = await request.close();
    if (response.statusCode != HttpStatus.ok) return null;
    var bytes = [await for (var chunk in response) ...chunk];
    final encoding = determineEncoding(response.headers);
    return encoding.decode(bytes);
  }
}
