// Copyright (c) 2020, 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 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;

import 'client.dart';
import 'constants.dart';
import 'dds_impl.dart';
import 'named_lookup.dart';
import 'stream_manager.dart';

/// [_ClientResumePermissions] associates a list of
/// [DartDevelopmentServiceClient]s, all of the same client name, with a
/// permissions mask used to determine which pause event types require approval
/// from one of the listed clients before resuming an isolate.
class ClientResumePermissions {
  final List<DartDevelopmentServiceClient> clients = [];
  int permissionsMask = 0;
}

/// The [ClientManager] has the responsibility of managing all state and
/// requests related to client connections, including:
///   - A list of all currently connected clients
///   - Tracking client names and associated permissions for isolate resume
///     synchronization
///   - Handling RPC invocations which change client state
class ClientManager {
  ClientManager(this.dds);

  /// Initialize state for a newly connected client.
  void addClient(DartDevelopmentServiceClient client) {
    _setClientNameHelper(
      client,
      client.defaultClientName,
    );
    clients.add(client);
    client.listen().then((_) => removeClient(client));
    if (clients.length == 1) {
      dds.isolateManager.initialize().then((_) {
        dds.streamManager.streamListen(
          null,
          StreamManager.kDebugStream,
        );
      });
    }
  }

  /// Cleanup state for a disconnected client.
  void removeClient(DartDevelopmentServiceClient client) {
    _clearClientName(client);
    clients.remove(client);
    if (clients.isEmpty) {
      dds.streamManager.streamCancel(
        null,
        StreamManager.kDebugStream,
      );
    }
  }

  /// Cleanup clients on DDS shutdown.
  Future<void> shutdown() async {
    // Close all incoming websocket connections.
    final futures = <Future>[];
    // Copy `clients` to guard against modification while iterating.
    for (final client in clients.toList()) {
      futures.add(client.close());
    }
    await Future.wait(futures);
  }

  /// Associates a name with a given client.
  ///
  /// The provided client name is used to track isolate resume approvals.
  Map<String, dynamic> setClientName(
    DartDevelopmentServiceClient client,
    json_rpc.Parameters parameters,
  ) {
    _setClientNameHelper(client, parameters['name'].asString);
    return RPCResponses.success;
  }

  /// Require permission from this client before resuming an isolate.
  Future<Map<String, dynamic>> requirePermissionToResume(
    DartDevelopmentServiceClient client,
    json_rpc.Parameters parameters,
  ) async {
    int pauseTypeMask = 0;
    if (parameters['onPauseStart'].asBoolOr(false)) {
      pauseTypeMask |= PauseTypeMasks.pauseOnStartMask;
    }
    if (parameters['onPauseReload'].asBoolOr(false)) {
      pauseTypeMask |= PauseTypeMasks.pauseOnReloadMask;
    }
    if (parameters['onPauseExit'].asBoolOr(false)) {
      pauseTypeMask |= PauseTypeMasks.pauseOnExitMask;
    }
    clientResumePermissions[client.name!]!.permissionsMask = pauseTypeMask;

    // Check to see if any isolates should resume as a result of the
    // resume permissions being updated.
    await dds.isolateManager.maybeResumeIsolates();

    return RPCResponses.success;
  }

  /// Changes `client`'s name to `name` while also updating resume permissions
  /// and approvals.
  void _setClientNameHelper(
    DartDevelopmentServiceClient client,
    String name,
  ) {
    _clearClientName(client);
    client.name = name.isEmpty ? client.defaultClientName : name;
    clientResumePermissions.putIfAbsent(
      client.name!,
      () => ClientResumePermissions(),
    );
    clientResumePermissions[client.name!]!.clients.add(client);
  }

  /// Resets the client's name while also cleaning up resume permissions and
  /// approvals.
  void _clearClientName(
    DartDevelopmentServiceClient client,
  ) {
    final name = client.name;
    client.name = null;
    final clientsForName = clientResumePermissions[name];
    if (clientsForName != null) {
      clientsForName.clients.remove(client);
      // If this was the last client with a given name, cleanup resume
      // permissions.
      if (clientsForName.clients.isEmpty) {
        clientResumePermissions.remove(name);

        // Check to see if we need to resume any isolates now that the last
        // client of a given name has disconnected or changed names.
        //
        // An isolate will be resumed in this situation if:
        //
        // 1) This client required resume approvals for the current pause event
        // associated with the isolate and all other required resume approvals
        // have been provided by other clients.
        //
        // OR
        //
        // 2) This client required resume approvals for the current pause event
        // associated with the isolate, no other clients require resume approvals
        // for the current pause event, and at least one client has issued a resume
        // request.
        dds.isolateManager.isolates.forEach(
          (_, isolate) async =>
              await isolate.maybeResumeAfterClientChange(name),
        );
      }
    }
  }

  DartDevelopmentServiceClient? findFirstClientThatHandlesService(
      String service) {
    for (final client in clients) {
      if (client.services.containsKey(service)) {
        return client;
      }
    }
    return null;
  }

  // Handles namespace generation for service extensions.
  static const _kServicePrologue = 's';
  final NamedLookup<DartDevelopmentServiceClient> clients = NamedLookup(
    prologue: _kServicePrologue,
  );

  /// Mapping of client names to all clients of that name and their resume
  /// permissions.
  final Map<String?, ClientResumePermissions> clientResumePermissions = {};

  final DartDevelopmentServiceImpl dds;
}
