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

@JS()
library;

import 'dart:async';
import 'dart:convert';

import 'package:collection/collection.dart' show IterableExtension;
import 'package:dwds/data/data_types.dart';
import 'package:dwds/data/debug_info.dart';
import 'package:dwds/data/devtools_request.dart';
import 'package:dwds/data/extension_request.dart';
import 'package:dwds/shared/batched_stream.dart';
import 'package:dwds/src/sockets.dart';
// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'package:js/js.dart';
// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'package:js/js_util.dart' as js_util;
import 'package:sse/client/sse_client.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

import 'chrome_api.dart';
import 'cider_connection.dart';
import 'cross_extension_communication.dart';
import 'logger.dart';
import 'messaging.dart';
import 'storage.dart';
import 'utils.dart';
import 'web_api.dart';

const _notADartAppAlert =
    'No Dart application detected.'
    ' Are you trying to debug an application that includes a Chrome hosted app'
    ' (an application listed in chrome://apps)? If so, debugging is disabled.'
    ' You can fix this by removing the application from chrome://apps. Please'
    ' see https://bugs.chromium.org/p/chromium/issues/detail?id=885025#c11.';

const _devToolsAlreadyOpenedAlert =
    'DevTools is already opened on a different window.';

final _debugSessions = <_DebugSession>[];
final _tabIdToTrigger = <int, Trigger>{};

enum DetachReason {
  canceledByUser,
  connectionErrorEvent,
  connectionDoneEvent,
  devToolsTabClosed,
  navigatedAwayFromApp,
  staleDebugSession,
  unknown;

  factory DetachReason.fromString(String value) {
    return DetachReason.values.byName(value);
  }
}

enum ConnectFailureReason {
  authentication,
  noDartApp,
  timeout,
  unknown;

  factory ConnectFailureReason.fromString(String value) {
    return ConnectFailureReason.values.byName(value);
  }
}

enum TabType { dartApp, devTools }

enum Trigger {
  angularDartDevTools,
  cider,
  extensionPanel,
  extensionIcon;

  String get clientName => switch (this) {
    Trigger.angularDartDevTools => 'acx-devtools',
    Trigger.cider => 'cider',
    Trigger.extensionPanel => 'embedded-devtools',
    Trigger.extensionIcon => 'devtools',
  };
}

enum DebuggerLocation {
  angularDartDevTools,
  chromeDevTools,
  dartDevTools,
  ide;

  String get displayName => switch (this) {
    DebuggerLocation.angularDartDevTools => 'AngularDart DevTools',
    DebuggerLocation.chromeDevTools => 'Chrome DevTools',
    DebuggerLocation.dartDevTools => 'a Dart DevTools tab',
    DebuggerLocation.ide => 'an IDE',
  };
}

bool get existsActiveDebugSession => _debugSessions.isNotEmpty;

int? get latestAppBeingDebugged =>
    existsActiveDebugSession ? _debugSessions.last.appTabId : null;

Future<void> attachDebugger(
  int dartAppTabId, {
  required Trigger trigger,
}) async {
  // Validate that the tab can be debugged:
  final tabIsDebuggable = await _validateTabIsDebuggable(
    dartAppTabId,
    forwardErrorsToCider: trigger == Trigger.cider,
  );
  if (!tabIsDebuggable) return;
  debugLog('Attaching to tab $dartAppTabId', verbose: true);
  _tabIdToTrigger[dartAppTabId] = trigger;
  _registerDebugEventListeners();
  chrome.debugger.attach(
    Debuggee(tabId: dartAppTabId),
    '1.3',
    allowInterop(() => _enableExecutionContextReporting(dartAppTabId)),
  );
}

Future<bool> detachDebugger(
  int tabId, {
  required TabType type,
  required DetachReason reason,
}) async {
  final debugSession = _debugSessionForTab(tabId, type: type);
  if (debugSession == null) return false;
  final debuggee = Debuggee(tabId: debugSession.appTabId);
  final completer = Completer<bool>();
  chrome.debugger.detach(
    debuggee,
    allowInterop(() {
      final error = chrome.runtime.lastError;
      if (error != null) {
        debugWarn(
          'Error detaching tab for reason: $reason. Error: ${error.message}',
        );
        completer.complete(false);
      } else {
        _handleDebuggerDetach(debuggee, reason);
        completer.complete(true);
      }
    }),
  );
  return completer.future;
}

bool isActiveDebugSession(int tabId) =>
    _debugSessionForTab(tabId, type: TabType.dartApp) != null;

Future<void> clearStaleDebugSession(int tabId) async {
  final debugSession = _debugSessionForTab(tabId, type: TabType.dartApp);
  if (debugSession != null) {
    await detachDebugger(
      tabId,
      type: TabType.dartApp,
      reason: DetachReason.staleDebugSession,
    );
  } else {
    await _removeDebugSessionDataInStorage(tabId);
  }
}

Future<bool> _validateTabIsDebuggable(
  int dartAppTabId, {
  bool forwardErrorsToCider = false,
}) async {
  // Check if a debugger is already attached:
  final existingDebuggerLocation = _debuggerLocation(dartAppTabId);
  if (existingDebuggerLocation != null) {
    await _showWarning(
      'Already debugging in ${existingDebuggerLocation.displayName}.',
      forwardToCider: forwardErrorsToCider,
    );
    return false;
  }
  // Determine if this is a Dart app:
  final debugInfo = await fetchStorageObject<DebugInfo>(
    type: StorageObject.debugInfo,
    tabId: dartAppTabId,
  );
  if (debugInfo == null) {
    await _showWarning('Not a Dart app.', forwardToCider: forwardErrorsToCider);
    return false;
  }
  // Determine if there are multiple apps in the tab:
  final multipleApps = await fetchStorageObject<String>(
    type: StorageObject.multipleAppsDetected,
    tabId: dartAppTabId,
  );
  if (multipleApps != null) {
    await _showWarning(
      'Dart debugging is not supported in a multi-app environment.',
      forwardToCider: forwardErrorsToCider,
    );
    return false;
  }
  // Verify that the user is authenticated:
  final isAuthenticated = await _authenticateUser(dartAppTabId);
  return isAuthenticated;
}

void _registerDebugEventListeners() {
  chrome.debugger.onEvent.addListener(allowInterop(_onDebuggerEvent));
  chrome.debugger.onDetach.addListener(
    allowInterop((source, _) async {
      await _handleDebuggerDetach(source, DetachReason.canceledByUser);
    }),
  );
  chrome.tabs.onRemoved.addListener(
    allowInterop((tabId, _) async {
      await detachDebugger(
        tabId,
        type: TabType.devTools,
        reason: DetachReason.devToolsTabClosed,
      );
    }),
  );
}

void _enableExecutionContextReporting(int tabId) {
  // Runtime.enable enables reporting of execution contexts creation by means of
  // executionContextCreated event. When the reporting gets enabled the event
  // will be sent immediately for each existing execution context:
  chrome.debugger.sendCommand(
    Debuggee(tabId: tabId),
    'Runtime.enable',
    EmptyParam(),
    allowInterop((_) {
      final chromeError = chrome.runtime.lastError;
      if (chromeError != null) {
        final errorMessage = _translateChromeError(chromeError.message);
        displayNotification(errorMessage, isError: true);
        return;
      }
    }),
  );
}

String _translateChromeError(String chromeErrorMessage) {
  if (chromeErrorMessage.contains('Cannot access') ||
      chromeErrorMessage.contains('Cannot attach')) {
    return _notADartAppAlert;
  }
  return _devToolsAlreadyOpenedAlert;
}

Future<void> _onDebuggerEvent(
  Debuggee source,
  String method,
  Object? params,
) async {
  final tabId = source.tabId;
  maybeForwardMessageToAngularDartDevTools(
    method: method,
    params: params,
    tabId: source.tabId,
  );

  if (method == 'Runtime.executionContextCreated') {
    // Only try to connect to DWDS if we don't already have a debugger instance:
    if (_debuggerLocation(tabId) == null) {
      return _maybeConnectToDwds(source.tabId, params);
    }
  }

  return _forwardChromeDebuggerEventToDwds(source, method, params);
}

Future<void> _maybeConnectToDwds(int tabId, Object? params) async {
  final context = json.decode(JSON.stringify(params))['context'];
  final contextOrigin = context['origin'] as String?;
  if (contextOrigin == null) return;
  if (contextOrigin.contains('chrome-extension:')) return;
  final debugInfo = await fetchStorageObject<DebugInfo>(
    type: StorageObject.debugInfo,
    tabId: tabId,
  );
  if (debugInfo == null) return;
  if (contextOrigin != debugInfo.appOrigin) return;
  final contextId = context['id'] as int;
  // Find the correct frame to connect to (this is necessary if the Dart app is
  // embedded in an IFRAME):
  final isDartFrame = await _isDartFrame(tabId: tabId, contextId: contextId);
  if (!isDartFrame) return;
  final connected = await _connectToDwds(
    dartAppContextId: contextId,
    dartAppTabId: tabId,
    debugInfo: debugInfo,
  );
  if (!connected) {
    debugWarn('Failed to connect to DWDS for $contextOrigin.');
    await _sendConnectFailureMessage(
      ConnectFailureReason.unknown,
      dartAppTabId: tabId,
    );
  }
}

Future<bool> _isDartFrame({required int tabId, required int contextId}) {
  final completer = Completer<bool>();
  chrome.debugger.sendCommand(
    Debuggee(tabId: tabId),
    'Runtime.evaluate',
    _InjectedParams(
      expression:
          '[window.\$dartAppId, '
          'window.\$dartAppInstanceId, '
          'window.\$dwdsVersion]',
      returnByValue: true,
      contextId: contextId,
    ),
    allowInterop((dynamic response) {
      final evalResponse = response as _EvalResponse;
      final value = evalResponse.result.value;
      final appId = value?[0];
      final instanceId = value?[1];
      final dwdsVersion = value?[2];
      final frameIdentifier = 'Frame at tab $tabId with context $contextId';
      if (appId == null || instanceId == null) {
        debugWarn('$frameIdentifier is not a Dart frame.');
        completer.complete(false);
      } else {
        debugLog('Dart $frameIdentifier is using DWDS $dwdsVersion.');
        completer.complete(true);
      }
    }),
  );
  return completer.future;
}

Future<bool> _connectToDwds({
  required int dartAppContextId,
  required int dartAppTabId,
  required DebugInfo debugInfo,
}) async {
  final extensionUrl = debugInfo.extensionUrl;
  if (extensionUrl == null) {
    debugWarn('Can\'t connect to DWDS without an extension URL.');
    return false;
  }
  final uri = Uri.parse(extensionUrl);
  // Start the client connection with DWDS:
  final client = uri.isScheme('ws') || uri.isScheme('wss')
      ? WebSocketClient(WebSocketChannel.connect(uri))
      : SseSocketClient(SseClient(uri.toString(), debugKey: 'DebugExtension'));
  final trigger = _tabIdToTrigger[dartAppTabId];
  debugLog('Connecting to DWDS...', verbose: true);
  final debugSession = _DebugSession(
    client: client,
    appTabId: dartAppTabId,
    trigger: trigger,
    onIncoming: (data) => _routeDwdsEvent(data, client, dartAppTabId),
    onDone: () async {
      await detachDebugger(
        dartAppTabId,
        type: TabType.dartApp,
        reason: DetachReason.connectionDoneEvent,
      );
    },
    onError: (err) async {
      debugWarn('Connection error: $err', verbose: true);
      await detachDebugger(
        dartAppTabId,
        type: TabType.dartApp,
        reason: DetachReason.connectionErrorEvent,
      );
    },
    cancelOnError: true,
  );
  _debugSessions.add(debugSession);
  // Send a DevtoolsRequest to the event stream:
  final tabUrl = await _getTabUrl(dartAppTabId);
  debugSession.sendEvent(
    DevToolsRequest(
      appId: debugInfo.appId!,
      instanceId: debugInfo.appInstanceId!,
      contextId: dartAppContextId,
      tabUrl: tabUrl,
      uriOnly: true,
      client: trigger?.clientName ?? 'unknown',
    ),
  );
  return true;
}

void _routeDwdsEvent(String eventData, SocketClient client, int tabId) {
  final decoded = jsonDecode(eventData);
  Object? message;
  if (decoded case ['ExtensionRequest', ...]) {
    message = ExtensionRequest.fromJson(decoded);
  } else if (decoded case ['ExtensionEvent', ...]) {
    message = ExtensionEvent.fromJson(decoded);
  }

  if (message is ExtensionRequest) {
    _forwardDwdsEventToChromeDebugger(message, client, tabId);
  } else if (message is ExtensionEvent) {
    maybeForwardMessageToAngularDartDevTools(
      method: message.method,
      params: message.params,
      tabId: tabId,
    );
    if (message.method == 'dwds.devtoolsUri') {
      if (_tabIdToTrigger[tabId] == Trigger.cider) {
        // Save the DevTools URI so that Cider can request it later:
        setStorageObject(
          type: StorageObject.devToolsUri,
          value: message.params,
          tabId: tabId,
        );
      } else {
        _openDevTools(message.params, dartAppTabId: tabId);
      }
    }
    if (message.method == 'dwds.debugUri') {
      debugLog('Sending debug URI to Cider ${message.params}', verbose: true);
      sendMessageToCider(
        messageType: CiderMessageType.startDebugResponse,
        messageBody: message.params,
      );
    }
    if (message.method == 'dwds.encodedUri') {
      setStorageObject(
        type: StorageObject.encodedUri,
        value: message.params,
        tabId: tabId,
      );
    }
  }
}

void _forwardDwdsEventToChromeDebugger(
  ExtensionRequest message,
  SocketClient client,
  int tabId,
) {
  try {
    final messageParams = message.commandParams;
    final params = messageParams == null
        ? <String, Object>{}
        : Map<String, Object>.from(json.decode(messageParams) as Map);

    chrome.debugger.sendCommand(
      Debuggee(tabId: tabId),
      message.command,
      js_util.jsify(params),
      allowInterop(([e]) {
        // No arguments indicate that an error occurred.
        if (e == null) {
          client.sink.add(
            jsonEncode(
              ExtensionResponse(
                id: message.id,
                success: false,
                result: JSON.stringify(chrome.runtime.lastError),
              ),
            ),
          );
        } else {
          client.sink.add(
            jsonEncode(
              ExtensionResponse(
                id: message.id,
                success: true,
                result: JSON.stringify(e),
              ),
            ),
          );
        }
      }),
    );
  } catch (error) {
    debugError(
      'Error forwarding ${message.command} with ${message.commandParams} to '
      'chrome.debugger: $error',
    );
  }
}

void _forwardChromeDebuggerEventToDwds(
  Debuggee source,
  String method,
  dynamic params,
) {
  final debugSession = _debugSessions.firstWhereOrNull(
    (session) => session.appTabId == source.tabId,
  );
  if (debugSession == null) return;
  final event = _extensionEventFor(method, params);
  if (method == 'Debugger.scriptParsed') {
    debugSession.sendBatchedEvent(event);
  } else {
    debugSession.sendEvent(event);
  }
}

Future<void> _openDevTools(
  String devToolsUri, {
  required int dartAppTabId,
}) async {
  if (devToolsUri.isEmpty) {
    debugError('DevTools URI is empty.');
    return;
  }
  final debugSession = _debugSessionForTab(dartAppTabId, type: TabType.dartApp);
  if (debugSession == null) {
    debugError('Debug session not found.');
    return;
  }
  // Save the DevTools URI so that the extension panels have access to it:
  await setStorageObject(
    type: StorageObject.devToolsUri,
    value: devToolsUri,
    tabId: dartAppTabId,
  );
  // Open a separate tab / window if triggered through the extension icon or
  // through AngularDart DevTools:
  if (debugSession.trigger == Trigger.extensionIcon ||
      debugSession.trigger == Trigger.angularDartDevTools) {
    final devToolsOpener = await fetchStorageObject<DevToolsOpener>(
      type: StorageObject.devToolsOpener,
    );
    final devToolsTab = await createTab(
      addQueryParameters(
        devToolsUri,
        queryParameters: {'ide': 'DebugExtension'},
      ),
      inNewWindow: devToolsOpener?.newWindow ?? false,
    );
    debugSession.devToolsTabId = devToolsTab.id;
  }
}

Future<void> _handleDebuggerDetach(Debuggee source, DetachReason reason) async {
  final tabId = source.tabId;
  debugLog(
    'Debugger detached due to: $reason',
    verbose: true,
    prefix: '$tabId',
  );
  final debugSession = _debugSessionForTab(tabId, type: TabType.dartApp);
  if (debugSession != null) {
    debugLog('Removing debug session...');
    _removeDebugSession(debugSession);
    // Notify the extension panels that the debug session has ended:
    await _sendStopDebuggingMessage(reason, dartAppTabId: tabId);
    // Maybe close the associated DevTools tab as well:
    await _maybeCloseDevTools(debugSession.devToolsTabId);
  }
  await _removeDebugSessionDataInStorage(tabId);
}

Future<void> _maybeCloseDevTools(int? devToolsTabId) async {
  if (devToolsTabId == null) return;
  final devToolsTab = await getTab(devToolsTabId);
  if (devToolsTab != null) {
    debugLog('Closing DevTools tab...');
    await removeTab(devToolsTabId);
  }
}

Future<void> _removeDebugSessionDataInStorage(int tabId) async {
  // Remove the DevTools URI, encoded URI, and multiple apps info from storage:
  await removeStorageObject(type: StorageObject.devToolsUri, tabId: tabId);
  await removeStorageObject(type: StorageObject.encodedUri, tabId: tabId);
  await removeStorageObject(
    type: StorageObject.multipleAppsDetected,
    tabId: tabId,
  );
}

void _removeDebugSession(_DebugSession debugSession) {
  // Note: package:sse will try to keep the connection alive, even after the
  // client has been closed. Therefore the extension sends an event to notify
  // DWDS that we should close the connection, instead of relying on the done
  // event sent when the client is closed. See details:
  // https://github.com/dart-lang/webdev/pull/1595#issuecomment-1116773378
  final event = _extensionEventFor(
    'DebugExtension.detached',
    js_util.jsify({}),
  );
  debugSession.sendEvent(event);
  debugSession.close();
  final removed = _debugSessions.remove(debugSession);
  if (!removed) {
    debugWarn('Could not remove debug session.');
  }
}

Future<bool> _sendConnectFailureMessage(
  ConnectFailureReason reason, {
  required int dartAppTabId,
}) async {
  final json = jsonEncode(
    ConnectFailure(tabId: dartAppTabId, reason: reason.name),
  );
  return await sendRuntimeMessage(
    type: MessageType.connectFailure,
    body: json,
    sender: Script.background,
    recipient: Script.debuggerPanel,
  );
}

Future<bool> _sendStopDebuggingMessage(
  DetachReason reason, {
  required int dartAppTabId,
}) async {
  final json = jsonEncode(
    DebugStateChange(
      tabId: dartAppTabId,
      newState: DebugStateChange.stopDebugging,
      reason: reason.name,
    ),
  );
  return await sendRuntimeMessage(
    type: MessageType.debugStateChange,
    body: json,
    sender: Script.background,
    recipient: Script.debuggerPanel,
  );
}

_DebugSession? _debugSessionForTab(int tabId, {required TabType type}) {
  return switch (type) {
    TabType.dartApp => _debugSessions.firstWhereOrNull(
      (session) => session.appTabId == tabId,
    ),
    TabType.devTools => _debugSessions.firstWhereOrNull(
      (session) => session.devToolsTabId == tabId,
    ),
  };
}

Future<bool> _authenticateUser(int tabId) async {
  final isAlreadyAuthenticated = await _fetchIsAuthenticated(tabId);
  if (isAlreadyAuthenticated) return true;
  final debugInfo = await fetchStorageObject<DebugInfo>(
    type: StorageObject.debugInfo,
    tabId: tabId,
  );
  final authUrl = debugInfo?.authUrl ?? _authUrl(debugInfo?.extensionUrl);
  if (authUrl == null) {
    await _showWarningNotification('Cannot authenticate user.');
    return false;
  }
  final isAuthenticated = await _sendAuthRequest(authUrl);
  if (isAuthenticated) {
    await setStorageObject<String>(
      type: StorageObject.isAuthenticated,
      value: '$isAuthenticated',
      tabId: tabId,
    );
  } else {
    await _sendConnectFailureMessage(
      ConnectFailureReason.authentication,
      dartAppTabId: tabId,
    );
    await createTab(authUrl, inNewWindow: false);
  }
  return isAuthenticated;
}

Future<bool> _fetchIsAuthenticated(int tabId) async {
  final authenticated = await fetchStorageObject<String>(
    type: StorageObject.isAuthenticated,
    tabId: tabId,
  );
  return authenticated == 'true';
}

Future<bool> _sendAuthRequest(String authUrl) async {
  final response = await fetchRequest(authUrl);
  final responseBody = response.body ?? '';
  return responseBody.contains('Dart Debug Authentication Success!');
}

Future<bool> _showWarning(String message, {bool forwardToCider = false}) {
  if (forwardToCider) {
    sendErrorMessageToCider(
      errorType: CiderErrorType.invalidRequest,
      errorDetails: message,
    );
    return Future.value(true);
  } else {
    return _showWarningNotification(message);
  }
}

Future<bool> _showWarningNotification(String message) {
  final completer = Completer<bool>();
  displayNotification(
    message,
    isError: true,
    callback: allowInterop((_) {
      completer.complete(true);
    }),
  );
  return completer.future;
}

DebuggerLocation? _debuggerLocation(int dartAppTabId) {
  final debugSession = _debugSessionForTab(dartAppTabId, type: TabType.dartApp);
  final trigger = _tabIdToTrigger[dartAppTabId];
  if (debugSession == null || trigger == null) return null;

  return switch (trigger) {
    Trigger.angularDartDevTools => DebuggerLocation.angularDartDevTools,
    Trigger.cider => DebuggerLocation.ide,
    Trigger.extensionPanel => DebuggerLocation.chromeDevTools,
    Trigger.extensionIcon =>
      debugSession.devToolsTabId != null
          ? DebuggerLocation.dartDevTools
          : DebuggerLocation.ide,
  };
}

/// Construct an [ExtensionEvent] from [method] and [params].
ExtensionEvent _extensionEventFor(String method, dynamic params) {
  return ExtensionEvent(
    params: jsonEncode(json.decode(JSON.stringify(params))),
    method: jsonEncode(method),
  );
}

Future<String> _getTabUrl(int tabId) async {
  final tab = await getTab(tabId);
  return tab?.url ?? '';
}

@JS()
@anonymous
class EmptyParam {
  external factory EmptyParam();
}

class _DebugSession {
  // The tab ID that contains the running Dart application.
  final int appTabId;

  // What triggered the debug session (debugger panel, extension icon, etc.)
  final Trigger? trigger;

  // Socket client for communication with dwds extension backend.
  late final SocketClient _socketClient;

  // How often to send batched events.
  static const int _batchDelayMilliseconds = 1000;

  // The tab ID that contains the corresponding Dart DevTools, if it exists.
  int? devToolsTabId;

  // Collect events into batches to be send periodically to the server.
  final _batchController = BatchedStreamController<ExtensionEvent>(
    delay: _batchDelayMilliseconds,
  );
  late final StreamSubscription<List<ExtensionEvent>> _batchSubscription;

  _DebugSession({
    required SocketClient client,
    required this.appTabId,
    required this.trigger,
    required void Function(String data) onIncoming,
    required void Function() onDone,
    required void Function(dynamic error) onError,
    required bool cancelOnError,
  }) : _socketClient = client {
    // Collect extension events and send them periodically to the server.
    _batchSubscription = _batchController.stream.listen((events) {
      _socketClient.sink.add(
        jsonEncode(['BatchedEvents', BatchedEvents(events: events).toJson()]),
      );
    });
    // Listen for incoming events:
    _socketClient.stream.listen(
      onIncoming,
      onDone: onDone,
      onError: onError,
      cancelOnError: cancelOnError,
    );
  }

  set socketClient(SocketClient client) {
    _socketClient = client;

    // Collect extension events and send them periodically to the server.
    _batchSubscription = _batchController.stream.listen((events) {
      _socketClient.sink.add(
        jsonEncode(['BatchedEvents', BatchedEvents(events: events).toJson()]),
      );
    });
  }

  void sendEvent<T>(T event) {
    try {
      _socketClient.sink.add(jsonEncode(_serialize(event)));
    } catch (error) {
      debugError('Error sending event $event: $error');
    }
  }

  Object? _serialize(Object? event) {
    return switch (event) {
      ExtensionEvent() || DevToolsRequest() => event,
      _ => throw UnsupportedError('Unknown event type: $event'),
    };
  }

  void sendBatchedEvent(ExtensionEvent event) {
    try {
      _batchController.sink.add(event);
    } catch (error) {
      debugError('Error sending batched event $event: $error');
    }
  }

  void close() {
    try {
      _socketClient.close();
    } catch (error) {
      debugError('Error closing socket client: $error');
    }
    try {
      _batchSubscription.cancel();
    } catch (error) {
      debugError('Error canceling batch subscription: $error');
    }
    try {
      _batchController.close();
    } catch (error) {
      debugError('Error closing batch controller: $error');
    }
  }
}

String? _authUrl(String? extensionUrl) {
  if (extensionUrl == null) return null;
  final authUrl = Uri.parse(extensionUrl).replace(path: authenticationPath);
  return switch (authUrl.scheme) {
    'ws' => authUrl.replace(scheme: 'http').toString(),
    'wss' => authUrl.replace(scheme: 'https').toString(),
    _ => authUrl.toString(),
  };
}

@JS()
@anonymous
class _EvalResponse {
  external _EvalResult get result;
}

@JS()
@anonymous
class _EvalResult {
  external List<String?>? get value;
}

@JS()
@anonymous
class _InjectedParams {
  external String get expresion;
  external bool get returnByValue;
  external int get contextId;
  external factory _InjectedParams({
    String? expression,
    bool? returnByValue,
    int? contextId,
  });
}
