package me.hammerle.supersnuvi.util;

import me.hammerle.supersnuvi.rendering.Game;

public class CollisionBox 
{
    public final static CollisionBox NULL_BOX = new CollisionBox(0, 0, 0, 0);
    public final static CollisionBox DEFAULT_BOX = createScaledBox(0, 0, 1, 1);
    
    private final double minX;
    private final double maxX;
    private final double minY;
    private final double maxY;
    
    private double cMinX;
    private double cMaxX;
    private double cMinY;
    private double cMaxY;
    
    public CollisionBox(double x1, double y1, double x2, double y2)
    {
        minX = Math.min(x1, x2);
        maxX = Math.max(x1, x2);
        minY = Math.min(y1, y2);
        maxY = Math.max(y1, y2);
        cMinX = minX;
        cMaxX = maxX;
        cMinY = minY;
        cMaxY = maxY;
    }
    
    public static CollisionBox createScaledBox(double x1, double y1, double x2, double y2)
    {
        return new CollisionBox(x1 * Game.TILE_SIZE, y1 * Game.TILE_SIZE, x2 * Game.TILE_SIZE, y2 * Game.TILE_SIZE);
    }
    
    public CollisionBox copy()
    {
        return new CollisionBox(cMinX, cMinY, cMaxX, cMaxY);
    }
    
    public CollisionBox reset()
    {
        cMinX = minX;
        cMaxX = maxX;
        cMinY = minY;
        cMaxY = maxY;
        return this;
    }

    public double getWidth() 
    {
        return maxX - minX;
    }
    
    public double getHeight() 
    {
        return maxY - minY;
    }
    
    public double getMinX() 
    {
        return cMinX;
    }

    public double getMaxX() 
    {
        return cMaxX;
    }

    public double getMinY() 
    {
        return cMinY;
    }

    public double getMaxY() 
    {
        return cMaxY;
    }
   
    public CollisionBox expand(double x, double y)
    {
        if(x < 0.0d)
        {
            cMinX += x;
        }
        else
        {
            cMaxX += x;
        }
        if(y < 0.0d)
        {
            cMinY += y;
        }
        else
        {
            cMaxY += y;
        }
        return this;
    }

    public CollisionBox grow(double x, double y)
    {
        x = Math.abs(x);
        y = Math.abs(y);
        cMinX -= x;
        cMaxX += x;
        cMinY -= y;
        cMaxY += y;
        return this;
    }

    public CollisionBox grow(double value)
    {
        return this.grow(value, value);
    }

    public CollisionBox intersect(CollisionBox cb)
    {
        return new CollisionBox(Math.max(cMinX, cb.cMinX), Math.max(cMinY, cb.cMinY), 
                Math.min(cMaxX, cb.cMaxX), Math.min(cMaxY, cb.cMaxY));
    }
    
    public boolean intersects(double x1, double y1, double x2, double y2)
    {
        if(this == NULL_BOX)
        {
            return false;
        }
        if(x1 > x2)
        {
            double swap = x1;
            x1 = x2;
            x2 = swap;
        }
        if(y1 > y2)
        {
            double swap = y1;
            y1 = y2;
            y2 = swap;
        }
        return cMinX < x2 && cMaxX > x1 && cMinY < y2 && cMaxY > y1;
    }
    
    public boolean intersects(CollisionBox cb)
    {
        if(cb == NULL_BOX)
        {
            return false;
        }
        return this.intersects(cb.cMinX, cb.cMinY, cb.cMaxX, cb.cMaxY);
    }

    public CollisionBox offset(double x, double y)
    {
        cMinX += x;
        cMaxX += x;
        cMinY += y;
        cMaxY += y;
        return this;
    }

    @Override
    public String toString() 
    {
        StringBuilder sb = new StringBuilder("box[x1 = ");
        sb.append(cMinX);
        sb.append(", y1 = ");
        sb.append(cMinY);
        sb.append(", x2 = ");
        sb.append(cMaxX);
        sb.append(", y2 = ");
        sb.append(cMaxY);
        sb.append(']');
        return sb.toString();
    } 
}
