// 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 'package:dwds/asset_reader.dart';
import 'package:dwds/src/debugging/execution_context.dart';
import 'package:dwds/src/debugging/inspector.dart';
import 'package:dwds/src/debugging/instance.dart';
import 'package:dwds/src/debugging/metadata/provider.dart';
import 'package:dwds/src/debugging/modules.dart';
import 'package:dwds/src/debugging/remote_debugger.dart';
import 'package:dwds/src/debugging/webkit_debugger.dart';
import 'package:dwds/src/handlers/socket_connections.dart';
import 'package:dwds/src/loaders/require.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/services/expression_compiler.dart';
import 'package:dwds/src/utilities/objects.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:vm_service/vm_service.dart';

/// A library of fake/stub implementations of our classes and their supporting
/// classes (e.g. WipConnection) for unit testing.
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

import 'debugger_data.dart';
import 'utilities.dart';

/// Constructs a trivial Isolate we can use when we need to provide one but
/// don't want go through initialization.
Isolate get simpleIsolate => Isolate(
      id: '1',
      number: '1',
      name: 'fake',
      libraries: [],
      exceptionPauseMode: 'abc',
      breakpoints: [],
      pauseOnExit: false,
      pauseEvent: null,
      startTime: 0,
      livePorts: 0,
      runnable: false,
      isSystemIsolate: false,
      isolateFlags: [],
    );

class FakeInspector implements AppInspector {
  final WebkitDebugger _remoteDebugger;
  FakeInspector(this._remoteDebugger, {required this.fakeIsolate});

  Isolate fakeIsolate;

  @override
  Object noSuchMethod(Invocation invocation) {
    throw UnsupportedError('This is a fake');
  }

  @override
  Future<RemoteObject> callFunction(
    String function,
    Iterable<String> argumentIds,
  ) async =>
      RemoteObject({'type': 'string', 'value': 'true'});

  @override
  Future<void> initialize() async => {};

  @override
  Future<InstanceRef?> instanceRefFor(Object value) async =>
      InstanceHelper.kNullInstanceRef;

  @override
  Future<Obj> getObject(String objectId, {int? offset, int? count}) async =>
      Obj.parse({})!;

  @override
  Future<ScriptList> getScripts() async => ScriptList(scripts: []);

  @override
  Future<ScriptRef> scriptRefFor(String uri) async =>
      ScriptRef(id: 'fake', uri: 'fake://uri');

  @override
  ScriptRef? scriptWithId(String? scriptId) => null;

  @override
  Isolate get isolate => fakeIsolate;

  @override
  IsolateRef get isolateRef => IsolateRef(
        id: fakeIsolate.id,
        number: fakeIsolate.number,
        name: fakeIsolate.name,
        isSystemIsolate: fakeIsolate.isSystemIsolate,
      );

  @override
  Future<List<Property>> getProperties(
    String objectId, {
    int? offset,
    int? count,
    int? length,
  }) async {
    final response = await _remoteDebugger.sendCommand(
      'Runtime.getProperties',
      params: {
        'objectId': objectId,
        'ownProperties': true,
      },
    );
    final result = response.result?['result'];
    return result
        .map<Property>((each) => Property(each as Map<String, dynamic>))
        .toList();
  }

  @override
  bool isDisplayableObject(Object? object) => true;

  @override
  bool isNativeJsError(InstanceRef instanceRef) => false;
}

class FakeSseConnection implements SseSocketConnection {
  /// A [StreamController] for incoming messages on SSE connection.
  final controllerIncoming = StreamController<String>();

  /// A [StreamController] for outgoing messages on SSE connection.
  final controllerOutgoing = StreamController<String>();

  @override
  bool get isInKeepAlivePeriod => false;

  @override
  StreamSink<String> get sink => controllerOutgoing.sink;

  @override
  Stream<String> get stream => controllerIncoming.stream;

  @override
  void shutdown() {}
}

class FakeModules implements Modules {
  final String _library;
  final String _module;
  final String _path;

  FakeModules({
    String library = 'main.dart',
    String module = 'main',
    String path = 'web/main.dart',
  })  : _library = library,
        _module = module,
        _path = path;

  @override
  void initialize(String entrypoint) {}

  @override
  Future<Uri> libraryForSource(String serverPath) async => Uri(path: _library);

  @override
  Future<String> moduleForSource(String serverPath) async => _module;

  @override
  Future<Map<String, String>> modules() async => {_module: _path};

  @override
  Future<String> moduleForLibrary(String libraryUri) async => _module;
}

class FakeWebkitDebugger implements WebkitDebugger {
  final Map<String, WipScript>? _scripts;
  @override
  Future disable() async => null;

  @override
  Future enable() async => null;

  FakeWebkitDebugger({Map<String, WipScript>? scripts}) : _scripts = scripts {
    final buildSettings = TestBuildSettings.dart(
      appEntrypoint: Uri.parse('package:fakeapp/main.dart'),
    );
    setGlobalsForTesting(
      toolConfiguration: TestToolConfiguration.withLoadStrategy(
        loadStrategy: RequireStrategy(
          ReloadConfiguration.none,
          (_) async => {},
          (_) async => {},
          (_, __) async => null,
          (MetadataProvider _, String __) async => '',
          (MetadataProvider _, String __) async => '',
          (String _) => '',
          (MetadataProvider _) async => <String, ModuleInfo>{},
          FakeAssetReader(),
          buildSettings,
        ),
      ),
    );
  }

  @override
  Stream<T> eventStream<T>(String method, WipEventTransformer<T> transformer) =>
      Stream.empty();

  @override
  Future<String> getScriptSource(String scriptId) async => '';

  Stream<WipDomain>? get onClosed => null;

  @override
  Stream<GlobalObjectClearedEvent> get onGlobalObjectCleared => Stream.empty();

  @override
  late Stream<DebuggerPausedEvent> onPaused;

  @override
  Stream<DebuggerResumedEvent> get onResumed => Stream.empty();

  @override
  Stream<ScriptParsedEvent> get onScriptParsed => Stream.empty();

  @override
  Stream<TargetCrashedEvent> get onTargetCrashed => Stream.empty();

  @override
  Future<WipResponse> pause() async => fakeWipResponse;

  @override
  Future<WipResponse> resume() async => fakeWipResponse;

  @override
  Map<String, WipScript> get scripts => _scripts!;

  List<WipResponse> results = variables1;
  int resultsReturned = 0;

  @override
  Future<WipResponse> sendCommand(
    String command, {
    Map<String, dynamic>? params,
  }) async {
    // Force the results that we expect for looking up the variables.
    if (command == 'Runtime.getProperties') {
      return results[resultsReturned++];
    }
    return fakeWipResponse;
  }

  @override
  Future<WipResponse> setPauseOnExceptions(PauseState state) async =>
      fakeWipResponse;

  @override
  Future<WipResponse> removeBreakpoint(String breakpointId) async =>
      fakeWipResponse;

  @override
  Future<WipResponse> stepInto({Map<String, dynamic>? params}) async =>
      fakeWipResponse;

  @override
  Future<WipResponse> stepOut() async => fakeWipResponse;

  @override
  Future<WipResponse> stepOver({Map<String, dynamic>? params}) async =>
      fakeWipResponse;

  @override
  Stream<ConsoleAPIEvent> get onConsoleAPICalled => Stream.empty();

  @override
  Stream<ExceptionThrownEvent> get onExceptionThrown => Stream.empty();

  @override
  Future<void> close() async {}

  @override
  Stream<WipConnection> get onClose => Stream.empty();

  @override
  Future<RemoteObject> evaluate(
    String expression, {
    bool? returnByValue,
    int? contextId,
  }) async =>
      RemoteObject({});

  @override
  Future<RemoteObject> evaluateOnCallFrame(
    String callFrameId,
    String expression,
  ) async {
    return RemoteObject(<String, dynamic>{});
  }

  @override
  Future<List<WipBreakLocation>> getPossibleBreakpoints(
    WipLocation start,
  ) async =>
      [];

  @override
  Future<WipResponse> enablePage() async => fakeWipResponse;

  @override
  Future<WipResponse> pageReload() async => fakeWipResponse;
}

/// Fake execution context that is needed for id only
class FakeExecutionContext extends ExecutionContext {
  @override
  Future<int> get id async {
    return 0;
  }

  FakeExecutionContext();
}

class FakeStrategy extends LoadStrategy {
  final BuildSettings _buildSettings;

  FakeStrategy(
    super.assetReader, {
    super.packageConfigPath,
    BuildSettings? buildSettings,
  }) : _buildSettings = buildSettings ??
            TestBuildSettings.dart(
              appEntrypoint: Uri.parse('package:myapp/main.dart'),
            );

  @override
  Future<String> bootstrapFor(String entrypoint) async => 'dummy_bootstrap';

  @override
  shelf.Handler get handler =>
      (request) => (request.url.path == 'someDummyPath')
          ? shelf.Response.ok('some dummy response')
          : shelf.Response.notFound('someDummyPath');

  @override
  BuildSettings get buildSettings => _buildSettings;

  @override
  String get id => 'dummy-id';

  @override
  String get moduleFormat => 'dummy-format';

  @override
  String get loadLibrariesModule => '';

  @override
  String get loadModuleSnippet => '';

  @override
  String? g3RelativePath(String absolutePath) => null;

  @override
  ReloadConfiguration get reloadConfiguration => ReloadConfiguration.none;

  @override
  String loadClientSnippet(String clientScript) => 'dummy-load-client-snippet';

  @override
  Future<String?> moduleForServerPath(
    String entrypoint,
    String serverPath,
  ) async =>
      '';

  @override
  Future<String> serverPathForModule(String entrypoint, String module) async =>
      '';

  @override
  Future<String> sourceMapPathForModule(
    String entrypoint,
    String module,
  ) async =>
      '';

  @override
  String? serverPathForAppUri(String appUri) => '';

  @override
  MetadataProvider metadataProviderFor(String entrypoint) =>
      MetadataProvider(entrypoint, FakeAssetReader());

  @override
  Future<Map<String, ModuleInfo>> moduleInfoForEntrypoint(String entrypoint) =>
      throw UnimplementedError();
}

class FakeAssetReader implements AssetReader {
  final String? _metadata;
  final String? _dartSource;
  final String? _sourceMap;
  const FakeAssetReader({
    metadata,
    dartSource,
    sourceMap,
  })  : _metadata = metadata,
        _dartSource = dartSource,
        _sourceMap = sourceMap;

  @override
  String get basePath => '';

  @override
  Future<String> dartSourceContents(String serverPath) {
    return _throwUnimplementedOrReturnContents(_dartSource);
  }

  @override
  Future<String> metadataContents(String serverPath) {
    return _throwUnimplementedOrReturnContents(_metadata);
  }

  @override
  Future<String> sourceMapContents(String serverPath) {
    return _throwUnimplementedOrReturnContents(_sourceMap);
  }

  @override
  Future<void> close() async {}

  Future<String> _throwUnimplementedOrReturnContents(String? contents) async {
    if (contents == null) throw UnimplementedError();
    return contents;
  }
}

class FakeExpressionCompiler implements ExpressionCompiler {
  @override
  Future<ExpressionCompilationResult> compileExpressionToJs(
    String isolateId,
    String libraryUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  ) async =>
      ExpressionCompilationResult(expression, false);

  @override
  Future<bool> updateDependencies(Map<String, ModuleInfo> modules) async =>
      true;

  @override
  Future<void> initialize(CompilerOptions options) async {}
}

final fakeWipResponse = WipResponse({
  'id': 1,
  'result': {'fake': ''},
});
