/*
	Category selection classes for selecting taxonomy categories from a tree
	generated by the SearchPortletUtils functions.
	Author: Sindri Traustason, Copyright 2005-2007 VYRE Ltd.
*/

/**
 * Category set is a array implementation of a set.
 * CategorySet.array never contains more than one instance of anything
 */
function CategorySet(){
	this.array = new Array(0);
}
CategorySet.prototype.contains = function(categoryId){
	for( var i=0; i < this.array.length; i=i+1 ){
		if(this.array[i]==categoryId){
			return true;
		}
	}
	return false;
};
CategorySet.prototype.add = function(categoryId){
	if(!this.contains(categoryId)){
		this.array.push(categoryId);
	}
};
CategorySet.prototype.remove = function(categoryId){
	var replacement = {};
	for( var i=0; i < this.array.length; i=i+1 ){
		if(this.array[i] == categoryId){
			this.array.splice(i, 1);
		}
	}
};
CategorySet.prototype.join = function(seperator){
	return this.array.join(seperator);
};

/**
 * CategorySelector manages selected categoies in a tree and
 * makes sure their ids are in a comma seperated string in the field
 * with id fieldId.
 */
function CategorySelector(namespace, tree, fieldId, tracerDivId, selectSingle){
	this.categoryIds = new CategorySet();
	this.namespace = namespace;
	this.tree = tree;
	this.fieldId = fieldId;
	this.tracerDivId = tracerDivId;
	this.rootName = namespace;
	this.selectSingle = selectSingle;
}

CategorySelector.prototype.init = function(array){
	this.categoryIds.array = (array.length == 1 && array[0] === "")?new Array():array;
	this.updateTracer();
	if(this.categoryIds.array.length > 0){
		this._colorTree(this.tree);
	}
};

CategorySelector.prototype._colorTree = function(xtreeNode){
	var categoryId = this._getId(xtreeNode);
	if(this.categoryIds.contains(categoryId)){
		this.color(categoryId);
		this._expandAncestors(xtreeNode);
	}
	for(var i = 0; i < xtreeNode.childNodes.length; i=i+1){
		this._colorTree(xtreeNode.childNodes[i]);
	}
};

CategorySelector.prototype.addOrRemoveCategory = function(categoryId, xtreeNode){
	if( !this.categoryIds.contains(categoryId) ){
		if(this.selectSingle){
			// remove all other selected categories
			this.clear();
		}
		// Add it but remove the children
		this._add(categoryId);
		this._removeDescendants(xtreeNode);
		this._removeAncestors(xtreeNode);
	} else {
		// Remove it
		this._remove(categoryId);
		this._removeDescendants(xtreeNode);
	}
	this.updateTracer();
	this.writeToForm();
};

CategorySelector.prototype.clear = function(){
	this._removeDescendants(this.tree);
	this.updateTracer();
	this.writeToForm();
};

CategorySelector.prototype._add = function(categoryId){
	//alert('adding ' + categoryId);
	this.categoryIds.add(categoryId);
	this.color(categoryId);
};

CategorySelector.prototype._remove = function(categoryId){
	//alert('removing ' + categoryId);
	this.categoryIds.remove(categoryId);
	this.uncolor(categoryId);
};

CategorySelector.prototype._removeDescendants = function(xtreeNode){
	for( var i=0; i < xtreeNode.childNodes.length; i=i+1){
		var childNode = xtreeNode.childNodes[i];
		var childId = this._getId(childNode);
		this._remove(childId);
		this._removeDescendants(childNode);
	}
};

CategorySelector.prototype._removeAncestors = function(xtreeNode){
	var ancestor = xtreeNode.parentNode;
	while(ancestor != undefined && ancestor.id != 'root'){
		this._remove(this._getId(ancestor));
		ancestor = ancestor.parentNode;
	}
};

CategorySelector.prototype._expandAncestors = function(xtreeNode){
	var ancestor = xtreeNode.parentNode;
	while(ancestor != undefined && ancestor.id != 'root'){
		ancestor.expand();
		ancestor = ancestor.parentNode;
	}
};

CategorySelector.prototype.color = function(categoryId){
	var xtreeDiv = document.getElementById( this.namespace + 'cat_' + categoryId);
	if(xtreeDiv != undefined){
		xtreeDiv.className = 'webfx-tree-item selected';
	}
};

CategorySelector.prototype.uncolor = function(categoryId){
	var xtreeDiv = document.getElementById( this.namespace + 'cat_' + categoryId);
	if(xtreeDiv != undefined){
		xtreeDiv.className = 'webfx-tree-item';
	}
};

CategorySelector.prototype.writeToForm = function(){
	var field = document.getElementById(this.fieldId);
	field.value = this.categoryIds.join(',');
};

CategorySelector.prototype.updateTracer = function(){
	if(document.getElementById(this.tracerDivId) != undefined){
		var html = "";
		if(this.categoryIds.array.length == 0){
			html = "(" + this.tree.text + ")";
		} else {
			for (var i = 0; i < this.categoryIds.array.length; i=i+1){
				html += "<span>"+ this._getTracer(this.categoryIds.array[i]) +"</span><br>";
			}
		}
		document.getElementById(this.tracerDivId).innerHTML = html;
	}
};

CategorySelector.prototype._getTracer = function(categoryId){
	var tracer = "";
	var category = this._getCategory(categoryId);
	while(category != undefined && category.id != 'root'){
		tracer = " &gt; " + category.text + tracer;
		category = category.parentNode;
	}
	return tracer;
};

CategorySelector.prototype._getCategory = function(categoryId, xtreeNode){
	if(xtreeNode == undefined){
		xtreeNode = this.tree;
	}
	if(categoryId == this._getId(xtreeNode)){
		return xtreeNode;
	} else for(var i = 0; i < xtreeNode.childNodes.length; i=i+1){
		var result = this._getCategory(categoryId, xtreeNode.childNodes[i]);
		if(result != null) return result;
	}
	return null;
};

CategorySelector.prototype._getId = function( xtreeNode ){
	return xtreeNode.id.replace( this.namespace + 'cat_', '');
};

/**
 * CategorySelector manages selected categoies in a checkbox tree and
 */
function CheckboxCategorySelector(tree, reverse){
	this.tree = tree;
	this.rootName = tree.id;
	this.reverse = reverse;
}

CheckboxCategorySelector.prototype.addOrRemoveCategory = function(xtreeNode){
	if(this.reverse){
		if( !xtreeNode.getChecked() ){
			this._removeAncestors(xtreeNode);
		} else {
			this._addDescendants(xtreeNode);
		}
	} else {
		if( !xtreeNode.getChecked() ){
			this._removeDescendants(xtreeNode);
		} else {
			this._addAncestors(xtreeNode);
		}
	}
};

CheckboxCategorySelector.prototype._removeDescendants = function(xtreeNode){
	for( var i=0; i < xtreeNode.childNodes.length; i=i+1){
		var childNode = xtreeNode.childNodes[i];
		var checkbox = document.getElementById("chckbx_" + childNode.id );
		if( checkbox.checked ){
			checkbox.checked = false
			this._removeDescendants(childNode);
		}
	}
};

CheckboxCategorySelector.prototype._addDescendants = function(xtreeNode){
	for( var i=0; i < xtreeNode.childNodes.length; i=i+1){
		var childNode = xtreeNode.childNodes[i];
		var checkbox = document.getElementById("chckbx_" + childNode.id );
		if( !checkbox.checked ){
			checkbox.checked = true
			this._addDescendants(childNode);
		}
	}
};

CheckboxCategorySelector.prototype._addAncestors = function(xtreeNode){
	var ancestor = xtreeNode.parentNode;
	while(ancestor != undefined && ancestor.id != this.rootName){
		document.getElementById("chckbx_" + ancestor.id ).checked = true
		ancestor = ancestor.parentNode;
	}
};

CheckboxCategorySelector.prototype._removeAncestors = function(xtreeNode){
	var ancestor = xtreeNode.parentNode;
	while(ancestor != undefined && ancestor.id != this.rootName){
		document.getElementById("chckbx_" + ancestor.id ).checked = false
		ancestor = ancestor.parentNode;
	}
};

