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