package com.github.davidmoten.rtree.geometry;

import com.github.davidmoten.util.ObjectsHelper;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

public final class Rectangle implements Geometry, HasGeometry {
    private final float x1, y1, x2, y2;

    protected Rectangle(float x1, float y1, float x2, float y2) {
        Preconditions.checkArgument(x2 >= x1);
        Preconditions.checkArgument(y2 >= y1);
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }

    public float x1() {
        return x1;
    }

    public float y1() {
        return y1;
    }

    public float x2() {
        return x2;
    }

    public float y2() {
        return y2;
    }

    public float area() {
        return (x2 - x1) * (y2 - y1);
    }

    public Rectangle add(Rectangle r) {
        return new Rectangle(Math.min(x1, r.x1), Math.min(y1, r.y1), Math.max(x2, r.x2), Math.max(
                y2, r.y2));
    }

    public static Rectangle create(double x1, double y1, double x2, double y2) {
        return new Rectangle((float) x1, (float) y1, (float) x2, (float) y2);
    }

    public static Rectangle create(float x1, float y1, float x2, float y2) {
        return new Rectangle(x1, y1, x2, y2);
    }

    public boolean contains(double x, double y) {
        return x >= x1 && x <= x2 && y >= y1 && y <= y2;
    }

    @Override
    public boolean intersects(Rectangle r) {
        float xMaxLeft = Math.max(x1(), r.x1());
        float xMinRight = Math.min(x2(), r.x2());
        if (xMinRight<xMaxLeft) 
            return false;
        else {
            float yMaxBottom = Math.max(y1(), r.y1());
            float yMinTop = Math.min(y2(), r.y2());
            return yMinTop>=yMaxBottom;
        }
    }

    @Override
    public double distance(Rectangle r) {
        if (intersects(r))
            return 0;
        else {
            Rectangle mostLeft = x1 < r.x1 ? this : r;
            Rectangle mostRight = x1 > r.x1 ? this : r;
            double xDifference = Math.max(0, mostLeft.x1 == mostRight.x1 ? 0 : mostRight.x1
                    - mostLeft.x2);

            Rectangle upper = y1 < r.y1 ? this : r;
            Rectangle lower = y1 > r.y1 ? this : r;

            double yDifference = Math.max(0, upper.y1 == lower.y1 ? 0 : lower.y1 - upper.y2);

            return Math.sqrt(xDifference * xDifference + yDifference * yDifference);
        }
    }

    @Override
    public Rectangle mbr() {
        return this;
    }

    @Override
    public String toString() {
        return "Rectangle [x1=" + x1 + ", y1=" + y1 + ", x2=" + x2 + ", y2=" + y2 + "]";
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(x1, y1, x2, y2);
    }

    @Override
    public boolean equals(Object obj) {
        Optional<Rectangle> other = ObjectsHelper.asClass(obj, Rectangle.class);
        if (other.isPresent()) {
            return Objects.equal(x1, other.get().x1) && Objects.equal(x2, other.get().x2)
                    && Objects.equal(y1, other.get().y1) && Objects.equal(y2, other.get().y2);
        } else
            return false;
    }

    public float intersectionArea(Rectangle r) {
        if (!intersects(r))
            return 0;
        else
            return create(Math.max(x1, r.x1), Math.max(y1, r.y1), Math.min(x2, r.x2),
                    Math.min(y2, r.y2)).area();
    }

    public float perimeter() {
        return 2 * (x2 - x1) + 2 * (y2 - y1);
    }

    @Override
    public Geometry geometry() {
        return this;
    }

}
@@ -973,26 +973,16 @@
 , r.x2),
- Math.max(
 %0A       
@@ -990,16 +990,25 @@
         
+Math.max(
 y2, r.y2
@@ -1499,329 +1499,67 @@
     
-float xMaxLeft = Math.max(x1(), r.x1());%0A        float xMinRight = Math.min(x2(), r.x2());%0A        if (xMinRight%3CxMaxLeft) %0A            return false;%0A        else %7B%0A            float yMaxBottom = Math.max(y1(), r.y1());%0A            float yMinTop = Math.min(y2(), r.y2());%0A            return yMinTop%3E=yMaxBottom;%0A        %7D
+return !(x1 %3E r.x2 %7C%7C x2 %3C r.x1 %7C%7C y1 %3E r.y2 %7C%7C y2 %3C r.y1);
 %0A   
@@ -1837,16 +1837,36 @@
 h.max(0,
+%0A                   
  mostLef
@@ -1904,36 +1904,16 @@
 Right.x1
-%0A                   
  - mostL

simplify Rectangle.intersects method