// 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:convert';
import 'dart:io';

import 'package:pedantic/pedantic.dart';
import 'package:pub_semver/pub_semver.dart' as semver;
import 'package:vm_service_lib/vm_service_lib.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

import 'debugger.dart';
import 'helpers.dart';
import 'inspector.dart';

/// A handler for application assets, e.g. Dart sources.
typedef AssetHandler = Future<String> Function(String);

/// Adds [event] to the stream with [streamId] if there is anybody listening
/// on that stream.
typedef StreamNotify = void Function(String streamId, Event event);

/// Returns the [AppInspector] for the current tab.
///
/// This may be null during a hot restart or page refresh.
typedef AppInspectorProvider = AppInspector Function();

/// A proxy from the chrome debug protocol to the dart vm service protocol.
class ChromeProxyService implements VmServiceInterface {
  /// Cache of all existing StreamControllers.
  ///
  /// These are all created through [onEvent].
  final _streamControllers = <String, StreamController<Event>>{};

  /// The root `VM` instance. There can only be one of these, but its isolates
  /// are dynamic and roughly map to chrome tabs.
  final VM _vm;

  /// The actual chrome tab running this app.
  final ChromeTab _tab;

  /// The connection with the chrome debug service for the tab.
  // TODO(grouma) - This should be class private.
  final WipConnection tabConnection;

  final AssetHandler _assetHandler;

  /// Provides debugger-related functionality.
  Debugger _debugger;

  AppInspector _inspector;
  AppInspector _appInspectorProvider() => _inspector;

  StreamSubscription<ConsoleAPIEvent> _consoleSubscription;

  ChromeProxyService._(
    this._vm,
    this._tab,
    this.tabConnection,
    this._assetHandler,
  );

  static Future<ChromeProxyService> create(ChromeConnection chromeConnection,
      AssetHandler assetHandler, String appInstanceId) async {
    ChromeTab appTab;
    for (var tab in await chromeConnection.getTabs()) {
      if (tab.url.startsWith('chrome-extensions:')) continue;
      var tabConnection = await tab.connect();
      var result = await tabConnection.runtime
          .evaluate(r'window["$dartAppInstanceId"];');
      if (result.value == appInstanceId) {
        appTab = tab;
        break;
      }
      unawaited(tabConnection.close());
    }
    if (appTab == null) {
      throw StateError('Could not connect to application with appInstanceId: '
          '$appInstanceId');
    }
    var tabConnection = await appTab.connect();
    await tabConnection.runtime.enable();

    // TODO: What about `architectureBits`, `targetCPU`, `hostCPU` and `pid`?
    final vm = VM()
      ..isolates = []
      ..name = 'ChromeDebugProxy'
      ..startTime = DateTime.now().millisecondsSinceEpoch
      ..version = Platform.version;
    var service = ChromeProxyService._(vm, appTab, tabConnection, assetHandler);
    await service._initialize();
    await service.createIsolate();
    return service;
  }

  Future<Null> _initialize() async {
    _debugger = await Debugger.create(
      _assetHandler,
      tabConnection,
      _streamNotify,
      _appInspectorProvider,
      uri,
    );
  }

  /// The root URI at which we're serving.
  String get uri => _tab.url;

  /// Creates a new isolate.
  ///
  /// Only one isolate at a time is supported, but they should be cleaned up
  /// with [destroyIsolate] and recreated with this method there is a hot
  /// restart or full page refresh.
  Future<void> createIsolate() async {
    if (_inspector?.isolate != null) {
      throw UnsupportedError(
          'Cannot create multiple isolates for the same app');
    }

    _inspector = await AppInspector.initialize(
      tabConnection,
      _assetHandler,
      _debugger,
      uri,
    );

    var isolateRef = _inspector.isolateRef;

    // Listen for `registerExtension` and `postEvent` calls.
    _setUpChromeConsoleListeners(isolateRef);

    _vm.isolates.add(isolateRef);

    _streamNotify(
        'Isolate',
        Event()
          ..kind = EventKind.kIsolateStart
          ..isolate = isolateRef);
    _streamNotify(
        'Isolate',
        Event()
          ..kind = EventKind.kIsolateRunnable
          ..isolate = isolateRef);

    // TODO: We shouldn't need to fire these events since they exist on the
    // isolate, but devtools doesn't recognize extensions after a page refresh
    // otherwise.
    for (var extensionRpc in _inspector.isolate.extensionRPCs) {
      _streamNotify(
          'Isolate',
          Event()
            ..kind = EventKind.kServiceExtensionAdded
            ..extensionRPC = extensionRpc
            ..isolate = isolateRef);
    }
  }

  /// Should be called when there is a hot restart or full page refresh.
  ///
  /// Clears out the [_inspector] and all related cached information.
  void destroyIsolate() {
    var isolate = _inspector?.isolate;
    if (isolate == null) return;
    _streamNotify(
        'Isolate',
        Event()
          ..kind = EventKind.kIsolateExit
          ..isolate = _inspector.isolateRef);
    _vm.isolates.removeWhere((ref) => ref.id == isolate.id);
    _inspector = null;
    _consoleSubscription.cancel();
    _consoleSubscription = null;
  }

  @override
  Future<Breakpoint> addBreakpoint(String isolateId, String scriptId, int line,
          {int column}) =>
      _debugger.addBreakpoint(isolateId, scriptId, line, column: column);

  @override
  Future<Breakpoint> addBreakpointAtEntry(String isolateId, String functionId) {
    throw UnimplementedError();
  }

  @override
  Future<Breakpoint> addBreakpointWithScriptUri(
      String isolateId, String scriptUri, int line,
      {int column}) {
    throw UnimplementedError();
  }

  @override
  Future<Response> callServiceExtension(String method,
      {String isolateId, Map args}) async {
    // Validate the isolate id is correct, _getIsolate throws if not.
    if (isolateId != null) _getIsolate(isolateId);
    args ??= <String, String>{};
    var stringArgs = args.map((k, v) => MapEntry(
        k is String ? k : jsonEncode(k), v is String ? v : jsonEncode(v)));
    var expression = '''
require("dart_sdk").developer.invokeExtension(
    "$method", JSON.stringify(${jsonEncode(stringArgs)}));
''';
    var response =
        await tabConnection.runtime.sendCommand('Runtime.evaluate', params: {
      'expression': expression,
      'awaitPromise': true,
    });
    handleErrorIfPresent(response, evalContents: expression);
    var decodedResponse =
        jsonDecode(response.result['result']['value'] as String)
            as Map<String, dynamic>;
    if (decodedResponse.containsKey('code') &&
        decodedResponse.containsKey('message') &&
        decodedResponse.containsKey('data')) {
      // ignore: only_throw_errors
      throw RPCError(method, decodedResponse['code'] as int,
          decodedResponse['message'] as String, decodedResponse['data'] as Map);
    } else {
      return Response()..json = decodedResponse;
    }
  }

  @override
  Future<Success> clearCpuProfile(String isolateId) {
    throw UnimplementedError();
  }

  @override
  Future<Success> clearVMTimeline() {
    throw UnimplementedError();
  }

  @override
  Future<Success> collectAllGarbage(String isolateId) {
    throw UnimplementedError();
  }

  @override
  Future evaluate(String isolateId, String targetId, String expression,
          {Map<String, String> scope, bool disableBreakpoints}) =>
      _inspector?.evaluate(isolateId, targetId, expression,
          scope: scope, disableBreakpoints: disableBreakpoints);

  @override
  Future evaluateInFrame(String isolateId, int frameIndex, String expression,
      {Map<String, String> scope, bool disableBreakpoints}) {
    throw UnimplementedError();
  }

  @override
  Future<AllocationProfile> getAllocationProfile(String isolateId,
      {bool gc, bool reset}) {
    throw UnimplementedError();
  }

  @override
  Future<CpuProfile> getCpuProfile(String isolateId, String tags) {
    throw UnimplementedError();
  }

  @override
  Future<FlagList> getFlagList() {
    throw UnimplementedError();
  }

  @override
  Future<InstanceSet> getInstances(
      String isolateId, String classId, int limit) {
    throw UnimplementedError();
  }

  /// Sync version of [getIsolate] for internal use, also has stronger typing
  /// than the public one which has to be dynamic.
  Isolate _getIsolate(String isolateId) {
    var isolate = _inspector?.isolate;
    if (isolate?.id == isolateId) return isolate;
    throw ArgumentError.value(
        isolateId, 'isolateId', 'Unrecognized isolate id');
  }

  @override
  Future<Isolate> getIsolate(String isolateId) async => _getIsolate(isolateId);

  @override
  Future<dynamic> getMemoryUsage(String isolateId) async {
    throw UnimplementedError();
  }

  @override
  Future getObject(String isolateId, String objectId,
          {int offset, int count}) =>
      _inspector?.getObject(isolateId, objectId, offset: offset, count: count);

  @override
  Future<ScriptList> getScripts(String isolateId) =>
      _inspector?.getScripts(isolateId);

  @override
  Future<SourceReport> getSourceReport(String isolateId, List<String> reports,
      {String scriptId, int tokenPos, int endTokenPos, bool forceCompile}) {
    throw UnimplementedError();
  }

  /// Returns the current stack.
  ///
  /// Returns null if the corresponding isolate is not paused.
  @override
  Future<Stack> getStack(String isolateId) => _debugger.getStack(isolateId);

  @override
  Future<VM> getVM() => Future.value(_vm);

  @override
  Future<Timeline> getVMTimeline({int timeOriginMicros, int timeExtentMicros}) {
    throw UnimplementedError();
  }

  @override
  Future<TimelineFlags> getVMTimelineFlags() {
    throw UnimplementedError();
  }

  @override
  Future<Version> getVersion() async {
    var version = semver.Version.parse(vmServiceVersion);
    return Version()
      ..major = version.major
      ..minor = version.minor;
  }

  @override
  Future invoke(String isolateId, String targetId, String selector,
      List<String> argumentIds,
      {bool disableBreakpoints}) {
    throw UnimplementedError();
  }

  @override
  Future<Success> kill(String isolateId) {
    throw UnimplementedError();
  }

  @override
  Stream<Event> onEvent(String streamId) {
    return _streamControllers.putIfAbsent(streamId, () {
      switch (streamId) {
        case 'Extension':
        // TODO: right now we only support the `ServiceExtensionAdded` event for
        // the Isolate stream.
        case 'Isolate':
        case 'VM':
        // TODO: https://github.com/dart-lang/webdev/issues/168
        case 'GC':
        // TODO: https://github.com/dart-lang/webdev/issues/168
        case 'Timeline':
        case '_Service':
          return StreamController<Event>.broadcast();
        case 'Debug':
          return StreamController<Event>.broadcast();
        case 'Stdout':
          return _chromeConsoleStreamController(
              (e) => _stdoutTypes.contains(e.type));
        case 'Stderr':
          return _chromeConsoleStreamController(
              (e) => _stderrTypes.contains(e.type),
              includeExceptions: true);
        default:
          throw UnimplementedError('The stream `$streamId` is not supported.');
      }
    }).stream;
  }

  @override
  Future<Success> pause(String isolateId) => _debugger.pause();

  @override
  Future<Success> registerService(String service, String alias) async {
    throw UnimplementedError();
  }

  @override
  Future<ReloadReport> reloadSources(String isolateId,
      {bool force, bool pause, String rootLibUri, String packagesUri}) async {
    throw UnimplementedError();
  }

  @override
  Future<Success> removeBreakpoint(String isolateId, String breakpointId) =>
      _debugger.removeBreakpoint(isolateId, breakpointId);

  @override
  Future<Success> requestHeapSnapshot(
      String isolateId, String roots, bool collectGarbage) {
    throw UnimplementedError();
  }

  @override
  Future<Success> resume(String isolateId,
          {String step, int frameIndex}) async =>
      _debugger.resume(isolateId, step: step, frameIndex: frameIndex);

  @override
  Future<Success> setExceptionPauseMode(String isolateId, String mode) =>
      _debugger.setExceptionPauseMode(isolateId, mode);

  @override
  Future<Success> setFlag(String name, String value) {
    throw UnimplementedError();
  }

  @override
  Future<Success> setLibraryDebuggable(
      String isolateId, String libraryId, bool isDebuggable) {
    throw UnimplementedError();
  }

  @override
  Future<Success> setName(String isolateId, String name) async {
    var isolate = _getIsolate(isolateId);
    isolate.name = name;
    return Success();
  }

  @override
  Future<Success> setVMName(String name) async {
    _vm.name = name;
    _streamNotify(
        'VM',
        Event()
          ..kind = EventKind.kVMUpdate
          ..vm = toVMRef(_vm));
    return Success();
  }

  @override
  Future<Success> setVMTimelineFlags(List<String> recordedStreams) {
    throw UnimplementedError();
  }

  @override
  Future<Success> streamCancel(String streamId) {
    throw UnimplementedError();
  }

  @override
  Future<Success> streamListen(String streamId) async {
    onEvent(streamId);
    return Success();
  }

  /// Returns a streamController that listens for console logs from chrome and
  /// adds all events passing [filter] to the stream.
  StreamController<Event> _chromeConsoleStreamController(
      bool Function(ConsoleAPIEvent) filter,
      {bool includeExceptions = false}) {
    StreamController<Event> controller;
    StreamSubscription chromeConsoleSubscription;
    StreamSubscription exceptionsSubscription;
    // This is an edge case for this lint apparently
    //
    // ignore: join_return_with_assignment
    controller = StreamController<Event>.broadcast(onCancel: () {
      chromeConsoleSubscription?.cancel();
      exceptionsSubscription?.cancel();
    }, onListen: () {
      chromeConsoleSubscription =
          tabConnection.runtime.onConsoleAPICalled.listen((e) {
        var isolate = _inspector?.isolate;
        if (isolate == null) return;
        if (!filter(e)) return;
        var args = e.params['args'] as List;
        var item = args[0] as Map;
        var value = '${item["value"]}\n';
        controller.add(Event()
          ..kind = EventKind.kWriteEvent
          ..isolate = _inspector.isolateRef
          ..bytes = base64.encode(utf8.encode(value))
          ..timestamp = e.timestamp.toInt());
      });
      if (includeExceptions) {
        exceptionsSubscription =
            tabConnection.runtime.onExceptionThrown.listen((e) {
          var isolate = _inspector?.isolate;
          if (isolate == null) return;
          controller.add(Event()
            ..kind = EventKind.kWriteEvent
            ..isolate = _inspector.isolateRef
            ..bytes = base64
                .encode(utf8.encode(e.exceptionDetails.exception.description)));
        });
      }
    });
    return controller;
  }

  /// Listens for chrome console events and handles the ones we care about.
  void _setUpChromeConsoleListeners(IsolateRef isolateRef) {
    _consoleSubscription = tabConnection.runtime.onConsoleAPICalled
        .listen((ConsoleAPIEvent event) {
      var isolate = _inspector?.isolate;
      if (isolate == null) return;
      if (event.type != 'debug') return;
      var firstArgValue = event.args[0].value as String;
      switch (firstArgValue) {
        case 'dart.developer.registerExtension':
          var service = event.args[1].value as String;
          isolate.extensionRPCs.add(service);
          _streamNotify(
              'Isolate',
              Event()
                ..kind = EventKind.kServiceExtensionAdded
                ..extensionRPC = service
                ..isolate = isolateRef);
          break;
        case 'dart.developer.postEvent':
          _streamNotify(
              'Extension',
              Event()
                ..kind = EventKind.kExtension
                ..extensionKind = event.args[1].value as String
                ..extensionData = ExtensionData.parse(
                    jsonDecode(event.args[2].value as String) as Map)
                ..isolate = isolateRef);
          break;
        case 'dart.developer.inspect':
          // All inspected objects should be real objects.
          if (event.args[1].type != 'object') break;

          var inspectee = InstanceRef()
            ..kind = InstanceKind.kPlainInstance
            ..id = event.args[1].objectId
            // TODO(jakemac): Create a real ClassRef, we need a way of looking
            // up the library for a given instance to create it though.
            // https://github.com/dart-lang/sdk/issues/36771.
            ..classRef = ClassRef();
          _streamNotify(
              'Debug',
              Event()
                ..kind = EventKind.kInspect
                ..inspectee = inspectee
                ..timestamp = event.timestamp.toInt()
                ..isolate = isolateRef);
          break;
        default:
          break;
      }
    });
  }

  void _streamNotify(String streamId, Event event) {
    var controller = _streamControllers[streamId];
    if (controller == null) return;
    controller.add(event);
  }
}

/// The `type`s of [ConsoleAPIEvent]s that are treated as `stderr` logs.
const _stderrTypes = ['error'];

/// The `type`s of [ConsoleAPIEvent]s that are treated as `stdout` logs.
const _stdoutTypes = ['log', 'info', 'warning'];

/// Throws an [ExceptionDetails] object if `exceptionDetails` is present on the
/// result.
void handleErrorIfPresent(WipResponse response,
    {String evalContents, Object additionalDetails}) {
  if (response.result.containsKey('exceptionDetails')) {
    throw ChromeDebugException(
        response.result['exceptionDetails'] as Map<String, dynamic>,
        evalContents: evalContents,
        additionalDetails: additionalDetails);
  }
}

class ChromeDebugException extends ExceptionDetails implements Exception {
  /// Optional, additional information about the exception.
  final Object additionalDetails;

  /// Optional, the exact contents of the eval that was attempted.
  final String evalContents;

  ChromeDebugException(Map<String, dynamic> exceptionDetails,
      {this.additionalDetails, this.evalContents})
      : super(exceptionDetails);

  @override
  String toString() {
    var description = StringBuffer()
      ..writeln('Unexpected error from chrome devtools:');
    if (text != null) {
      description.writeln('text: $text');
    }
    if (exception != null) {
      description.writeln('exception:');
      description.writeln('  description: ${exception.description}');
      description.writeln('  type: ${exception.type}');
      description.writeln('  value: ${exception.value}');
    }
    if (evalContents != null) {
      description.writeln('attempted JS eval: `$evalContents`');
    }
    if (additionalDetails != null) {
      description.writeln('additional details:\n  $additionalDetails');
    }
    return description.toString();
  }
}
