
/**
 * Vytvoří instanci stromu.
 *
 * @param String id id nejvyššího elementu stromu
 */
function Tree(id)
{
	this.id = id;
	this.element = document.getElementById(id);
}
Tree.prototype =
{
	id : null,			// id stromu
	element : null,		// nejvyšší element stromu

	/**
	 * Provede různé akce v závislosti na stavu vybrané položky.
	 *
	 * @param HTMLInputElement element checkbox, na který bylo kliknuto
	 */
	checkNode : function(element)
	{
		this.checkChildren(element);
		this.checkSameValue(element);
		this.checkParent(element);
	},

	/**
	 * Zaškrtne/odškrtne všechny děti.
	 *
	 * @param HTMLInputElement element checkbox, na který bylo kliknuto
	 */
	checkChildren : function(element)
	{
		var childNodes = element.parentNode.getElementsByTagName('input');
		if (childNodes.length > 1) {
			for (var i = 1; i < childNodes.length; i++) {
				childNodes[i].checked = element.checked;
			}
		}
	},
	
	/**
	 * Filter na pozadovane tagy, jelikoz FF vraci take prazdne radky jako elementy
	 * je potreba tyto odstranit a vratit dle nazvu tagu opravdu pouze tagy pozadovane.
	 * 
	 * @param obj - pole s elementy
	 * @param tag - nazev elementu ktere chceme vratit
	 */
	filterTag:function(obj, tag){
		var result = new Array();
		var j = 0;
		
		for(var i=0;i<obj.length;i++){
			if (obj[i].tagName == tag.toUpperCase()) {
				result[j++] = obj[i];
			}
		}
		return result;
	},

	/**
	 * Zaškrtne rodiče, pokud jsou zaškrnuty všechny děti.
	 *
	 * @param HTMLInputElement element checkbox, na který bylo kliknuto
	 */
	checkParent : function(element)
	{
		var parentUl = element.parentNode.parentNode;
		var childrenLi = this.filterTag(parentUl.childNodes, 'li');
		var childrenLiInputs = this.filterTag(childrenLi[0].getElementsByTagName('input'), 'input');
		var childrenState = childrenLiInputs[0].checked;
		var allSame = true;
		var temp = false;

		for (var i = 1; i < childrenLi.length; i++) {
			temp = this.filterTag(childrenLi[i].getElementsByTagName('input'), 'input');
			if (temp[0].checked != childrenState) {
			    allSame = false;
			    break;
			}
		}

		temp = this.filterTag(parentUl.parentNode.getElementsByTagName('input'), 'input');
		var parentInput = temp[0];
		// bylo kliknuto na hlavni kategorie, ktere nemaji rodice, ukoncime script
		if (parentUl.parentNode.tagName != 'LI') return false; 
		
		var previousState = parentInput.checked;
	    parentInput.checked = (allSame) ? childrenState : false;

		// pokud nejsme na vrcholu stromu a změnil se stav, tak pokračujeme do vyšší úrovně
		if ((parentUl != this.element) && (previousState != parentInput.checked)) {
			this.checkParent(parentUl);
		}
	},

	/**
	 * Zaškrtne/odškrtne všechny položky se stejnou hodnotou.
	 *
	 * @param HTMLInputElement element checkbox, na který bylo kliknuto
	 */
	checkSameValue : function(element)
	{
		var inputList = this.element.getElementsByTagName('input');
		for (i = 0; i < inputList.length; i++) {
			if (inputList[i].getAttribute('value') == element.getAttribute('value')) {
				inputList[i].checked = element.checked;
			}
		}
	}
}

/**
 * Otevře/skryje podstrom.
 *
 * @param HTMLElement element element obsluhuje otvírání/zavírání
 * @param String url url, ze které se načte obsah
 */
Tree.openCloseSubtree = function(element, url)
{
	var plus = (element.className.indexOf('plus') != -1);

	ulList = element.parentNode.getElementsByTagName('ul');
	if (plus) {
		if (ulList.length < 1) {
			var ajax = new Ajax();
			if (ajax == null) {
				return false;
			}

			var ul = document.createElement('ul');
			element.parentNode.appendChild(ul);
			ul.innerHTML = '<li class="loading"><span>Loading...</span></li>';

			ajax.open('GET', url, true);
			ajax.onreadystatechange = function()
			{
				if ((ajax.readyState == 4) && (ajax.status == 200)) {
					ul.innerHTML = ajax.responseText;
					element.className = element.className.replace(/plus/, 'minus');

					// zaškrtne děti
					inputList = element.parentNode.getElementsByTagName('input');
					var childNodes = ul.getElementsByTagName('input');
					if (childNodes.length > 0) {
						for (i = 0; i < childNodes.length; i++) {
							childNodes[i].checked = inputList[0].checked;
						}
					}
				}
			}
			ajax.send(null);
		} else {
			ulList[0].className = 'block';
			element.className = element.className.replace(/plus/, 'minus');
		}
	} else {
		ulList[0].className = 'hidden';
		element.className = element.className.replace(/minus/, 'plus');
	}
}

/**
 * Otevře postupně větev stromu.
 *
 * @param String url url, ze které se bude větev načítat (např. /tree?node=%nodeId)
 * @param String branch větev, která se má načíst (např. 0.2.5.8.14.22)
 */
Tree.openBranch = function(url, branch)
{
    var nodeList = branch.split('.');
	var nodeId = nodeList[0];
	var nodeUrl = url.replace(/%nodeId/, nodeId);

	var node = document.getElementById('node' + nodeId);
	var ul = document.createElement('ul');
	node.parentNode.appendChild(ul);
	ul.innerHTML = '<li class="loading"><span>Loading...</span></li>';

	var ajax = new Ajax();
	if (ajax == null) {
		return false;
	}

	ajax.open('GET', nodeUrl, true);
	ajax.onreadystatechange = function()
	{
		if ((ajax.readyState == 4) && (ajax.status == 200)) {
			node.className = node.className.replace(/plus/, 'minus');
			ul.innerHTML = ajax.responseText;

			nodeList.shift();
			if (nodeList.length > 0) {
			    Tree.openBranch(url, nodeList.join('.'));
			}
		}
	}
	ajax.send(null);
}
