// 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 (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(
        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';
    }
  }

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