// mooutils.js -- MooTools extended utilities
// Written by Oo+
// require MooTools 1.2+
// an integral part of TRE Web 2.0 Components

//
// Extend Element class to support more size computation functions.
//
Element.implement({
	/// Build CSS complaint rectangle, with width and height values.
	getRectangle: function(top, right, bottom, left) {
		return {
			'top': top,
			'right': right,
			'bottom': bottom,
			'left': left,
			'width': left + right,
			'height': top + bottom
		};
	},

	/// Get margin size as integer.
	getMarginSize: function() {
		return this.getRectangle(
			this.getStyle('margin-top').toInt(),
			this.getStyle('margin-right').toInt(),
			this.getStyle('margin-bottom').toInt(),
			this.getStyle('margin-left').toInt()
		);
	},

	/// Get padding size as integer.
	getPaddingSize: function() {
		return this.getRectangle(
			this.getStyle('padding-top').toInt(),
			this.getStyle('padding-right').toInt(),
			this.getStyle('padding-bottom').toInt(),
			this.getStyle('padding-left').toInt()
		);
	},

	/// Get border size as integer.
	getBorderSize: function() {
		return this.getRectangle(
			this.getStyle('border-top-width').toInt(),
			this.getStyle('border-right-width').toInt(),
			this.getStyle('border-bottom-width').toInt(),
			this.getStyle('border-left-width').toInt()
		);
	},

	/// Compute usable size
	getUsableSize: function() {
		var size = this.getSize();
		var border = this.getBorderSize();
		var padding = this.getPaddingSize();
		size.x -= (border.width + padding.width);
		size.y -= (border.height + padding.height);
		return size;
	},

	// Compute size for an element to fit in given area {x: width, y: height}
	// Please note margin calculation will not be correct in all case.
	// Avoid using margins for elements that need dimensions be computed.
	getSizeToFitArea: function(size) {
		var margin = this.getMarginSize();
		var border = this.getBorderSize();
		var padding = this.getPaddingSize();
		return {
			x: size.x - margin.width - border.width - padding.width,
			y: size.y - margin.height - border.height - padding.height
		};
	},

	/// Compute how to resize this element to fit in target element.
	getFitSize: function(target) {
		var size = target.getSize();
		var spacing = target.getBorderSize();
		var margin = this.getMarginSize();
		var border = this.getBorderSize();
		var padding = this.getPaddingSize();
		return {
			left: -spacing.left,
			top: -spacing.top,
			width: size.x - margin.width - border.width - padding.width,
			height: size.y - margin.height - border.height - padding.height
		};
	},

	/// Resize and inject this element to cover target element.
	sizeToCover: function(target) {
		this.setStyle('position', 'absolute').inject(target.setStyle('position', 'relative'));
		var size = this.getFitSize(target);
		this.setStyle('left', size.left);
		this.setStyle('top', size.top);
		this.setStyle('width', size.width);
		this.setStyle('height', size.height);
		return this;
	}
});

//
// Extend Element class to stacked visibility and disability setting
//
Element.implement({
	stackedHide: function() {
		var counter = this.retrieve('hidden');
		if ($chk(counter) && counter > 0)
			this.store('hidden', counter + 1);
		else {
			this.store('hidden', 1);
			this.setStyle('visibility', 'hidden');
		}
		return this;
	},
	stackedShow: function() {
		var counter = this.retrieve('hidden');
		if ($chk(counter) && counter > 1)
			this.store('hidden', counter - 1);
		else {
			this.store('hidden', 0);
			this.setStyle('visibility', 'visible');
		}
		return this;
	},
	stackedDisable: function() {
		var counter = this.retrieve('disabled');
		if ($chk(counter) && counter > 0)
			this.store('disabled', counter + 1);
		else {
			this.store('disabled', 1);
			this.disabled = true;
		}
		return this;
	},
	stackedEnable: function() {
		var counter = this.retrieve('disabled');
		if ($chk(counter) && counter > 1)
			this.store('disabled', counter - 1);
		else {
			this.store('disabled', 0);
			this.disabled = false;
		}
		return this;
	}
});

//
// Extend Element class to support miscellaneous functionals.
//
Element.implement({
	makeEnoughHeight: function() {
		var h0 = this.getSize().y;
		var h1 = h0;
		for (var i = 0; i < arguments.length; ++i) {
			var h2 = $(arguments[i]).getSize().y;
			if (h1 < h2)
				h1 = h2;
		}
		if (h1 != h0)
			this.setStyle('height', h1);
		return this;
	},
	makeEqualHeight: function(target) {
		var h0 = this.getSize().y;
		var h1 = target.getSize().y;
		if (h0 < h1)
			this.setStyle('height', h1);
		else if (h0 > h1)
			target.setStyle('height', h0);
	}
});


