/**
   * Return the parent directory of a directory
   *
   * @param u The owner
   * @param path The directory path
   * @param name The directory name
   * @return The parent directory, or null if not found
   */
  public static Directory getDirectoryParent(User u, Directory d) {

    if (d.name == null) return null; // Root doesn't have a parent

    if (d.getPathList().size() > 0) {
      return getDirectory(
          u,
          d.getPathList().subList(0, d.getPathList().size() - 1),
          d.getPathList().get(d.getPathList().size() - 1));
    } else {
      return new Directory(); // Root directory
    }
  }
  /**
   * Move a directory
   *
   * @param u
   * @param d
   * @param newContainer
   * @return
   */
  public static Directory moveDirectory(User u, Directory d, Directory newContainer) {

    if (d.UID == null) return d;

    MongoCollection<Document> collection = DataBase.getInstance().getCollection("directories");
    MongoCollection<Document> collectionFiles = DataBase.getInstance().getCollection("files.files");
    Date now = new Date();

    // Change path
    BasicDBObject query = new BasicDBObject();
    query.put("_id", new ObjectId(d.UID));
    query.put("owner", new ObjectId(u.UID));

    String oldPath = d.path;
    String newPath = newContainer.name == null ? "/" : newContainer.path + newContainer.name + "/";

    BasicDBObject update = new BasicDBObject();
    update.append("$set", new BasicDBObject().append("path", newPath).append("edit", now));

    collection.updateOne(query, update);

    // Update paths
    query = new BasicDBObject();
    query.put("owner", new ObjectId(u.UID));

    if (d.getPathList().size() > 0) {
      String pathRegex = "^/" + String.join("/", d.getPathList()) + "/" + d.name + "/";
      query.put("path", new BasicDBObject("$regex", pathRegex));
    } else {
      String pathRegex = "^/" + d.name + "/";
      query.put("path", new BasicDBObject("$regex", pathRegex));
    }

    // Update directories
    for (Document doc : collection.find(query)) {
      BasicDBObject dirQuery = new BasicDBObject();
      dirQuery.put("_id", doc.getObjectId("_id"));

      update = new BasicDBObject();
      update.append(
          "$set",
          new BasicDBObject()
              .append("path", newPath + doc.getString("path").substring(oldPath.length()))
              .append("edit", now));

      collection.updateOne(dirQuery, update);
    }

    // Update files
    for (Document doc : collectionFiles.find(query)) {
      BasicDBObject fileQuery = new BasicDBObject();
      fileQuery.put("_id", doc.getObjectId("_id"));

      update = new BasicDBObject();
      update.append(
          "$set",
          new BasicDBObject()
              .append("path", newPath + doc.getString("path").substring(oldPath.length()))
              .append("edit", now));

      collectionFiles.updateOne(fileQuery, update);
    }

    updateDirectoryDate(u, newContainer);

    // Update local version
    d.path = newPath;

    return d;
  }
  /**
   * Rename a directory
   *
   * @param u The owner
   * @param d The directory
   * @param newName The new name
   * @return The renamed directory
   */
  public static Directory renameDirectory(User u, Directory d, String newName) {

    if (d.name == null) // Root can't be renamed
    return d;

    MongoCollection<Document> collection = DataBase.getInstance().getCollection("directories");
    MongoCollection<Document> collectionFiles = DataBase.getInstance().getCollection("files.files");
    Date now = new Date();
    String newPath = d.path + newName;
    String oldPath = d.path + d.name;

    // Change name
    BasicDBObject query = new BasicDBObject();
    query.put("_id", new ObjectId(d.UID));
    query.put("owner", new ObjectId(u.UID));

    BasicDBObject update = new BasicDBObject();
    update.append("$set", new BasicDBObject().append("name", newName).append("edit", now));

    collection.updateOne(query, update);

    // Update paths
    query = new BasicDBObject();
    query.put("owner", new ObjectId(u.UID));

    if (d.getPathList().size() > 0) {
      String pathRegex = "^/" + String.join("/", d.getPathList()) + "/" + d.name + "/";
      query.put("path", new BasicDBObject("$regex", pathRegex));
    } else {
      String pathRegex = "^/" + d.name + "/";
      query.put("path", new BasicDBObject("$regex", pathRegex));
    }

    // Update directories
    for (Document doc : collection.find(query)) {
      BasicDBObject dirQuery = new BasicDBObject();
      dirQuery.put("_id", doc.getObjectId("_id"));

      update = new BasicDBObject();
      update.append(
          "$set",
          new BasicDBObject()
              .append("path", newPath + doc.getString("path").substring(oldPath.length()))
              .append("edit", now));

      collection.updateOne(dirQuery, update);
    }

    // Update files
    for (Document doc : collectionFiles.find(query)) {
      BasicDBObject fileQuery = new BasicDBObject();
      fileQuery.put("_id", doc.getObjectId("_id"));

      update = new BasicDBObject();
      update.append(
          "$set",
          new BasicDBObject()
              .append("path", newPath + doc.getString("path").substring(oldPath.length()))
              .append("edit", now));

      collectionFiles.updateOne(fileQuery, update);
    }

    // Return the modified element
    d.name = newName;
    return d;
  }