class AssignAction implements Runnable {

  @Override public void run() {
    List<String> assignType = assignActionConfig.assignType;

    if (assignType == null || assignType.isEmpty()) {
      throw new IllegalArgumentException("Must specify a single type to assign.");
    }

    if (assignActionConfig.name == null || !validName(assignActionConfig.name) ||
        assignActionConfig.group == null || !validName(assignActionConfig.group)) {
      throw new IllegalArgumentException(format("Invalid name, must match %s", VALID_NAME_PATTERN));
    }
    Group group;
    try {
      group = keywhizClient.getGroupByName(assignActionConfig.group);
    } catch (KeywhizClient.NotFoundException e) {
      throw new AssertionError("Group doesn't exist.");
    } catch (IOException e) {
      throw Throwables.propagate(e);
    }

    String type = assignType.get(0).toLowerCase().trim();
    switch (type) {
      case "client":
        Client client = null;
        boolean createClient = false;
        try {
          client = keywhizClient.getClientByName(assignActionConfig.name);
        } catch (KeywhizClient.NotFoundException e) {
          logger.info("Creating client '{}'.", assignActionConfig.name);
          createClient = true;
        } catch (IOException e) {
          throw Throwables.propagate(e);
        }

        if (createClient) {
          try {
            keywhizClient.createClient(assignActionConfig.name, "", "");
            client = keywhizClient.getClientByName(assignActionConfig.name);
          } catch (IOException e) {
            throw Throwables.propagate(e);
          }
        }

        try {
          if (keywhizClient.groupDetailsForId(group.getId()).getClients().contains(client)) {
            throw new AssertionError(
                format("Client '%s' already assigned to group '%s'", assignActionConfig.name,
                    group.getName()));
          }
          logger.info("Enrolling client '{}' in group '{}'.", client.getName(), group.getName());
          keywhizClient.enrollClientInGroupByIds(client.getId(), group.getId());
        } catch (IOException e) {
          throw Throwables.propagate(e);
        }
        break;

      case "secret":

        try {
          long groupId = group.getId();
          SanitizedSecret sanitizedSecret =
                keywhizClient.getSanitizedSecretByName(assignActionConfig.name);
          if (keywhizClient.groupDetailsForId(groupId).getSecrets().contains(sanitizedSecret)) {
            throw new AssertionError(
                format("Secret '%s' already assigned to group '%s'", assignActionConfig.name,
                    group.getName()));
          }
          logger.info("Allowing group '{}' access to secret '{}'.", group.getName(), sanitizedSecret.name());
          keywhizClient.grantSecretToGroupByIds(sanitizedSecret.id(), groupId);
        } catch (KeywhizClient.NotFoundException e) {
          throw new AssertionError("Secret doesn't exist.");
        } catch (IOException e) {
          throw Throwables.propagate(e);
        }
        break;

      default:
        throw new IllegalArgumentException("Invalid assign type specified: " + type);
    }
  }

  public  AssignAction(AssignActionConfig assignActionConfig, KeywhizClient client);

}