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

class RunningIsolate implements MessageRouter {
  final int portId;
  final SendPort sendPort;
  final String name;
  final Set<String> _resumeApprovalsByName = {};

  RunningIsolate(this.portId, this.sendPort, this.name);

  String get serviceId => 'isolates/$portId';

  static const kInvalidPauseEvent = -1;
  static const kPauseOnStartMask = 1 << 0;
  static const kPauseOnReloadMask = 1 << 1;
  static const kPauseOnExitMask = 1 << 2;
  static const kDefaultResumePermissionMask =
      kPauseOnStartMask | kPauseOnReloadMask | kPauseOnExitMask;

  /// Resumes the isolate if all clients which need to approve a resume have
  /// done so. Called when the last client of a given name disconnects or
  /// changes name to ensure we don't deadlock waiting for approval to resume
  /// from a disconnected client.
  Future<void> maybeResumeAfterClientChange(
      VMService service, String disconnectedClientName) async {
    // Remove approvals from the disconnected client.
    _resumeApprovalsByName.remove(disconnectedClientName);

    // If we've received approval to resume from all clients who care, clear
    // approval state and resume.
    final pauseType = await _isolatePauseType(service, portId.toString());
    if (pauseType != kInvalidPauseEvent &&
        _shouldResume(service, null, pauseType)) {
      _resumeApprovalsByName.clear();
      await Message.forMethod('resume')
        ..params.addAll({
          'isolateId': portId,
        })
        ..sendToIsolate(sendPort);
    }
  }

  bool _shouldResume(VMService service, Client? client, int pauseType) {
    if (client != null) {
      // Mark the approval by the client.
      _resumeApprovalsByName.add(client.name);
    }
    final requiredClientApprovals = <String>{};
    final permissions = service.clientResumePermissions;

    // Determine which clients require approval for this pause type.
    permissions.forEach((name, clientNamePermissions) {
      if (clientNamePermissions.permissionsMask & pauseType != 0) {
        requiredClientApprovals.add(name);
      }
    });

    // We require at least a single client to resume, even if that client
    // doesn't require resume approval.
    if (_resumeApprovalsByName.isEmpty) {
      return false;
    }

    // If all the required approvals are present, we should resume.
    return _resumeApprovalsByName.containsAll(requiredClientApprovals);
  }

  Future<int> _isolatePauseType(VMService service, String isolateId) async {
    final getIsolateMessage = Message.forMethod('getIsolate')
      ..params.addAll({
        'isolateId': isolateId,
      });
    final result =
        (await routeRequest(service, getIsolateMessage)).decodeJson();
    final pauseEvent = result['result']['pauseEvent'];
    const pauseEvents = <String, int>{
      'PauseStart': kPauseOnStartMask,
      'PausePostRequest': kPauseOnReloadMask,
      'PauseExit': kPauseOnExitMask,
    };
    final kind = pauseEvent['kind'];
    return pauseEvents[kind] ?? kInvalidPauseEvent;
  }

  Future<Response> _routeResumeRequest(
      VMService service, Message message) async {
    // If we've received approval to resume from all clients who care, clear
    // approval state and resume.
    final pauseType =
        await _isolatePauseType(service, message.params['isolateId']);
    if (pauseType == kInvalidPauseEvent ||
        _shouldResume(service, message.client, pauseType)) {
      _resumeApprovalsByName.clear();
      return message.sendToIsolate(sendPort);
    }

    // We're still awaiting some approvals. Simply return success, but don't
    // resume yet.
    return Response(ResponsePayloadKind.String, encodeSuccess(message));
  }

  @override
  Future<Response> routeRequest(VMService service, Message message) {
    if (message.method == 'resume') {
      return _routeResumeRequest(service, message);
    }
    // Send message to isolate.
    return message.sendToIsolate(sendPort);
  }

  @override
  void routeResponse(Message message) {}
}
