// 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:html';

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 'debug_session.dart';
import 'logger.dart';
import 'messaging.dart';
import 'storage.dart';
import 'utils.dart';

bool _connecting = false;
String _backgroundColor = _darkColor;
bool _isDartApp = true;

const _bugLinkId = 'bugLink';
const _darkColor = '202125';
const _darkThemeClass = 'dark-theme';
const _hiddenClass = 'hidden';
const _iframeContainerId = 'iframeContainer';
const _landingPageId = 'landingPage';
const _launchDebugConnectionButtonId = 'launchDebugConnectionButton';
const _lightColor = 'ffffff';
const _lightThemeClass = 'light-theme';
const _loadingSpinnerId = 'loadingSpinner';
const _panelAttribute = 'data-panel';
const _panelBodyId = 'panelBody';
const _showClass = 'show';
const _warningBannerId = 'warningBanner';
const _warningMsgId = 'warningMsg';

const _noAppDetectedMsg = 'No app detected.';
const _lostConnectionMsg = 'Lost connection.';
const _connectionTimeoutMsg = 'Connection timed out.';
const _failedToConnectMsg = 'Failed to connect, please try again.';
const _pleaseAuthenticateMsg = 'Please re-authenticate and try again.';
const _multipleAppsMsg = 'Cannot debug multiple apps in a page.';

int get _tabId => chrome.devtools.inspectedWindow.tabId;

Future<void> main() async {
  unawaited(
    _registerListeners().catchError((Object? error) {
      debugWarn('Error registering listeners in panel: $error');
    }),
  );
  _setColorThemeToMatchChromeDevTools();
  await _maybeUpdateFileABugLink();
  final multipleApps = await fetchStorageObject<String>(
    type: StorageObject.multipleAppsDetected,
    tabId: _tabId,
  );
  _maybeShowMultipleAppsWarning(multipleApps);
}

Future<void> _registerListeners() async {
  chrome.storage.onChanged.addListener(allowInterop(_handleStorageChanges));
  chrome.runtime.onMessage.addListener(allowInterop(_handleRuntimeMessages));
  final launchDebugConnectionButton =
      document.getElementById(_launchDebugConnectionButtonId) as ButtonElement;
  launchDebugConnectionButton.addEventListener('click', _launchDebugConnection);

  await _maybeInjectDevToolsIframe();
}

void _handleRuntimeMessages(
  dynamic jsRequest,
  // ignore: avoid-unused-parameters
  MessageSender sender,
  // ignore: avoid-unused-parameters
  Function sendResponse,
) {
  if (jsRequest is! String) return;

  interceptMessage<DebugStateChange>(
    message: jsRequest,
    expectedType: MessageType.debugStateChange,
    expectedSender: Script.background,
    expectedRecipient: Script.debuggerPanel,
    sender: sender,
    messageHandler: (DebugStateChange debugStateChange) async {
      if (debugStateChange.tabId != _tabId) {
        debugWarn(
          'Received debug state change request, but '
          'Dart app tab does not match current tab.',
        );
        return;
      }
      if (debugStateChange.newState == DebugStateChange.stopDebugging) {
        _handleDebugConnectionLost(debugStateChange.reason);
      }
    },
  );

  interceptMessage<ConnectFailure>(
    message: jsRequest,
    expectedType: MessageType.connectFailure,
    expectedSender: Script.background,
    expectedRecipient: Script.debuggerPanel,
    sender: sender,
    messageHandler: (ConnectFailure connectFailure) async {
      debugLog(
        'Received connect failure for ${connectFailure.tabId} vs $_tabId',
      );
      if (connectFailure.tabId != _tabId) {
        return;
      }
      _connecting = false;
      _handleConnectFailure(
        ConnectFailureReason.fromString(connectFailure.reason ?? 'unknown'),
      );
    },
  );
}

void _handleStorageChanges(Object storageObj, String _) {
  interceptStorageChange<DebugInfo>(
    storageObj: storageObj,
    expectedType: StorageObject.debugInfo,
    tabId: _tabId,
    changeHandler: _handleDebugInfoChanges,
  );
  interceptStorageChange<String>(
    storageObj: storageObj,
    expectedType: StorageObject.devToolsUri,
    tabId: _tabId,
    changeHandler: _handleDevToolsUriChanges,
  );
  interceptStorageChange<String>(
    storageObj: storageObj,
    expectedType: StorageObject.multipleAppsDetected,
    tabId: _tabId,
    changeHandler: _maybeShowMultipleAppsWarning,
  );
}

void _handleDebugInfoChanges(DebugInfo? debugInfo) {
  if (debugInfo == null && _isDartApp) {
    _isDartApp = false;
    if (!_warningBannerIsVisible()) {
      _showWarningBanner(_noAppDetectedMsg);
    }
  }
  if (debugInfo != null && !_isDartApp) {
    _isDartApp = true;
    if (_warningBannerIsVisible()) {
      _hideWarningBanner();
    }
  }
}

void _handleDevToolsUriChanges(String? devToolsUri) {
  if (devToolsUri != null) {
    _injectDevToolsIframe(devToolsUri);
  }
}

void _maybeShowMultipleAppsWarning(String? multipleApps) {
  if (multipleApps != null) {
    _showWarningBanner(_multipleAppsMsg);
  } else {
    if (_warningBannerIsVisible(message: _multipleAppsMsg)) {
      _hideWarningBanner();
    }
  }
}

Future<void> _maybeUpdateFileABugLink() async {
  final debugInfo = await fetchStorageObject<DebugInfo>(
    type: StorageObject.debugInfo,
    tabId: _tabId,
  );
  final isInternal = debugInfo?.isInternalBuild ?? false;
  if (isInternal) {
    final bugLink = document.getElementById(_bugLinkId);
    if (bugLink == null) return;
    bugLink.setAttribute('href', 'http://go/dde-bug');
  }
}

void _setColorThemeToMatchChromeDevTools() {
  final chromeTheme = chrome.devtools.panels.themeName;
  final panelBody = document.getElementById(_panelBodyId);
  if (chromeTheme == 'dark') {
    _backgroundColor = _darkColor;
    _updateColorThemeForElement(panelBody, isDarkTheme: true);
  } else {
    _backgroundColor = _lightColor;
    _updateColorThemeForElement(panelBody, isDarkTheme: false);
  }
}

void _updateColorThemeForElement(
  Element? element, {
  required bool isDarkTheme,
}) {
  if (element == null) return;
  final classToRemove = isDarkTheme ? _lightThemeClass : _darkThemeClass;
  if (element.classes.contains(classToRemove)) {
    element.classes.remove(classToRemove);
    final classToAdd = isDarkTheme ? _darkThemeClass : _lightThemeClass;
    element.classes.add(classToAdd);
  }
}

void _handleDebugConnectionLost(String? reason) {
  final detachReason = DetachReason.fromString(reason ?? 'unknown');
  _removeDevToolsIframe();
  _updateElementVisibility(_landingPageId, visible: true);
  switch (detachReason) {
    case DetachReason.canceledByUser:
      return;
    case DetachReason.staleDebugSession:
    case DetachReason.navigatedAwayFromApp:
      _showWarningBanner(_noAppDetectedMsg);
    default:
      _showWarningBanner(_lostConnectionMsg);
  }
}

void _handleConnectFailure(ConnectFailureReason reason) {
  switch (reason) {
    case ConnectFailureReason.authentication:
      _showWarningBanner(_pleaseAuthenticateMsg);
    case ConnectFailureReason.noDartApp:
      _showWarningBanner(_noAppDetectedMsg);
    case ConnectFailureReason.timeout:
      _showWarningBanner(_connectionTimeoutMsg);
    default:
      _showWarningBanner(_failedToConnectMsg);
  }
  _updateElementVisibility(_launchDebugConnectionButtonId, visible: true);
  _updateElementVisibility(_loadingSpinnerId, visible: false);
}

bool _warningBannerIsVisible({String? message}) {
  final warningBanner = document.getElementById(_warningBannerId);
  final isVisible =
      warningBanner != null && warningBanner.classes.contains(_showClass);
  if (message == null || !isVisible) return isVisible;
  final warningMsg = document.getElementById(_warningMsgId);
  return warningMsg?.innerHtml == message;
}

void _showWarningBanner(String message) {
  final warningMsg = document.getElementById(_warningMsgId);
  warningMsg?.setInnerHtml(message);
  final warningBanner = document.getElementById(_warningBannerId);
  warningBanner?.classes.add(_showClass);
}

void _hideWarningBanner() {
  final warningBanner = document.getElementById(_warningBannerId);
  warningBanner?.classes.remove(_showClass);
}

Future<void> _launchDebugConnection(Event _) async {
  _updateElementVisibility(_launchDebugConnectionButtonId, visible: false);
  _updateElementVisibility(_loadingSpinnerId, visible: true);
  final json = jsonEncode([
    'DebugStateChange',
    DebugStateChange(
      tabId: _tabId,
      newState: DebugStateChange.startDebugging,
    ).toJson(),
  ]);
  await sendRuntimeMessage(
    type: MessageType.debugStateChange,
    body: json,
    sender: Script.debuggerPanel,
    recipient: Script.background,
  );
  unawaited(_maybeHandleConnectionTimeout().catchError((_) {}));
}

Future<void> _maybeHandleConnectionTimeout() async {
  _connecting = true;
  await Future<void>.delayed(const Duration(seconds: 10));
  if (_connecting) {
    _handleConnectFailure(ConnectFailureReason.timeout);
  }
}

Future<void> _maybeInjectDevToolsIframe() async {
  final devToolsUri = await fetchStorageObject<String>(
    type: StorageObject.devToolsUri,
    tabId: _tabId,
  );
  if (devToolsUri == null) return;
  if (isActiveDebugSession(_tabId)) {
    debugWarn('Unexpected state. Stale DevTools URI.');
    await clearStaleDebugSession(_tabId);
    _updateElementVisibility(_landingPageId, visible: true);
  } else {
    _injectDevToolsIframe(devToolsUri);
  }
}

void _injectDevToolsIframe(String devToolsUri) {
  _connecting = false;
  final iframeContainer = document.getElementById(_iframeContainerId);
  if (iframeContainer == null) return;
  final panelBody = document.getElementById(_panelBodyId);
  final panelType = panelBody?.getAttribute(_panelAttribute) ?? 'debugger';
  final iframe = document.createElement('iframe');
  final iframeSrc = addQueryParameters(
    devToolsUri,
    queryParameters: {
      'ide': 'ChromeDevTools',
      'embed': 'true',
      'page': panelType,
      'backgroundColor': _backgroundColor,
    },
  );
  iframe.setAttribute('src', iframeSrc);
  _hideWarningBanner();
  _updateElementVisibility(_landingPageId, visible: false);
  _updateElementVisibility(_loadingSpinnerId, visible: false);
  _updateElementVisibility(_launchDebugConnectionButtonId, visible: true);
  iframeContainer.append(iframe);
}

void _removeDevToolsIframe() {
  final iframeContainer = document.getElementById(_iframeContainerId);
  final iframe = iframeContainer?.firstChild;
  if (iframe == null) return;
  iframe.remove();
}

void _updateElementVisibility(String elementId, {required bool visible}) {
  final element = document.getElementById(elementId);
  if (element == null) return;
  if (visible) {
    element.classes.remove(_hiddenClass);
  } else {
    element.classes.add(_hiddenClass);
  }
}
