/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       flatten heights of the element nodes.
 *
 *    @version 1.1.20090610
 *    @requires jquery.js
 *    @requires bajl.js
 *    @requires bajl.fontSizeObserver.js
 */
/* -------------------------------------------------------------------------- */

(function($) {



/* -------------------- jQuery.fn : BAJL_FlatHeights -------------------- */
/**
 * BAJL.FlatHeights as jQuery plugin
 * @returns jQuery
 * @type jQuery
 */
jQuery.fn.BAJL_FlatHeights = function() {
	if (this.size() > 0) new BAJL.FlatHeights(this);
	return this;
}



/* -------------------- Class : BAJL.FlatHeights -------------------- */

/**
 * provides a behavior to flatten heights of element nodes.
 * @class heights flattener
 * @param {NodeList|jQuery|String} blocks    block elements to flatten heights
 * @constructor
 */
BAJL.FlatHeights = function(blocks) {
	/** block elements to flatten heights.
	    @type Element[]
	    @private
	    @constant */
	this.blocks = $(blocks).get();
	/** current max height (px).
	    @type Number
	    @private
	    */
	this.height = 0;
	
	if (BAJL.env.isDOMReady) {
		this.init();
	}
}

/**
 * an array of instances of this class.
 * @field
 * @type BAJL.FlatHeights[]
 */
BAJL.FlatHeights.instances = []

/**
 * initialize.
 * @private
 */
BAJL.FlatHeights.prototype.init = function() {
	if (this.blocks.length == 0 || !this.blocks.every(function(node) { return node.nodeType == Node.ELEMENT_NODE })) {
		throw new TypeError('BAJL.FlatHeights.init: all targets must be element nodes.');
	} else {
		this.process();
		BAJL.Singleton(BAJL.FontSizeObserver).addCallback('onChange', this.process, this);
		BAJL.FlatHeights.instances.push(this);
	}
}

/**
 * process to flatten heights of the nodes.
 * @return max height value (in pixel unit)
 * @type Number
 */
BAJL.FlatHeights.prototype.process = function() {
	return this.setHeight(this.getHeight(true));
}

/**
 * get max height value in the nodes.
 * @param {Boolean} recalibrate    if true, recalibrate the heights, this causes blocks unflatten
 * @return max height value (in pixel unit)
 * @type Number
 */
BAJL.FlatHeights.prototype.getHeight = function(recalibrate) {
	if (!recalibrate) {
		return this.height;
	} else {
		this.setHeight(0);  // set heights to 'auto'
		return $(this.blocks).map (function() { return this.offsetHeight })
		                     .sort(function(a, b) { return (b - a) })
		                     .get(0) || 0;
	}
}

/**
 * change height of the nodes.
 * @param {Number} height    new height (border-box height) of the balloon, 0 means 'auto'
 * @return max height value (in pixel unit)
 * @type Number
 */ 
BAJL.FlatHeights.prototype.setHeight = function(height) {
	height = Math.max(height, 0) || 0;
	$(this.blocks).each(function() {
		$(this).css('height', (height == 0) ? 'auto' : height + 'px');

		var current = $(this).outerHeight();
		var revise  = 2 * height - current;

		if (current != height && revise >= 0) {
			$(this).css('height', revise + 'px');
		}
	});
	return (this.height = height);
}





})(jQuery);
