/**
   * Change the package's status to DRAFT.
   *
   * @param packageId
   * @throws EslException
   */
  public void changePackageStatusToDraft(PackageId packageId) throws EslException {
    String path =
        template
            .urlFor(UrlTemplate.PACKAGE_ID_PATH)
            .replace("{packageId}", packageId.getId())
            .build();

    try {
      client.put(path, "{\"status\":\"DRAFT\"}");
    } catch (RequestException e) {
      throw new EslServerException("Could not change the package status to DRAFT.", e);
    } catch (Exception e) {
      throw new EslException("Could not change the package status to DRAFT.", e);
    }
  }
  /**
   * Updates a role from the package.
   *
   * @param packageId
   * @param role
   * @return The updated role
   * @throws EslException
   */
  public Role updateRole(PackageId packageId, Role role) throws EslException {
    String path =
        template
            .urlFor(UrlTemplate.ROLE_ID_PATH)
            .replace("{packageId}", packageId.getId())
            .replace("{roleId}", role.getId())
            .build();

    String roleJson = JacksonUtil.serializeDirty(role);
    String stringResponse;
    try {
      stringResponse = client.put(path, roleJson);
    } catch (RequestException e) {
      throw new EslServerException("Could not update role", e);
    } catch (Exception e) {
      throw new EslException("Could not update role", e);
    }
    return Serialization.fromJson(stringResponse, Role.class);
  }
  /**
   * Updates a signer's information from a package
   *
   * @param packageId The id of the package containing the signer to be updated
   * @param signer The signer with the updated information
   */
  public void updateSigner(PackageId packageId, com.silanis.esl.sdk.Signer signer) {
    Role apiPayload =
        new SignerConverter(signer).toAPIRole(UUID.randomUUID().toString().replace("-", ""));

    String path =
        template
            .urlFor(UrlTemplate.SIGNER_PATH)
            .replace("{packageId}", packageId.getId())
            .replace("{roleId}", signer.getId())
            .build();

    try {
      String json = Serialization.toJson(apiPayload);
      client.put(path, json);
    } catch (RequestException e) {
      throw new EslException("Could not update signer.", e);
    } catch (Exception e) {
      throw new EslException("Could not update signer." + " Exception: " + e.getMessage());
    }
  }
  /**
   * Updates the documents signing order
   *
   * @param documentPackage
   */
  public void orderDocuments(DocumentPackage documentPackage) {
    String path =
        template
            .urlFor(UrlTemplate.DOCUMENT_PATH)
            .replace("{packageId}", documentPackage.getId().getId())
            .build();

    List<Document> documents = new ArrayList<Document>();
    for (com.silanis.esl.sdk.Document document : documentPackage.getDocuments()) {
      documents.add(new DocumentConverter(document).toAPIDocumentMetadata());
    }
    try {
      String json = Serialization.toJson(documents);

      client.put(path, json);
    } catch (RequestException e) {
      throw new EslServerException("Could not order the documents.", e);
    } catch (Exception e) {
      throw new EslException("Could not order the documents." + " Exception: " + e.getMessage());
    }
  }
  /**
   * Updates the signer order in a package.
   *
   * @param documentPackage The id of the package to update signer order
   */
  public void orderSigners(DocumentPackage documentPackage) {
    String path =
        template
            .urlFor(UrlTemplate.ROLE_PATH)
            .replace("{packageId}", documentPackage.getId().getId())
            .build();

    List<Role> roles = new ArrayList<Role>();
    for (com.silanis.esl.sdk.Signer signer : documentPackage.getSigners()) {
      roles.add(new SignerConverter(signer).toAPIRole(signer.getId()));
    }

    try {
      String json = Serialization.toJson(roles);
      client.put(path, json);
    } catch (RequestException e) {
      throw new EslServerException("Could not order signers.", e);
    } catch (Exception e) {
      throw new EslException("Could not order signers." + " Exception: " + e.getMessage());
    }
  }
  /**
   * Updates the document's metadata from the package.
   *
   * @param documentPackage
   * @param document
   */
  public void updateDocumentMetadata(
      DocumentPackage documentPackage, com.silanis.esl.sdk.Document document) {
    String path =
        template
            .urlFor(UrlTemplate.DOCUMENT_ID_PATH)
            .replace("{packageId}", documentPackage.getId().getId())
            .replace("{documentId}", document.getId().toString())
            .build();

    Document internalDoc = new DocumentConverter(document).toAPIDocumentMetadata();

    try {
      String json = Serialization.toJson(internalDoc);

      client.put(path, json);
    } catch (RequestException e) {
      throw new EslServerException("Could not update the document's metadata.", e);
    } catch (Exception e) {
      throw new EslException(
          "Could not update the document's metadata." + " Exception: " + e.getMessage());
    }
  }
  /**
   * Updates the package's fields and roles.
   *
   * @param packageId
   * @param sdkPackage
   * @throws EslException
   */
  public void updatePackage(PackageId packageId, DocumentPackage sdkPackage) throws EslException {
    String path =
        template
            .urlFor(UrlTemplate.PACKAGE_ID_PATH)
            .replace("{packageId}", packageId.getId())
            .build();

    Package aPackage = new DocumentPackageConverter(sdkPackage).toAPIPackage();

    String packageJson = Serialization.toJson(aPackage);
    try {
      client.put(path, packageJson);
    } catch (RequestException e) {
      throw new EslServerException("Could not update the package.", e);
    } catch (Exception e) {
      throw new EslException("Could not update the package.", e);
    }
    // Update roles
    List<Role> roleList = aPackage.getRoles();
    for (Role role : roleList) {
      updateRole(packageId, role);
    }
  }