// 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/data/serializers.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_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;

  /// 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 message = serializers.deserialize(jsonDecode(data));
        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 (var 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(
        serializers.serialize(
          ExtensionEvent(
            (b) => b
              ..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(
          serializers.serialize(
            ExtensionRequest(
              (b) => b
                ..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';
      default:
        throw ArgumentError('unknown state: $state');
    }
  }

  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;
  }
}
