var HEGA = HEGA || {};

/**
	Creates a standardized way of describing a rectangle.
	
	usage:
	
	  var rectangle = HEGA.rectangle(0, 0, 300, 100);
	  // value
	  
*/
HEGA.rectangle = function(x, y, width, height) {
  
  // private vars
  var _x = x,
      _y = y,
      _width = width,
      _height = height,
      _maxX = _x + _width,
      _maxY = _y + _height;
  
  // our public scope that gets returned, methods are defined here
  var pScope = {};
  
  // decided to not implement property getter/setter api using "__defineGetter__" or Object.defineProperty() due to speed costs, see test cases:
  //    http://jsperf.com/object-defineproperty-vs-definegetter-vs-normal/6

  
  pScope.getX = function() {
    return _x;
  };
  
  pScope.setX = function(x) {
    _x = x;
    _maxX = _x + _width;
  };
  
  pScope.getY = function() {
    return _y;
  };
  
  pScope.setY = function(y) {
    _y = y;
    _maxY = _y + _height;
  };
  
  pScope.getWidth = function() {
    return _width;
  };
  
  pScope.setWidth = function(width) {
    _width = width;
    _maxX = _x + _width;
  };
  
  pScope.getHeight = function() {
    return _height;
  };
  
  pScope.setHeight = function(height) {
    _height = height;
    _maxY = _y + _height;
  };
  
  pScope.getMaxX = function() {
    return _maxX;
  };
  
  pScope.getMaxY = function() {
    return _maxY;
  };
  
  
  /** 
    Determines whether the specified point is contained within the rectangular region defined by this Rectangle object.  
  
  */
  pScope.contains = function(x, y) {
    return (_x <= x && x <= _maxX && 
            _y <= y && y <= _maxY);
  };
  
  /** 
    Determines whether another rectangle is contained within the rectangular region defined by this Rectangle object.  
  
  */
  pScope.containsRectangle = function(rectangle) {
    return (pScope.contains(rectangle.getX(), rectangle.getY()) &&
            pScope.contains(rectangle.getMaxX(), rectangle.getMaxY()));
  };
    
  /** 
    Determines whether the object specified in the testRect parameter intersects with this Rectangle object
    
    @returns boolean
    
  */
	pScope.intersects = function(testRect) {
    return (Math.min( _maxX, testRect.getMaxX() ) - Math.max( _x, testRect.getX() ) >= 0 &&
		        Math.min( _maxY, testRect.getMaxY() ) - Math.max( _y, testRect.getY() ) >= 0);
  };
  
  /** 
    @returns HEGA.rectangle
    
  */
  pScope.intersection = function(testRect) {
    if (pScope.intersects(testRect)) {
      var x = Math.max( _x, testRect.getX() ),
          y = Math.max( _y, testRect.getY() );
          
      return HEGA.rectangle(x,
                            y,
                            Math.min( _maxX, testRect.getMaxX()) - x,
                            Math.min( _maxY, testRect.getMaxY()) - y);
    } else {
      return HEGA.rectangle(0, 0, 0, 0);
    }
  };
  
  pScope.equals = function(rectangle) {
    return (_x == rectangle.getX() && _maxX == rectangle.getMaxX() &&
            _y == rectangle.getY() && _maxY == rectangle.getMaxY());
  };
  
  pScope.clone = function() {
    return HEGA.rectangle(_x, _y, _width, _height);
  };
  
  pScope.copy = function(rectangle) {
    _x = rectangle.getX();
    _y = rectangle.getY();
    _width = rectangle.getWidth();
    _height = rectangle.getHeight();
    _maxX = _x + _width;
    _maxY = _y + _height;
  };
  
  pScope.toString = function() {
    return 'rectangle: { x:'+_x+', y:'+_y+', width: '+_width+', height:'+_height+' }';
  }
  
  return pScope;
  
};
