Object.extend (Element, {				   
  	findParent: function (element, tagName) 
  	{
	   	while (element.parentNode && (!element.tagName || (element.tagName.toUpperCase() != tagName.toUpperCase())))
		{
      		element = element.parentNode;
		}
    	
		return element;
  	}
});

var CheckboxManager = Class.create ();

CheckboxManager.prototype = {
	
	/**
	 * This constructor initializes the CheckBoxManager and adds all the event listeners
	 *
	 * @param	HTMLElement		form			The id or reference of the containing form
	 * @param	HTMLElement		checkboxName	The name of the array with the checkboxes we want to manage
	 * 
	 */
	initialize: function (form, checkboxName)
	{
		this.form           = $(form);
		this.checkboxName   = checkboxName;
		this.buttons        = {};
		this.useConfirm     = false;
		this.code           = "";
		this.rowType        = "";
		this.checkAllButton = false;
		this.onCheckedCountChangedHandler = false;
		
		this.form.onsubmit  = this.onSubmit.bindAsEventListener (this);
		this.table = this.form.getElementsByTagName ("table")[0];
		this.checkboxes = Form.getInputs (this.form, "checkbox", this.checkboxName);

		for (var i = 0; i < this.checkboxes.length; i++)
		{
			this.checkboxes[i].onclick = this.onCheckboxClicked.bindAsEventListener (this);
		}
		
		if ($("checkAll"))
		{
			$("checkAll").onclick = this.onCheckAllClicked.bindAsEventListener (this);
			this.checkAllButton = $('checkAll');
		}
		
		this.onCheckedCountChanged ();
	},
	
	/**
	 * This public function registers virtual rows of html elements to change css style when selected (if not using default html table)
	 *
	 * @param	HTMLElement     rowType			The htlm elment of the virtual rows (for example li)
	 * 
	 */
	registerVirtualRows: function (rowType)
	{
		this.rowType = rowType;
	},
	
	/**
	 * This public function registers a Form-submit-button
	 *
	 * @param	HTMLElement		button			The id of or reference to the button
	 * @param	boolean			useConfirm		Whether or not we will show the user a confirmation alert
	 * @param	string			code			prefix of the id of the hidden form value with the confirmation text (id = prefix + "ConfirmText")
	 * 
	 */
	registerButton: function (button, useConfirm, code)
	{	
		if ($(button))
		{
			$(button).onclick = this.onButtonClicked.bindAsEventListener (this);
			this.buttons[button] = { useConfirm: useConfirm, code: code };	
			this.onCheckedCountChanged ();
		}
	},
	
	/**
	 * This public function registers a 'toggle all'-checkbox (if not using default with id="checkAll")
	 *
	 * @param	HTMLElement		checkbox	The id of or reference to the checkbox that toggles all other checkboxes this manager is watching
	 * 
	 */
	registerCheckAllCheckBox: function (checkbox)
	{
		if ($(checkbox))
		{
			$(checkbox).onclick = this.onCheckAllClicked.bindAsEventListener (this);
			this.onCheckedCountChanged ();
			this.checkAllButton = $(checkbox);
		}
	},
	
	/**
	 * This public function registeres a function that will be called whenever the amount of checked checkboxes can change
	 *
	 * @param	Javascript-function		eventHandler	Reference to function that should be executed on change
	 *
	 */
	registerOnCheckedCountChangedHandler: function (eventHandler)
	{
		this.onCheckedCountChangedHandler = eventHandler;
	},
	
	/**
	 * This private function is the event handler for the click-event of the registered button
	 *
	 * @param	Javascript-event	e	The event that triggered this action
	 *
	 */
	onButtonClicked: function (e)
	{
		var buttonID = Event.element(e).id;

		if (this.buttons[buttonID])
		{
			var button      = this.buttons[buttonID];
			this.useConfirm = button["useConfirm"];
			this.code       = button["code"];
		}
	},
	
	/**
	 * This private function is the event handler for the submit-event of the form
	 *
	 * @param	Javascript-event	e	The event that triggered this action
	 *
	 */
	onSubmit: function (e)
	{
		if (this.useConfirm)
		{
			this.useConfirm = false;
			
			var code  = this.code;
			this.code = "";

			return (confirm ($(code + "ConfirmText").value));
		}	
	},
	
	onRowClicked: function (e)
	{
		var row = Event.element (e);
			
		/*debug (row);*/
		
		this.selectRow (row, true);
	},
	
	onCheckboxClicked: function (e) 
	{
		if (this.table)
		{
			var row = Event.findElement (e, "tr");
			this.selectRow (row, Event.element (e).checked);
		}
		else
		{
			var row = Event.findElement (e, this.rowType);
			this.selectRow (row, Event.element (e).checked);
		}
		
		this.onCheckedCountChanged ();
	},
	
	onCheckAllClicked: function (e)
	{
		var checked = Event.element (e).checked;
		
		for (var i = 0; i < this.checkboxes.length; i++)
		{
			this.checkboxes[i].checked = checked;
			
			if (this.table)
			{
				this.selectRow (Element.findParent (this.checkboxes[i], "tr"), checked);			
			}
			else
			{
				this.selectRow (Element.findParent (this.checkboxes[i], this.rowType), checked);
			}
		}
		
		this.onCheckedCountChanged ();
	},
	
	onCheckedCountChanged: function ()
	{
		var checkedCount = this.checkedCount ();

		for (var buttonID in this.buttons)
		{	
			if ($(buttonID))
			{
				$(buttonID).disabled = (checkedCount == 0);
			}
		}
		
		if (this.checkAllButton)
		{
			this.checkAllButton.checked = (checkedCount == this.checkboxes.length);
		}
		
		if (this.onCheckedCountChangedHandler)
		{
			this.onCheckedCountChangedHandler ();
		}
	},
	
	/**
	 * This function return the amount of checked checkboxes this manager is watching
	 *
	 * @return int
	 *
	 */
	checkedCount: function ()
	{
		var count = 0;
		
		for (var i = 0; i < this.checkboxes.length; i++)
		{
			if (this.checkboxes[i].checked)
			{
				count++;
			}
		}
		
		return count;			
	},
	
	selectRow: function (row, selected)
	{
		if (!selected)
		{
			try {
				row.removeClassName ("selected");
			} catch (e) {
				/*debug (e);*/
			}
		}
		else
		{
			try {
				row.addClassName ("selected");
			} catch (e) {
				/*debug (e);*/
			}
		}		
	}
}
