/**
   * Get the resulting x-position of the right edge of the crop window given the handle's position
   * and the image's bounding box and snap radius.
   *
   * @param x the x-position that the right edge is dragged to
   * @param imageRect the bounding box of the image that is being cropped
   * @param imageSnapRadius the snap distance to the image edge (in pixels)
   * @return the actual x-position of the right edge
   */
  private static float adjustRight(
      float x, Rect imageRect, float imageSnapRadius, float aspectRatio) {

    float resultX = x;

    // If close to the edge
    if (imageRect.right - x < imageSnapRadius) resultX = imageRect.right;
    else {
      // Select the maximum of the three possible values to use
      float resultXHoriz = Float.NEGATIVE_INFINITY;
      float resultXVert = Float.NEGATIVE_INFINITY;

      // Checks if the window is too small horizontally
      if (x <= Edge.LEFT.getCoordinate() + MIN_CROP_LENGTH_PX)
        resultXHoriz = Edge.LEFT.getCoordinate() + MIN_CROP_LENGTH_PX;

      // Checks if the window is too small vertically
      if (((x - Edge.LEFT.getCoordinate()) / aspectRatio) <= MIN_CROP_LENGTH_PX) {
        resultXVert = Edge.LEFT.getCoordinate() + (MIN_CROP_LENGTH_PX * aspectRatio);
      }

      resultX = Math.max(resultX, Math.max(resultXHoriz, resultXVert));
    }

    return resultX;
  }
  /**
   * Adjusts this Edge position such that the resulting window will have the given aspect ratio.
   *
   * @param aspectRatio the aspect ratio to achieve
   */
  public void adjustCoordinate(float aspectRatio) {

    final float left = Edge.LEFT.getCoordinate();
    final float top = Edge.TOP.getCoordinate();
    final float right = Edge.RIGHT.getCoordinate();
    final float bottom = Edge.BOTTOM.getCoordinate();

    switch (this) {
      case LEFT:
        mCoordinate = AspectRatioUtil.calculateLeft(top, right, bottom, aspectRatio);
        break;
      case TOP:
        mCoordinate = AspectRatioUtil.calculateTop(left, right, bottom, aspectRatio);
        break;
      case RIGHT:
        mCoordinate = AspectRatioUtil.calculateRight(left, top, bottom, aspectRatio);
        break;
      case BOTTOM:
        mCoordinate = AspectRatioUtil.calculateBottom(left, top, right, aspectRatio);
        break;
    }
  }
 /** Gets the current width of the crop window. */
 public static float getWidth() {
   return Edge.RIGHT.getCoordinate() - Edge.LEFT.getCoordinate();
 }
  /**
   * Returns whether or not you can re-scale the image based on whether any edge would be out of
   * bounds. Checks all the edges for a possibility of jumping out of bounds.
   *
   * @param Edge the Edge that is about to be expanded
   * @param imageRect the rectangle of the picture
   * @param aspectratio the desired aspectRatio of the picture.
   * @return whether or not the new image would be out of bounds.
   */
  public boolean isNewRectangleOutOfBounds(Edge edge, Rect imageRect, float aspectRatio) {

    float offset = edge.snapOffset(imageRect);

    switch (this) {
      case LEFT:
        if (edge.equals(Edge.TOP)) {
          float top = imageRect.top;
          float bottom = Edge.BOTTOM.getCoordinate() - offset;
          float right = Edge.RIGHT.getCoordinate();
          float left = AspectRatioUtil.calculateLeft(top, right, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);

        } else if (edge.equals(Edge.BOTTOM)) {
          float bottom = imageRect.bottom;
          float top = Edge.TOP.getCoordinate() - offset;
          float right = Edge.RIGHT.getCoordinate();
          float left = AspectRatioUtil.calculateLeft(top, right, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);
        }
        break;

      case TOP:
        if (edge.equals(Edge.LEFT)) {
          float left = imageRect.left;
          float right = Edge.RIGHT.getCoordinate() - offset;
          float bottom = Edge.BOTTOM.getCoordinate();
          float top = AspectRatioUtil.calculateTop(left, right, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);

        } else if (edge.equals(Edge.RIGHT)) {
          float right = imageRect.right;
          float left = Edge.LEFT.getCoordinate() - offset;
          float bottom = Edge.BOTTOM.getCoordinate();
          float top = AspectRatioUtil.calculateTop(left, right, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);
        }
        break;

      case RIGHT:
        if (edge.equals(Edge.TOP)) {
          float top = imageRect.top;
          float bottom = Edge.BOTTOM.getCoordinate() - offset;
          float left = Edge.LEFT.getCoordinate();
          float right = AspectRatioUtil.calculateRight(left, top, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);

        } else if (edge.equals(Edge.BOTTOM)) {
          float bottom = imageRect.bottom;
          float top = Edge.TOP.getCoordinate() - offset;
          float left = Edge.LEFT.getCoordinate();
          float right = AspectRatioUtil.calculateRight(left, top, bottom, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);
        }
        break;

      case BOTTOM:
        if (edge.equals(Edge.LEFT)) {
          float left = imageRect.left;
          float right = Edge.RIGHT.getCoordinate() - offset;
          float top = Edge.TOP.getCoordinate();
          float bottom = AspectRatioUtil.calculateBottom(left, top, right, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);

        } else if (edge.equals(Edge.RIGHT)) {
          float right = imageRect.right;
          float left = Edge.LEFT.getCoordinate() - offset;
          float top = Edge.TOP.getCoordinate();
          float bottom = AspectRatioUtil.calculateBottom(left, top, right, aspectRatio);

          return isOutOfBounds(top, left, bottom, right, imageRect);
        }
        break;
    }
    return true;
  }