// Copyright (c) 2013, 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.

part of dart._vmservice;

final class _CompileExpressionErrorDetails {
  final String details;

  _CompileExpressionErrorDetails(this.details);
}

class RunningIsolates implements MessageRouter {
  final isolates = <int, RunningIsolate>{};
  int? _rootPortId;

  RunningIsolates();

  void isolateStartup(int portId, SendPort sp, String name) {
    if (_rootPortId == null) {
      _rootPortId = portId;
    }
    var ri = RunningIsolate(portId, sp, name);
    isolates[portId] = ri;
  }

  void isolateShutdown(int portId, SendPort sp) {
    if (_rootPortId == portId) {
      _rootPortId = null;
    }
    (isolates.remove(portId))?.onIsolateExit();
  }

  @override
  Future<Response> routeRequest(VMService service, Message message) {
    String isolateParam = message.params['isolateId']! as String;
    int isolateId;
    if (!isolateParam.startsWith('isolates/')) {
      message.setErrorResponse(
        kInvalidParams,
        "invalid 'isolateId' parameter: $isolateParam",
      );
      return message.response;
    }
    isolateParam = isolateParam.substring('isolates/'.length);
    if (isolateParam == 'root') {
      isolateId = _rootPortId!;
    } else {
      try {
        isolateId = int.parse(isolateParam);
      } catch (e) {
        message.setErrorResponse(
          kInvalidParams,
          "invalid 'isolateId' parameter: $isolateParam",
        );
        return message.response;
      }
    }
    final isolate = isolates[isolateId];
    if (isolate == null) {
      // There is some chance that this isolate may have lived before,
      // so return a sentinel rather than an error.
      final result = <String, String>{
        'type': 'Sentinel',
        'kind': 'Collected',
        'valueAsString': '<collected>',
      };
      message.setResponse(encodeResult(message, result));
      return message.response;
    }

    if (message.method == 'evaluateInFrame' || message.method == 'evaluate') {
      return _Evaluator(message, isolate, service).run();
    } else {
      return isolate.routeRequest(service, message);
    }
  }

  @override
  void routeResponse(Message message) {}
}

// NOTE: The following class is a duplicate of one in
// 'package:frontend_server/resident_frontend_server_utils.dart'. We are forced
// to duplicate it because `dart:_vmservice` is not allowed to import
// `package:frontend_server`.

final class _ResidentCompilerInfo {
  /// The SDK hash that kernel files compiled using the Resident Frontend
  /// Compiler associated with this object will be stamped with.
  final String? sdkHash;

  /// The address that the Resident Frontend Compiler associated with this
  /// object is listening from.
  final InternetAddress address;

  /// The port number that the Resident Frontend Compiler associated with this
  /// object is listening on.
  final int port;

  /// Extracts the value associated with a key from [entries], where [entries]
  /// is a [String] with the format '$key1:$value1 $key2:$value2 $key3:$value3 ...'.
  static String _extractValueAssociatedWithKey(String entries, String key) =>
      RegExp(
        '$key:'
        r'(\S+)(\s|$)',
      ).allMatches(entries).first[1]!;

  static _ResidentCompilerInfo fromFile(File file) {
    final fileContents = file.readAsStringSync();

    return _ResidentCompilerInfo._(
      sdkHash:
          fileContents.contains('sdkHash:')
              ? _extractValueAssociatedWithKey(fileContents, 'sdkHash')
              : null,
      address: InternetAddress(
        _extractValueAssociatedWithKey(fileContents, 'address'),
      ),
      port: int.parse(_extractValueAssociatedWithKey(fileContents, 'port')),
    );
  }

  _ResidentCompilerInfo._({
    required this.sdkHash,
    required this.port,
    required this.address,
  });
}

/// Class that knows how to orchestrate expression evaluation in dart2 world.
class _Evaluator {
  static const _successString = 'success';
  static const _compileExpressionString = 'compileExpression';
  static const _isolateIdString = 'isolateId';
  static const _expressionString = 'expression';
  static const _definitionsString = 'definitions';
  static const _definitionTypesString = 'definitionTypes';
  static const _typeDefinitionsString = 'typeDefinitions';
  static const _typeBoundsString = 'typeBounds';
  static const _typeDefaultsString = 'typeDefaults';
  static const _libraryUriString = 'libraryUri';
  static const _tokenPosString = 'tokenPos';
  static const _isStaticString = 'isStatic';
  static const _scriptUriString = 'scriptUri';
  static const _methodString = 'method';
  static const _rootLibraryUriString = 'rootLibraryUri';

  _Evaluator(this._message, this._isolate, this._service);

  Future<Response> run() async {
    final buildScopeResponse = await _buildScope();
    final responseJson =
        buildScopeResponse.decodeJson() as Map<String, dynamic>;

    if (responseJson.containsKey('error')) {
      final error = responseJson['error'] as Map<String, dynamic>;
      final data = error['data'] as Map<String, dynamic>;
      return Response.from(
        encodeCompilationError(_message, data['details'] as String),
      );
    }

    String kernelBase64;
    try {
      kernelBase64 = await _compileExpression(
        responseJson['result'] as Map<String, dynamic>,
      );
    } on _CompileExpressionErrorDetails catch (e) {
      return Response.from(
        encodeRpcError(
          _message,
          kExpressionCompilationError,
          details: e.details,
        ),
      );
    }
    return await _evaluateCompiledExpression(kernelBase64);
  }

  Message _message;
  RunningIsolate _isolate;
  VMService _service;

  Future<Response> _buildScope() {
    final params = _setupParams();
    params['isolateId'] = _message.params['isolateId'];
    final buildScopeParams = <String, dynamic>{
      'method': '_buildExpressionEvaluationScope',
      'id': _message.serial,
      'params': params,
    };
    if (_message.params['scope'] != null) {
      (buildScopeParams['params'] as Map<String, dynamic>)['scope'] =
          _message.params['scope'];
    }
    final buildScope = Message._fromJsonRpcRequest(
      _message.client!,
      buildScopeParams,
    );

    // Decode the JSON and insert it into the map. The map key
    // is the request Uri.
    return _isolate.routeRequest(_service, buildScope);
  }

  /// If [response] represents a valid JSON-RPC result, then this function
  /// returns the 'kernelBytes' property of that result. Otherwise, this
  /// function throws a [_CompileExpressionErrorDetails] object wrapping the
  /// 'details' property of the JSON-RPC error.
  static String _getKernelBytesOrThrowErrorDetails(
    Map<String, dynamic> response,
  ) {
    if (response['result'] != null) {
      return (response['result'] as Map<String, dynamic>)['kernelBytes']
          as String;
    }
    final error = response['error'] as Map<String, dynamic>;
    final data = error['data'] as Map<String, dynamic>;
    throw _CompileExpressionErrorDetails(data['details']);
  }

  // NOTE: The following function is a duplicate of one in
  // 'package:frontend_server/resident_frontend_server_utils.dart'. We are
  // forced to duplicate it because `dart:_vmservice` is not allowed to import
  // `package:frontend_server`.

  /// Sends a compilation [request] to the resident frontend compiler associated
  /// with [serverInfoFile], and returns the compiler's JSON response.
  ///
  /// Throws a [FileSystemException] if [serverInfoFile] cannot be accessed.
  static Future<Map<String, dynamic>>
  _sendRequestToResidentFrontendCompilerAndRecieveResponse(
    String request,
    File serverInfoFile,
  ) async {
    Socket? client;
    Map<String, dynamic> jsonResponse;
    final residentCompilerInfo = _ResidentCompilerInfo.fromFile(serverInfoFile);

    try {
      client = await Socket.connect(
        residentCompilerInfo.address,
        residentCompilerInfo.port,
      );
      client.write(request);
      final data = String.fromCharCodes(await client.first);
      jsonResponse = jsonDecode(data);
    } catch (e) {
      jsonResponse = <String, dynamic>{
        _successString: false,
        'errorMessage': e.toString(),
      };
    }
    client?.destroy();
    return jsonResponse;
  }

  /// If compilation fails, this method will throw a
  /// [_CompileExpressionErrorDetails] object that will be used to populate the
  /// 'details' field of the response to the evaluation RPC that requested this
  /// compilation to happen.
  Future<String> _compileExpression(
    Map<String, dynamic> buildScopeResponseResult,
  ) async {
    Client? externalClient = _service._findFirstClientThatHandlesService(
      _compileExpressionString,
    );

    final compileParams = <String, dynamic>{
      _isolateIdString: _message.params[_isolateIdString]!,
      _expressionString: _message.params[_expressionString]!,
      _definitionsString: buildScopeResponseResult['param_names']!,
      _definitionTypesString: buildScopeResponseResult['param_types']!,
      _typeDefinitionsString: buildScopeResponseResult['type_params_names']!,
      _typeBoundsString: buildScopeResponseResult['type_params_bounds']!,
      _typeDefaultsString: buildScopeResponseResult['type_params_defaults']!,
      _libraryUriString: buildScopeResponseResult[_libraryUriString]!,
      _tokenPosString: buildScopeResponseResult[_tokenPosString]!,
      _isStaticString: buildScopeResponseResult[_isStaticString]!,
    };
    final klass = buildScopeResponseResult['klass'];
    if (klass != null) {
      compileParams['klass'] = klass;
    }
    final scriptUri = buildScopeResponseResult[_scriptUriString];
    if (scriptUri != null) {
      compileParams[_scriptUriString] = scriptUri;
    }
    final method = buildScopeResponseResult[_methodString];
    if (method != null) {
      compileParams[_methodString] = method;
    }
    if (externalClient != null) {
      // Let the external client handle expression compilation.
      final compileExpression = Message.forMethod(_compileExpressionString);
      compileExpression.client = externalClient;
      compileExpression.params.addAll(compileParams);

      final id = _service._serviceRequests.newId();
      final oldId = _message.serial;
      final completer = Completer<String>();
      externalClient.serviceHandles[id] = (Message? m) {
        if (m != null) {
          completer.complete(json.encode(m.forwardToJson({'id': oldId})));
        } else {
          completer.complete(encodeRpcError(_message, kServiceDisappeared));
        }
      };
      externalClient.post(
        Response.json(
          compileExpression.forwardToJson({
            'id': id,
            _methodString: _compileExpressionString,
          }),
        ),
      );
      return completer.future
          .then((s) => jsonDecode(s))
          .then(
            (json) => _getKernelBytesOrThrowErrorDetails(
              json as Map<String, dynamic>,
            ),
          );
    } else if (VMServiceEmbedderHooks.getResidentCompilerInfoFile!() != null) {
      // Compile the expression using the resident compiler.
      final response =
          await _sendRequestToResidentFrontendCompilerAndRecieveResponse(
            jsonEncode({
              'command': _compileExpressionString,
              _expressionString: compileParams[_expressionString],
              _definitionsString: compileParams[_definitionsString],
              _definitionTypesString: compileParams[_definitionTypesString],
              _typeDefinitionsString: compileParams[_typeDefinitionsString],
              _typeBoundsString: compileParams[_typeBoundsString],
              _typeDefaultsString: compileParams[_typeDefaultsString],
              _libraryUriString: compileParams[_libraryUriString],
              'offset': compileParams[_tokenPosString],
              _isStaticString: compileParams[_isStaticString],
              'class': compileParams['klass'],
              _scriptUriString: compileParams[_scriptUriString],
              _methodString: compileParams[_methodString],
              _rootLibraryUriString:
                  buildScopeResponseResult[_rootLibraryUriString],
            }),
            VMServiceEmbedderHooks.getResidentCompilerInfoFile!()!,
          );

      if (response[_successString] == true) {
        return response['kernelBytes'];
      } else if (response['errorMessage'] != null) {
        throw _CompileExpressionErrorDetails(response['errorMessage']);
      } else {
        final compilerOutputLines =
            (response['compilerOutputLines'] as List<dynamic>).cast<String>();
        throw _CompileExpressionErrorDetails(compilerOutputLines.join('\n'));
      }
    } else {
      // fallback to compile using kernel service
      final compileExpressionParams = <String, dynamic>{
        'method': '_compileExpression',
        'id': _message.serial,
        'params': compileParams,
      };
      final compileExpression = Message._fromJsonRpcRequest(
        _message.client!,
        compileExpressionParams,
      );

      return _isolate
          .routeRequest(_service, compileExpression)
          .then((response) => response.decodeJson())
          .then(
            (json) => _getKernelBytesOrThrowErrorDetails(
              json as Map<String, dynamic>,
            ),
          );
    }
  }

  Future<Response> _evaluateCompiledExpression(String kernelBase64) {
    if (kernelBase64.isNotEmpty) {
      final params = _setupParams();
      params['isolateId'] = _message.params['isolateId'];
      params['kernelBytes'] = kernelBase64;
      params['disableBreakpoints'] = _message.params['disableBreakpoints'];
      final runParams = <String, dynamic>{
        'method': '_evaluateCompiledExpression',
        'id': _message.serial,
        'params': params,
      };
      if (_message.params['scope'] != null) {
        (runParams['params'] as Map<String, dynamic>)['scope'] =
            _message.params['scope'];
      }
      if (_message.params['idZoneId'] != null) {
        (runParams['params'] as Map<String, dynamic>)['idZoneId'] =
            _message.params['idZoneId'];
      }
      final runExpression = Message._fromJsonRpcRequest(
        _message.client!,
        runParams,
      );
      return _isolate.routeRequest(_service, runExpression); // _message
    } else {
      // empty kernel indicates dart1 mode
      return _isolate.routeRequest(_service, _message);
    }
  }

  Map<String, dynamic> _setupParams() {
    if (_message.method == 'evaluateInFrame') {
      return <String, dynamic>{'frameIndex': _message.params['frameIndex']};
    } else {
      assert(_message.method == 'evaluate');
      return <String, dynamic>{'targetId': _message.params['targetId']};
    }
  }
}
