// Copyright (c) 2019, 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:collection';
import 'dart:convert';

import 'package:dwds/data/devtools_request.dart';
import 'package:dwds/data/extension_request.dart';
import 'package:dwds/src/debugging/execution_context.dart';
import 'package:dwds/src/debugging/remote_debugger.dart';
import 'package:dwds/src/handlers/socket_connections.dart';
import 'package:dwds/src/services/chrome/chrome_debug_exception.dart';
import 'package:logging/logging.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
    hide StackTrace;

final _logger = Logger('ExtensionDebugger');

/// A remote debugger backed by the Dart Debug Extension with an SSE connection.
class ExtensionDebugger implements RemoteDebugger {
  /// A connection between the debugger and the background of
  /// Dart Debug Extension
  final SocketConnection sseConnection;

  /// A map from id to a completer associated with an [ExtensionRequest]
  final _completers = <int, Completer>{};
  final _eventStreams = <String, Stream>{};
  var _completerId = 0;

  @override
  Future<void> Function()? onReconnect;

  /// Null until [close] is called.
  ///
  /// All subsequent calls to [close] will return this future.
  Future<void>? _closed;

  String? instanceId;
  ExecutionContext? _executionContext;

  ExecutionContext? get executionContext => _executionContext;

  final _devToolsRequestController = StreamController<DevToolsRequest>();

  Stream<DevToolsRequest> get devToolsRequestStream =>
      _devToolsRequestController.stream;

  final _notificationController = StreamController<WipEvent>.broadcast();

  Stream<WipEvent> get onNotification => _notificationController.stream;

  final _closeController = StreamController<Object>.broadcast();

  @override
  Stream<Object> get onClose => _closeController.stream;

  @override
  Stream<ConsoleAPIEvent> get onConsoleAPICalled => eventStream(
    'Runtime.consoleAPICalled',
    (WipEvent event) => ConsoleAPIEvent(event.json),
  );

  @override
  Stream<ExceptionThrownEvent> get onExceptionThrown => eventStream(
    'Runtime.exceptionThrown',
    (WipEvent event) => ExceptionThrownEvent(event.json),
  );

  final _scripts = <String, WipScript>{};
  final _scriptIds = <String, String>{};

  ExtensionDebugger(this.sseConnection) {
    sseConnection.stream.listen(
      (data) {
        final decoded = jsonDecode(data);
        final message = _deserialize(decoded);
        if (message is ExtensionResponse) {
          final encodedResult = {
            'result': json.decode(message.result),
            'id': message.id,
          };
          final completer = _completers[message.id];
          if (completer == null) {
            throw StateError('Missing completer.');
          }
          // TODO(#988): Call completeError(WipError()) to match the behavior of
          // package:webkit_inspection_protocol.
          completer.complete(WipResponse(encodedResult));
        } else if (message is ExtensionEvent) {
          final map = {
            'method': json.decode(message.method),
            'params': json.decode(message.params),
          };
          // 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
          if (map['method'] == 'DebugExtension.detached') {
            close();
          } else {
            _notificationController.sink.add(WipEvent(map));
          }
        } else if (message is BatchedEvents) {
          for (final event in message.events) {
            final map = {
              'method': json.decode(event.method),
              'params': json.decode(event.params),
            };
            _notificationController.sink.add(WipEvent(map));
          }
        } else if (message is DevToolsRequest) {
          instanceId = message.instanceId;
          _executionContext = RemoteDebuggerExecutionContext(
            message.contextId,
            this,
          );
          _devToolsRequestController.sink.add(message);
        }
      },
      onError: (_) {
        close();
      },
      onDone: close,
    );
    onScriptParsed.listen((event) {
      // Remove stale scripts from cache.
      if (event.script.url.isNotEmpty &&
          _scriptIds.containsKey(event.script.url)) {
        _scripts.remove(_scriptIds[event.script.url]);
      }
      _scripts[event.script.scriptId] = event.script;
      _scriptIds[event.script.url] = event.script.scriptId;
    });
    // Listens for a page reload.
    onGlobalObjectCleared.listen((_) {
      _scripts.clear();
    });
  }

  void sendEvent(String method, String params) {
    sseConnection.sink.add(
      jsonEncode(ExtensionEvent(method: method, params: params)),
    );
  }

  /// Sends a [command] with optional [params] to Dart Debug Extension
  /// over the SSE connection.
  @override
  Future<WipResponse> sendCommand(
    String command, {
    Map<String, dynamic>? params,
  }) {
    final completer = Completer<WipResponse>();
    final id = newId();
    _completers[id] = completer;
    try {
      sseConnection.sink.add(
        jsonEncode(
          ExtensionRequest(
            id: id,
            command: command,
            commandParams: jsonEncode(params ?? {}),
          ),
        ),
      );
    } on StateError catch (error, stackTrace) {
      if (error.message.contains('Cannot add event after closing')) {
        _logger.severe('Socket connection closed. Shutting down debugger.');
        closeWithError(error);
      } else {
        _logger.severe('Bad state while sending $command.', error, stackTrace);
      }
    } catch (error, stackTrace) {
      _logger.severe(
        'Unknown error while sending $command.',
        error,
        stackTrace,
      );
    }
    return completer.future;
  }

  int newId() => _completerId++;

  @override
  Future<void> close() => _closed ??= () {
    _closeController.add({});
    return Future.wait([
      sseConnection.sink.close(),
      _notificationController.close(),
      _devToolsRequestController.close(),
      _closeController.close(),
    ]);
  }();

  void closeWithError(Object? error) {
    _logger.shout(
      'Closing extension debugger due to error. Restart app for debugging functionality',
      error,
    );
    close();
  }

  @override
  Future disable() => sendCommand('Debugger.disable');

  @override
  Future enable() => sendCommand('Debugger.enable');

  @override
  Future<String> getScriptSource(String scriptId) async =>
      (await sendCommand(
            'Debugger.getScriptSource',
            params: {'scriptId': scriptId},
          )).result!['scriptSource']
          as String;

  @override
  Future<WipResponse> pause() => sendCommand('Debugger.pause');

  @override
  Future<WipResponse> resume() => sendCommand('Debugger.resume');

  @override
  Future<WipResponse> setPauseOnExceptions(PauseState state) => sendCommand(
    'Debugger.setPauseOnExceptions',
    params: {'state': _pauseStateToString(state)},
  );

  @override
  Future<WipResponse> removeBreakpoint(String breakpointId) {
    return sendCommand(
      'Debugger.removeBreakpoint',
      params: {'breakpointId': breakpointId},
    );
  }

  @override
  Future<WipResponse> stepInto({Map<String, dynamic>? params}) =>
      sendCommand('Debugger.stepInto', params: params);

  @override
  Future<WipResponse> stepOut() => sendCommand('Debugger.stepOut');

  @override
  Future<WipResponse> stepOver({Map<String, dynamic>? params}) =>
      sendCommand('Debugger.stepOver', params: params);

  @override
  Future<WipResponse> enablePage() => sendCommand('Page.enable');

  @override
  Future<WipResponse> pageReload() => sendCommand('Page.reload');

  @override
  Future<RemoteObject> evaluate(
    String expression, {
    bool? returnByValue,
    int? contextId,
  }) async {
    final params = <String, dynamic>{'expression': expression};
    if (returnByValue != null) {
      params['returnByValue'] = returnByValue;
    }
    if (returnByValue != null) {
      params['contextId'] = contextId;
    }
    final response = await sendCommand('Runtime.evaluate', params: params);
    final result = _validateResult(response.result);
    return RemoteObject(result['result'] as Map<String, dynamic>);
  }

  @override
  Future<RemoteObject> evaluateOnCallFrame(
    String callFrameId,
    String expression,
  ) async {
    final params = <String, dynamic>{
      'callFrameId': callFrameId,
      'expression': expression,
    };
    final response = await sendCommand(
      'Debugger.evaluateOnCallFrame',
      params: params,
    );
    final result = _validateResult(response.result);
    return RemoteObject(result['result'] as Map<String, dynamic>);
  }

  @override
  Future<List<WipBreakLocation>> getPossibleBreakpoints(
    WipLocation start,
  ) async {
    final params = <String, dynamic>{'start': start.toJsonMap()};
    final response = await sendCommand(
      'Debugger.getPossibleBreakpoints',
      params: params,
    );
    final result = _validateResult(response.result);
    final locations = result['locations'] as List;
    return List.from(
      locations.map((map) => WipBreakLocation(map as Map<String, dynamic>)),
    );
  }

  @override
  Stream<T> eventStream<T>(String method, WipEventTransformer<T> transformer) {
    return _eventStreams
        .putIfAbsent(
          method,
          () => onNotification
              .where((event) => event.method == method)
              .map(transformer),
        )
        .cast();
  }

  @override
  Stream<GlobalObjectClearedEvent> get onGlobalObjectCleared => eventStream(
    'Debugger.globalObjectCleared',
    (WipEvent event) => GlobalObjectClearedEvent(event.json),
  );

  @override
  Stream<DebuggerPausedEvent> get onPaused => eventStream(
    'Debugger.paused',
    (WipEvent event) => DebuggerPausedEvent(event.json),
  );

  @override
  Stream<DebuggerResumedEvent> get onResumed => eventStream(
    'Debugger.resumed',
    (WipEvent event) => DebuggerResumedEvent(event.json),
  );

  @override
  Stream<ScriptParsedEvent> get onScriptParsed => eventStream(
    'Debugger.scriptParsed',
    (WipEvent event) => ScriptParsedEvent(event.json),
  );

  @override
  Stream<TargetCrashedEvent> get onTargetCrashed => eventStream(
    'Inspector.targetCrashed',
    (WipEvent event) => TargetCrashedEvent(event.json),
  );

  @override
  Map<String, WipScript> get scripts => UnmodifiableMapView(_scripts);

  String _pauseStateToString(PauseState state) {
    switch (state) {
      case PauseState.all:
        return 'all';
      case PauseState.none:
        return 'none';
      case PauseState.uncaught:
        return 'uncaught';
    }
  }

  Map<String, dynamic> _validateResult(Map<String, dynamic>? result) {
    if (result == null) {
      throw ChromeDebugException({'text': 'null result from Chrome Devtools'});
    }
    if (result.containsKey('exceptionDetails')) {
      throw ChromeDebugException(
        result['exceptionDetails'] as Map<String, dynamic>,
      );
    }
    return result;
  }

  static Object? _deserialize(dynamic decoded) {
    if (decoded case ['ExtensionResponse', ...]) {
      return ExtensionResponse.fromJson(decoded);
    }
    if (decoded case ['ExtensionEvent', ...]) {
      return ExtensionEvent.fromJson(decoded);
    }
    if (decoded case ['BatchedEvents', ...]) {
      return BatchedEvents.fromJson(decoded);
    }
    if (decoded case ['DevToolsRequest', ...]) {
      return DevToolsRequest.fromJson(decoded);
    }
    return null;
  }
}
