// 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';
// TODO: https://github.com/dart-lang/webdev/issues/2508
// ignore: deprecated_member_use
import 'dart:js_util';

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

import 'chrome_api.dart';
import 'logger.dart';
import 'utils.dart';

// A default response for the sendResponse callback.
//
// Prevents the message port from closing. See:
// https://developer.chrome.com/docs/extensions/mv3/messaging/#simple
final defaultResponse = jsify({'response': 'received'});

enum Script {
  background,
  copier,
  debuggerPanel,
  detector,
  popup;

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

enum MessageType {
  isAuthenticated,
  connectFailure,
  appId,
  debugInfo,
  debugStateChange,
  devToolsUrl,
  multipleAppsDetected;

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

class Message {
  final Script to;
  final Script from;
  final MessageType type;
  final String body;
  final String? error;

  Message({
    required this.to,
    required this.from,
    required this.type,
    required this.body,
    this.error,
  });

  factory Message.fromJSON(String json) {
    final decoded = jsonDecode(json) as Map<String, dynamic>;

    return Message(
      to: Script.fromString(decoded['to'] as String),
      from: Script.fromString(decoded['from'] as String),
      type: MessageType.fromString(decoded['type'] as String),
      body: decoded['body'] as String,
      error: decoded['error'] as String?,
    );
  }

  String toJSON() {
    return jsonEncode({
      'to': to.name,
      'from': from.name,
      'type': type.name,
      'body': body,
      if (error != null) 'error': error,
    });
  }
}

void interceptMessage<T>({
  required String? message,
  required MessageType expectedType,
  required Script expectedSender,
  required Script expectedRecipient,
  required MessageSender sender,
  required void Function(T message) messageHandler,
}) {
  if (message == null) return;
  if (!_isLegitimateSender(sender)) return;

  try {
    final decodedMessage = Message.fromJSON(message);
    if (decodedMessage.type != expectedType ||
        decodedMessage.to != expectedRecipient ||
        decodedMessage.from != expectedSender) {
      return;
    }
    if (T == String) {
      messageHandler(decodedMessage.body as T);
    } else {
      messageHandler(_deserialize<T>(decodedMessage.body));
    }
  } catch (error) {
    debugError(
      'Error intercepting $expectedType from '
      '$expectedSender to $expectedRecipient: $error',
    );
  }
}

T _deserialize<T>(String body) {
  final decoded = jsonDecode(body);
  return switch (decoded) {
    ['ConnectFailure', ...] => ConnectFailure.fromJson(decoded) as T,
    ['DebugStateChange', ...] => DebugStateChange.fromJson(decoded) as T,
    ['DevToolsOpener', ...] => DevToolsOpener.fromJson(decoded) as T,
    ['DevToolsUrl', ...] => DevToolsUrl.fromJson(decoded) as T,
    ['DebugInfo', ...] => DebugInfo.fromJson(decoded) as T,
    _ => throw UnsupportedError('Unknown type for deserialization: $T'),
  };
}

/// Send a message using the chrome.runtime.sendMessage API.
Future<bool> sendRuntimeMessage({
  required MessageType type,
  required String body,
  required Script sender,
  required Script recipient,
}) =>
    _sendMessage(type: type, body: body, sender: sender, recipient: recipient);

/// Send a message using the chrome.tabs.sendMessage API.
Future<bool> sendTabsMessage({
  required int tabId,
  required MessageType type,
  required String body,
  required Script sender,
  required Script recipient,
}) => _sendMessage(
  tabId: tabId,
  type: type,
  body: body,
  sender: sender,
  recipient: recipient,
);

Future<bool> _sendMessage({
  required MessageType type,
  required String body,
  required Script sender,
  required Script recipient,
  int? tabId,
}) {
  final message = Message(
    to: recipient,
    from: sender,
    type: type,
    body: body,
  ).toJSON();
  final completer = Completer<bool>();
  void responseHandler([dynamic _]) {
    final error = chrome.runtime.lastError;
    if (error != null) {
      debugError(
        'Error sending $type to $recipient from $sender: ${error.message}',
      );
    }
    completer.complete(error != null);
  }

  if (tabId != null) {
    chrome.tabs.sendMessage(
      tabId,
      message,
      // options
      null,
      allowInterop(responseHandler),
    );
  } else {
    chrome.runtime.sendMessage(
      // id
      null,
      message,
      // options
      null,
      allowInterop(responseHandler),
    );
  }
  return completer.future;
}

// Verify the message sender is our extension.
bool _isLegitimateSender(MessageSender sender) {
  // Check that the sender ID matches our extension ID:
  if (sender.id != chrome.runtime.id) return false;

  final senderUri = Uri.parse(sender.origin ?? '');
  final senderHost = senderUri.host;
  final isDartAppHost =
      senderHost == 'localhost' ||
      senderHost == '127.0.0.1' ||
      _isGoogleHost(senderHost);
  final isExtensionOrigin =
      senderHost == chrome.runtime.id && senderUri.scheme == 'chrome-extension';

  if (isDartAppHost || isExtensionOrigin) return true;

  // If the sender's host is unexpected, display an error.
  displayNotification(
    'Unexpected sender ${sender.origin}. Please file a bug at go/dde-bug or https://github.com/dart-lang/webdev',
    isError: true,
  );
  return false;
}

bool _isGoogleHost(String host) {
  const googleSuffices = ['.googlers.com', '.google.com', '.googleprod.com'];
  return googleSuffices.any((suffix) => host.endsWith(suffix));
}
