orion.VersionRange = function(minVersion, includeMin, maxVersion, includeMax) {
	if (minVersion != null && !(minVersion instanceof orion.Version))
		throw "invalid minVersion:" + minVersion;

	if (typeof includeMin !== "boolean")
		throw "invalid includeMin:" + includeMin;

	if (maxVersion != null && !(maxVersion instanceof orion.Version))
		throw "invalid maxVersion:" + minVersion;

	if (typeof includeMax !== "boolean")
		throw "invalid includeMax:" + includeMax;

	this._minVersion = minVersion || orion.Version.EMPTY_VERSION;
	this._includeMin = includeMin;
	this._maxVersion = maxVersion || orion.Version.MAX_VERSION;
	this._includeMax = includeMax;
};

orion.VersionRange.prototype = {
	getMinimum : function() {
		return this._minVersion;
	},
	getIncludeMinimum : function() {
		return this._includeMin;
	},
	getMaximum : function() {
		return this._maxVersion;
	},
	getIncludeMaximum : function() {
		return this._includeMax;
	},
	equals : function(other) {
		if (this === other)
			return true;

		if (!other instanceof orion.VersionRange)
			return false;

		if (this._includeMin !== other._includeMin || this._includeMax !== other._includeMax)
			return false;

		if (!this._minVersion.equals(other._minVersion))
			return false;

		if (!this._maxVersion.equals(other._maxVersion))
			return false;

		return true;
	},
	isIncluded : function(version) {
		if (version == null)
			version = orion.Version.MIN_VERSION;
		
		if (!version instanceof orion.Version)
			return false;
		
		var minCheck = this._includeMin ? 0 : 1;
		var maxCheck = this._includeMax ? 0 : -1;
		return version.compareTo(this._minVersion) >= minCheck && version.compareTo(this._maxVersion) <= maxCheck;
	},
	toString : function() {
		if (this._includeMin && this._includeMax && orion.Version.MAX_VERSION.equals(this._maxVersion))
			return this._minVersion.toString();

		return (this._includeMin ? '[' : '(') + this._minVersion + ',' + this._maxVersion + (this._includeMax ? ']' : ')');
	}
};

orion.VersionRange.EMPTY_RANGE = new orion.VersionRange(orion.Version.EMPTY_VERSION, true, orion.Version.MAX_VERSION, true);

orion.VersionRange.parseVersionRange = function(text) {
	if (text === null)
		return orion.VersionRange.EMPTY_RANGE;

	if (typeof text !== "string")
		throw "invalid text:" + text;

	text = text.replace(/^\s+|\s+$/g, '');
	if (text.length === 0)
		return orion.VersionRange.EMPTY_RANGE;

	var minVersion = null;
	var includeMin = false;
	var maxVersion = null;
	var includeMax = false;

	if (text.charAt(0) === '[' || text.charAt(0) == '(') {
		var comma = text.indexOf(',');
		if (comma === -1)
			throw "invalid text:" + text;
		var last = text.charAt(text.length - 1);
		if (last !== ']' && last !== ')')
			throw "invalid text:" + text;

		minVersion = orion.Version.parseVersion(text.substring(1, comma).replace(/^\s+|\s+$/g, ''));
		includeMin = text.charAt(0) == '[';
		maxVersion = orion.Version.parseVersion(text.substring(comma + 1, text.length() - 1).replace(/^\s+|\s+$/g, ''));
		includeMax = last == ']';
	} else {
		minVersion = orion.Version.parseVersion(text);
		includeMin = true;
		maxVersion = orion.Version.MAX_VERSION;
		includeMax = true;
	}
	return new orion.VersionRange(minVersion, includeMin, maxVersion, includeMax);
};
