/**
 * CheckList class
 *
 */
var CheckList = {
	listItemStates : new Object(),
	LSTATE : {OPEN:1,CLOSED:0},
	
	init : function(elm){
		CheckList._initSubList(elm);
	},
	
	_initSubList : function(listElm){
		var lis = listElm.childNodes;
		var li, title, ul, chks, chk;
		
		for(var i=0;i<lis.length;i++){
			li = lis[i];
			
			if(DomHtml.isElementNode(li) && li.nodeName.toLowerCase() == 'li'){
				if(li.className == 'mainItem'){
					title = li.getElementsByTagName('div')[0];
					ul = li.getElementsByTagName('ul');

					Events.attachEvent(title,'click',CheckList.titleEvtClick);
					Events.attachEvent(title,'mouseover',CheckList.titleEvtMouseOver);
					Events.attachEvent(title,'mouseout ',CheckList.titleEvtMouseOut);
					
					if(ul && typeof ul[0] != 'undefined') CheckList._initSubList(ul[0]);
				}
				else if(li.className == 'groupTitle'){
					chk = CheckList._getMainCheckItem(li);
					
					if(chk != null){
						Events.attachEvent(chk,'click',CheckList.mainChkEvtClick);
						CheckList.checkItemGroup(CheckList._resolveParentListItem(li));
					}
				}
				else if(li.className == 'subItem'){
					chks = CheckList._getCheckItems(li);
					
					if(typeof chks[0] != 'undefined'){
						Events.attachEvent(chks[0],'click',CheckList.itemChkEvtClick);
						if(chks[0].checked) CheckList.openList(CheckList._resolveParentListItem(li));
					}
				}
			}
		}
	},
	
	mainChkEvtClick : function(e){
		var target = e.getTarget();
		var listItem = CheckList._resolveParentListItem(target);
		var chks = CheckList._getCheckItems(listItem);
		var check = target.checked;
		
		for(var i=0;i<chks.length;i++){
			chks[i].checked = check;
		}
	},
	
	itemChkEvtClick : function(e){
		var target = e.getTarget();
		var listItem = CheckList._resolveParentListItem(target);
		CheckList.checkItemGroup(listItem);
	},
	
	checkItemGroup : function(elm){
		var mainChk = CheckList._getMainCheckItem(elm);
		var chks = CheckList._getCheckItems(elm);
		var checked = true;
		
		for(var i=0;i<chks.length;i++){
			if(!chks[i].checked){
				checked = false;
				break;
			}
		}
		
		mainChk.checked = checked;
	},
	
	titleEvtClick : function(e){
		var target = e.getTarget();
		var elm = CheckList._resolveParentListItem(target);
		
		if(CheckList._state(elm) == CheckList.LSTATE.CLOSED){
			CheckList.openList(elm);	
		}
		else{
			CheckList.closeList(elm);
		}
	},
	
	titleEvtMouseOver : function(e){
		var target = e.getTarget();
		var elm = CheckList._resolveParentListItem(target);
		var title = CheckList._resolveListTitle(elm);
		
		if(CheckList._state(elm) == CheckList.LSTATE.CLOSED){
			title.className = 'titleOverClosed';
		}
		else{
			title.className = 'titleOverOpen';
		}
	},
	
	titleEvtMouseOut : function(e){
		var target = e.getTarget();
		var elm = CheckList._resolveParentListItem(target);
		var title = CheckList._resolveListTitle(elm);
		
		if(CheckList._state(elm) == CheckList.LSTATE.CLOSED){
			title.className = 'titleClosed';
		}
		else{
			title.className = 'titleOpen';
		}
	},
	
	openList : function(e){
		if(CheckList._state(e) == CheckList.LSTATE.OPEN) return;
		
		var _extend = function(container,elm,amount,space,scrollLimit){
			var h = 15;
			var c = parseInt(elm.style.height);
			var newHeight, scroll;

			if(amount > h){
				newHeight = (c+h);
				amount = amount-h;
			}
			else{
				newHeight = (c+amount);
				amount = 0;
			}
			
			elm.style.height = newHeight+'px';
			
			if(space < amount && scrollLimit > 0){
				var scroll = (h > scrollLimit)?scrollLimit:h;
				container.scrollTop += scroll;
				scrollLimit -= scroll;
			}
			
			if(amount > 0){
				setTimeout(function(){_extend(container,elm,amount,space,scrollLimit)},10);
			}
		}
		
		var elms = e.getElementsByTagName('ul');
		if(typeof elms[0] == 'undefined') return;
		
		var scrollBarHeight = 20;
		var itemList = elms[0];
		var title = CheckList._resolveListTitle(e);
		var vpCont = DomHtml.getNodeViewport(e.parentNode);
		var vpList, vpList2, space, offsetTop, scrollLimit;
		
		//change the rendering of the title
		title.className = 'titleOpen';

		//hide item list, set its position to absolute and its display to block
		itemList.style.visibility = 'hidden';
		itemList.style.position = 'absolute';
		itemList.style.display = 'block';
		
		//get view port of the item list after the 
		//list has been hidden and its position is absolute
		vpList = DomHtml.getNodeViewport(itemList);
		
		//set display bavk stacit, set list's height to 0 and set list visible
		itemList.style.height = '0px';
		itemList.style.position = 'static';
		itemList.style.visibility = 'visible';
		itemList.style.overflow = 'hidden'; //use "overflow hidden" to show list only partially
		
		//get new view port after list has zero height
		vpList2 = DomHtml.getNodeViewport(itemList);
				
		//use top property from the secondary viewport
		vpList['top'] = vpList2['top']; 
		
		//top offset between item list and the checklist container
		offsetTop = (vpList['top']-e.parentNode.scrollTop-vpCont['top']);
		
		//available space for item list
		space = vpCont['height']-scrollBarHeight-offsetTop;
		
		//available scroll amount for the item list
		if(space < 0){
			scrollLimit = 0;
		}
		else{
			scrollLimit = Math.round(((vpCont['height']-scrollBarHeight)/2)-space);
		}
		
		//extend list
		_extend(e.parentNode,itemList,vpList['height'],space,scrollLimit);
		
		//set opened
		CheckList._setState(e,CheckList.LSTATE.OPEN);
	},
	
	closeList : function(e){
		if(CheckList._state(e) == CheckList.LSTATE.CLOSED) return;
		
		var _collapse = function(elm,amount){
			var h = 15;
			var c = parseInt(elm.style.height);
			
			if(amount > h){
				elm.style.height = (c-h)+'px';
			}
			else{
				elm.style.display = 'none';
				elm.style.height = 'auto';
				elm.style.borderBottom = '0';
				return;
			}
			
			setTimeout(function(){_collapse(elm,amount-h)},10);
		}
		
		var elms = e.getElementsByTagName('ul');
		if(typeof elms[0] == 'unedfined') return;
		
		var modelList = elms[0];	
		var title = CheckList._resolveListTitle(e);
		var vpList = DomHtml.getNodeViewport(modelList);
	
		modelList.style.borderBottom = '1px solid #CCC';
		_collapse(modelList,vpList['height']);
		title.className = 'titleClosed';
		CheckList._setState(e,CheckList.LSTATE.CLOSED);
	},
	
	_scrollBy : function(elm,amount){
		if(amount <= 0) return;
		 
		elm.scrollTop += 15;
		amount -= 15;
		
		var f = function(){CheckList._scrollBy(elm,amount);};
		setTimeout(f,10);
	},
	
	_state : function(e){
		e = CheckList._resolveParentListItem(e);
		if(e == null) return null;
		
		if(typeof CheckList.listItemStates[e.id] == 'undefined'){
			if(CheckList._isChecklist(e)) CheckList.listItemStates[e.id] = CheckList.LSTATE.OPEN;
			else CheckList.listItemStates[e.id] = CheckList.LSTATE.CLOSED;
		}
		return CheckList.listItemStates[e.id];
	},
	
	_setState : function(e, state){
		e = CheckList._resolveParentListItem(e);
		CheckList.listItemStates[e.id] = state;
	},
	
	_resolveListTitle : function(e){
		return e.getElementsByTagName('div')[0];
	},
	
	_resolveParentListItem : function(e){
		while(e){
			if(CheckList._isMainItem(e)) return e;
			else e = e.parentNode;
			
			if(e.nodeName.toLowerCase() == 'body') return null;
		}
		
		return null;
	},
	
	_isChecklist : function(e){
		return DomHtml.elementHasClass(e,'checkList');
	},
	
	_isMainItem : function(e){
		return DomHtml.elementHasClass(e,'mainItem');
	},
	
	_getMainCheckItem : function(e){
		var chks = DomHtml.getElementsByClassName(e,'mainCheck');
		return (typeof chks[0] != 'undefined')?chks[0]:null;
	},
	
	_getCheckItems : function(e){
		var chks = DomHtml.getElementsByClassName(e,'itemCheck');
		return chks;
	}
}