// Copyright (c) 2023, 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;

// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'package:js/js.dart';

import 'chrome_api.dart';
import 'debug_session.dart';
import 'logger.dart';
import 'storage.dart';
import 'web_api.dart';

// The only extension allowed to communicate with this extension is the
// AngularDart DevTools extension.
//
// This ID is used to send messages to AngularDart DevTools, while the
// externally_connectable field in the manifest.json allows AngularDart DevTools
// to send messages to this extension.
const _angularDartDevToolsId = 'nbkbficgbembimioedhceniahniffgpl';

// A set of events to forward to the AngularDart DevTools extension.
final _eventsForAngularDartDevTools = {
  'Overlay.inspectNodeRequested',
  'dwds.encodedUri',
};

Future<void> handleMessagesFromAngularDartDevTools(
  dynamic jsRequest,
  // ignore: avoid-unused-parameters
  MessageSender sender,
  Function sendResponse,
) async {
  if (jsRequest == null) return;
  final message = jsRequest as ExternalExtensionMessage;
  if (message.name == 'chrome.debugger.sendCommand') {
    _forwardCommandToChromeDebugger(message, sendResponse);
  } else if (message.name == 'dwds.encodedUri') {
    await _respondWithEncodedUri(message.tabId, sendResponse);
  } else if (message.name == 'dwds.startDebugging') {
    await attachDebugger(message.tabId, trigger: Trigger.angularDartDevTools);
    sendResponse(true);
  } else {
    sendResponse(
      ErrorResponse()..error = 'Unknown message name: ${message.name}',
    );
  }
}

void maybeForwardMessageToAngularDartDevTools({
  required String method,
  required dynamic params,
  required int tabId,
}) {
  if (!_eventsForAngularDartDevTools.contains(method)) return;

  final message =
      method.startsWith('dwds')
          ? _dwdsEventMessage(method: method, params: params, tabId: tabId)
          : _debugEventMessage(method: method, params: params, tabId: tabId);

  _forwardMessageToAngularDartDevTools(message);
}

void _forwardCommandToChromeDebugger(
  ExternalExtensionMessage message,
  Function sendResponse,
) {
  try {
    final options = message.options as SendCommandOptions;
    chrome.debugger.sendCommand(
      Debuggee(tabId: message.tabId),
      options.method,
      options.commandParams,
      allowInterop(
        ([result]) => _respondWithChromeResult(result, sendResponse),
      ),
    );
  } catch (e) {
    sendResponse(ErrorResponse()..error = '$e');
  }
}

void _respondWithChromeResult(Object? chromeResult, Function sendResponse) {
  // No result indicates that an error occurred.
  if (chromeResult == null) {
    sendResponse(
      ErrorResponse()
        ..error = JSON.stringify(chrome.runtime.lastError ?? 'Unknown error.'),
    );
  } else {
    sendResponse(chromeResult);
  }
}

Future<void> _respondWithEncodedUri(int tabId, Function sendResponse) async {
  final encodedUri = await fetchStorageObject<String>(
    type: StorageObject.encodedUri,
    tabId: tabId,
  );
  sendResponse(encodedUri ?? '');
}

void _forwardMessageToAngularDartDevTools(ExternalExtensionMessage message) {
  chrome.runtime.sendMessage(
    _angularDartDevToolsId,
    message,
    // options
    null,
    allowInterop(([result]) => _checkForErrors(result, message.name)),
  );
}

void _checkForErrors(Object? chromeResult, String messageName) {
  // No result indicates that an error occurred.
  if (chromeResult == null) {
    final errorMessage = chrome.runtime.lastError?.message ?? 'Unknown error.';
    debugWarn('Error forwarding $messageName: $errorMessage');
  }
}

ExternalExtensionMessage _debugEventMessage({
  required String method,
  required dynamic params,
  required int tabId,
}) => ExternalExtensionMessage(
  name: 'chrome.debugger.event',
  tabId: tabId,
  options: DebugEvent(method: method, params: params),
);

ExternalExtensionMessage _dwdsEventMessage({
  required String method,
  required dynamic params,
  required int tabId,
}) => ExternalExtensionMessage(name: method, tabId: tabId, options: params);

// This message is used for cross-extension communication between this extension
// and the AngularDart DevTools extension.
@JS()
@anonymous
class ExternalExtensionMessage {
  external int get tabId;
  external String get name;
  external dynamic get options;
  external factory ExternalExtensionMessage({
    required int tabId,
    required String name,
    required dynamic options,
  });
}

@JS()
@anonymous
class DebugEvent {
  external factory DebugEvent({String method, Object? params});
}

@JS()
@anonymous
class SendCommandOptions {
  external String get method;
  external Object get commandParams;
}

@JS()
@anonymous
class ErrorResponse {
  external set error(String error);
}
