/**
 * Creates an expandable / collapsible module instead of a static
 * module. Clicking the title will expand / collapse the content,
 * changing the icon to indicate the state.
 * @constructor
 */
function ExpandableModule(element) {
	this._element = $(element);

	this._element.addClass("expanded-sidebar-module");
	this._element.children("h3:first-child").addClass("activator");
	this._enable();
}

ExpandableModule.prototype = {
	/**
	 * The HTML List element containing the module; title and content.
	 * @private
	 */
	_element: null,
	
	/**
	 * The time, in miliseconds, the animation should take.
	 * @private
	 */
	 _duration: 500,
	
	/**
	 * Disables the expand / collapse functionality.
	 */
	_disable: function () {
		this._element.children("h3:first-child").unbind("toggle").unbind("click");
	},
	
	/**
	 * Enables the expand / collapse functionality
	 */
	_enable: function () {
		this._element.children("h3:first-child").toggle(new Delegate(this, this._hideContent), new Delegate(this, this._showContent));
	},
	
	
	/**
	 * Eventhandler used to show the content of the module,
	 * changes the classname so content can be shown using CSS,
	 * and animates to the height of the content.
	 * @param {EventObject} eventObj The jQuery event object.
	 * @private
	 */
	_showContent: function (eventObj) {
		// Prevent multiple clicks.
		this._disable();
		
		// Reset the CSS classes so the content is visible again.
		var module = $(eventObj.target).parent(".expandable-sidebar-module");
		module.removeClass("collapsed-sidebar-module").addClass("expanded-sidebar-module");
		
		// Detect the height of the content.
		module.css("overflow", "visible");
		var oldCssHeight = module.css("height");
		module.css("height", "");
		var contentHeight = module.height();
		module.css("height", oldCssHeight);
		module.css("overflow", "hidden");
		
		// Animate the current height to the content height, then reset.
		module.animate({"height": contentHeight + "px"}, this._duration, new Delegate(this, function () {
			module.css("overflow", "");
			module.css("height", "");
			
			// Allow clicking again.
			this._enable();
		}));
	},
	
	/**
	 * Eventhandler used to hide the content of the module,
	 * changes the classname so content can be hidden using CSS,
	 * and animates the collapsing.
	 * @param {EventObject} eventObj The jQuery event object.
	 * @private
	 */
	_hideContent: function (eventObj) {
		// Prevent multiple clicks.
		this._disable();
		
		var module = $(eventObj.target).parent(".expandable-sidebar-module");
		
		// Detect the height of the title.
		module.removeClass("expanded-sidebar-module").addClass("collapsed-sidebar-module");
		var contentHeight = module.height();
		module.removeClass("collapsed-sidebar-module").addClass("expanded-sidebar-module");
				
		// Animate the current height to the height of the title,
		// then reset and hide the content.
		module.css("overflow", "hidden");
		module.animate({"height": contentHeight + "px"}, this._duration, new Delegate(this, function () {
			module.css("overflow", "");
			module.removeClass("expanded-sidebar-module").addClass("collapsed-sidebar-module");
			
			// Allow clicking again.
			this._enable();
		}));
	}
};
