var range = function(start, end) {
  
  // private variables
  var _start = start,
      _end = end;
  
  // our public scope that gets returned, methods are defined here
  var  pScope = {}; 
  
  pScope.setRange = function(start, end) {
    _start = start;
    _end = end;
  };
  
  pScope.getStart  = function() {
    return _start;
  };
  
  pScope.setStart = function(start) {
    _start = start;
  };
  
  pScope.getEnd = function() {
    return _end;
  };
  
  pScope.setEnd = function(end) {
    _end = end;
  };
  
  /**
		The minimum or smallest value of the range.
	*/
	pScope.getMin = function() {
		return Math.min(_start, _end);
	}
	
	/**
		Tthe maximum or largest value of the range.
	*/
	pScope.getMax = function() {
		return Math.max(_start, _end);
	}
	
	/**
		Determines if value is included in the range including the range's start and end values.
		
		@return Returns <code>true</code> if value was included in range; otherwise <code>false</code>.
	*/
	pScope.isWithinRange = function(value) {
		return (value <= pScope.getMax() && value >= pScope.getMin());
	}
	
	/**
		Calculates the percent of the range.
		
		@param percent: A decimal percentage (in 0-1 range)
		@return The value the percent represent of the range.
	*/
	pScope.getValueOfPercent = function(percent) {
		var min,
		    max,
		    val;
		
		if (_start <= _end) {
			min = _start;
			max = _end;
		} else {
			percent = 1 - percent;
			
			min = _end;
			max = _start;
		}
		
		val = Math.abs(max - min) * percent + min;
		
		return val;
	}
	
	/**
		Returns the percentage the value represents out of the range.
		
		@param value: An integer.
		@return A Percent object.
	*/
	pScope.getPercentOfValue = function(value) {
		return (value - pScope.getMin()) / (pScope.getMax() - pScope.getMin());
	}
  
  /**
		Determines if the range specified by the <code>range</code> parameter is equal to this range object.
		
		@param percent: A Range object.
		@return Returns <code>true</code> if ranges are identical; otherwise <code>false</code>.
	*/
	pScope.equals = function(range) {
		return _start == range.getStart() && _end == range.getEnd();
	}
	
	/**
		Determines if this range and the range specified by the <code>range</code> parameter overlap.
		
		@param A Range object.
		@return Returns <code>true</code> if this range contains any value of the range specified; otherwise <code>false</code>.
	*/
	pScope.overlaps = function(range) {
		if (pScope.equals(range) || pScope.contains(range) || range.contains(pScope) || pScope.isWithinRange(range.getStart()) || pScope.isWithinRange(range.getEnd()))
			return true;
		
		return false;
	}
	
	/**
		Determines if this range contains the range specified by the <code>range</code> parameter.
		
		@param A Range object.
		@return Returns <code>true</code> if this range contains all values of the range specified; otherwise <code>false</code>.
	*/
	pScope.contains = function(range) {
		return _start <= range.getStart() && _end >= range.getEnd();
	}
	
	/**
		@return A new range object with the same values as this range.
	*/
	pScope.clone = function() {
		return range(_start, _end);
	}
  
  return pScope;
}
