function FilterItem(item, itemTypes) {
	this.mItem = item;
	this.mItemTypes = itemTypes;
}

FilterItem.prototype.Match = function(itemType) {
    if (itemType.length == 0) {
        return true;
    } else {
	    return (this.mItemTypes.indexOf(';'+itemType+';') > -1);
	}
}

FilterItem.prototype.IsFiltered = function(filter) {
    return (this.mItem.className == filter.mShowItemCSS);
}


function SelectedFilter(filterItemID, filterType) {
	this.mFilterItemID = filterItemID;
	this.mFilterType = filterType;	
}


function Filter()
{
    this.mChildFilters = new Array();
    this.mFilters = new Array();
    this.mSelectedFilters = new Array();
    this.mFilterMenuItems = new Array();
    this.mParentFilter = null;

    this.mfnHoverHook = function(sender, hovering) {
        return(false);
    };
    
    this.mFilterPrefix = '';
    this.mFilterTypesCSS = '';
    this.mHideItemCSS = '';
    this.mMenuElementID = '';
    this.mNoFilterElementID = '';
    this.mNoFilterHideCSS = '' ;
    this.mNoFilterShowCSS = '' ;
    this.mSelectHeaderCSS = '';
    this.mSelectHeaderHoverCSS = '';
    this.mShowItemCSS = '';
    this.mUnselectHeaderCSS = '';
    this.mUnselectHeaderHoverCSS = '';
}

Filter.prototype.AddChild = function(childFilter, parentAdded) {
    this.mChildFilters.push(childFilter);
    if ( !parentAdded )
        childFilter.AddParent(this,true);
}

Filter.prototype.AddParent = function(parentFilter, childAdded) {
    this.mParentFilter = parentFilter;
    if ( !childAdded )
        parentFilter.AddChild(this,true);
}

Filter.prototype.Initialise = function(showItemCSS, hideItemCSS, 
        selectHeaderCSS, selectHeaderHoverCSS, unselectHeaderCSS, unselectHeaderHoverCSS,
        filterTypesCSS, menuElementID, filterPrefix, 
        noFilterElementID, noFilterShowCSS, noFilterHideCSS) {
        
    this.mFilterPrefix = filterPrefix;
    this.mFilterTypesCSS = filterTypesCSS;
    this.mHideItemCSS = hideItemCSS;
    this.mMenuElementID = menuElementID;
    this.mNoFilterElementID = noFilterElementID;
    this.mNoFilterHideCSS = noFilterHideCSS;
    this.mNoFilterShowCSS = noFilterShowCSS;
    this.mSelectHeaderCSS = selectHeaderCSS;
    this.mSelectHeaderHoverCSS = selectHeaderHoverCSS;
    this.mShowItemCSS = showItemCSS;
    this.mUnselectHeaderCSS = unselectHeaderCSS;
    this.mUnselectHeaderHoverCSS = unselectHeaderHoverCSS;

    var items = document.getElementsByTagName('span');
    var filter;
    for (var i = 0 ; i < items.length ; i++) {
        if (items[i].className == this.mFilterTypesCSS) {
            filter = new FilterItem(items[i].parentNode,items[i].innerHTML);
			this.mFilters.push(filter);
        }
    }
	
	itemHTML = document.getElementById(this.mMenuElementID);
	if ( itemHTML ) {
		var prefixLen = this.mFilterPrefix.length;
		this.LocateMenuEntries(itemHTML,prefixLen);
	}
}

Filter.prototype.LocateMenuEntries = function(itemHTML,prefixLen) {
	if ( itemHTML ) {
		var nodes;
		
		if ( itemHTML.children ) {
			nodes = itemHTML.children;
		} else {
			nodes = itemHTML.childNodes;
		}
		
		for ( var i = 0 ; i < nodes.length; i++ ) {
			if ( nodes[i].id ) {
				if ( (nodes[i].id.length >= prefixLen) && (nodes[i].id.substr(0,prefixLen) == this.mFilterPrefix) )
					this.mFilterMenuItems.push(nodes[i].id);
			}
			this.LocateMenuEntries(nodes[i],prefixLen);
		}
	}
}


Filter.prototype.ChangeState = function(sender, itemID, trackingURL) {
	var tag;
	var tagID;
	tagID = this.mFilterPrefix+itemID;
	for (var i=0; i < this.mFilterMenuItems.length; i++) {
		tag = document.getElementById(this.mFilterMenuItems[i])
		if (tag){
			if(tag.id == tagID) {
				tag.className=this.mSelectHeaderCSS;
			}else{
				tag.className=this.mUnselectHeaderCSS;
			}
		}
	}
	this.SetFilter([itemID]);
	TrackURL(trackingURL);
}

Filter.prototype.ToggleState = function (sender,itemID) {
	var tag;
	tag=document.getElementById(this.mFilterPrefix+itemID);
	if (tag) {
		switch (tag.className)
		{
		    case this.mUnselectHeaderCSS:
		    case this.mUnselectHeaderHoverCSS:
    			tag.className=selectHeaderCSS;
	    		this.AddFilter(itemID);
	    		break;
	    		
	    	case this.mSelectHeaderCSS:
	    	case this.mSelectHeaderHoverCSS:
    			tag.className=unselectHeaderCSS;
	    		this.RemoveFilter(itemID);
		}
	}	
}

Filter.prototype.AddFilter = function(filterID) {
	this.mSelectedFilters.push(filterID);
	this.FilterItems();
}

Filter.prototype.RemoveFilter = function(filterID) {
	var updatedFilters = new Array(0);
	for (var i = 0 ; i < this.mSelectedFilters.length ; i++) {
		if (this.mSelectedFilters[i] != filterID) {
			updatedFilters.push(this.mSelectedFilters[i])
		}
	}
	this.mSelectedFilters = updatedFilters;
	this.FilterItems();
}

Filter.prototype.SetFilter = function (filterList) {
	this.mSelectedFilters = filterList;
	this.FilterItems();
}

Filter.prototype.FilterItems = function(selective) {
	var s = new String();
	var tag;

	for ( var i = 0 ; i < this.mSelectedFilters.length ; i++ ) {
		s += ';' + this.mSelectedFilters[i];
	}
	if ( s.length > 0 )
	    s += ';';
	tag = document.getElementById('debug');
	if ( tag )
	    tag.innerHTML=s;

	for ( var i = 0 ; i < this.mFilters.length; i++ ) {
		var matched = true;

        if ( !selective || this.mFilters[i].IsFiltered(this) ) {
		    for (var j = 0 ; j < this.mSelectedFilters.length ; j++) {
			    if (!this.mFilters[i].Match(this.mSelectedFilters[j])) {
				    matched = false;
				    break;
			    }
			}
		    if (matched) {
			    this.mFilters[i].mItem.className = this.mShowItemCSS;
		    } else {
			    this.mFilters[i].mItem.className = this.mHideItemCSS;
		    }
		}
	}
	
	if ( !selective )
	{
	    this.FilterDown();
	    this.FilterUp();
	}
	
	if ( this.mNoFilterElementID.length > 0 ) {
	    var count = 0;

	    for ( var i = 0 ; i < this.mFilters.length; i++ ) {
            if ( this.mFilters[i].IsFiltered(this) )
                count++;
	    }
	    
        tag = document.getElementById(this.mNoFilterElementID);
        if ( tag ) {
            if ( count == 0 ) {
                tag.className = this.mNoFilterShowCSS;
            } else {
                tag.className = this.mNoFilterHideCSS;
            }
        }
    }
}

Filter.prototype.Hover = function (sender, hovering) {
    var newCSS;

    if ( !this.mfnHoverHook(sender, hovering) )
    {
        if ( hovering ) {
            switch( sender.className ) {
                case this.mSelectHeaderCSS:
                case this.mSelectHeaderHoverCSS:
                    newCSS = this.mSelectHeaderHoverCSS;
                    break;
                    
                case this.mUnselectHeaderCSS:
                case this.mUnselectHeaderHoverCSS:
                    newCSS = this.mUnselectHeaderHoverCSS;
                    break;
                    
                default:
                    newCSS = sender.className;
                    break;
            }
        } else {
            switch(sender.className) {
                case this.mSelectHeaderCSS:
                case this.mSelectHeaderHoverCSS:
                    newCSS = this.mSelectHeaderCSS;
                    break;
                    
                case this.mUnselectHeaderCSS:
                case this.mUnselectHeaderHoverCSS:
                    newCSS = this.mUnselectHeaderCSS;
                    break;
                    
                default:
                    newCSS = sender.className;
                    break;
            }
        }
        sender.className = newCSS;
    }
}

Filter.prototype.FilterDown = function() {
    for ( var i = 0; i < this.mChildFilters.length; i++ ) {
        this.mChildFilters[i].FilterItems(true);
        this.mChildFilters[i].FilterDown();
    }
}

Filter.prototype.FilterUp = function() {
    if ( this.mParentFilter ) {
        this.mParentFilter.FilterItems(true);
        this.mParentFilter.FilterUp();
    }
}