function MainCategory(id, name, url)
{
    this.id = id;
    this.name = name;
    this.url = url;
    this.children = [];
    this.root = null;
    this.parent = null;
    this.showing = false;
}

MainCategory.prototype.add = function(category)
{
    category.root = this.root;
    category.parent = this;
    this.children.push(category);
    this.root.categoryPathMapping.setItem(category.getPath(), category);
}

MainCategory.prototype.toggle = function()
{
    if (this.showing)
        this.hideChildren();
    else
        this.display();
        
    this.showing = !this.showing;
}

MainCategory.prototype.show = function()
{
    var listItem = $("#" + this.getListItemId());
    listItem.css( { "display" : "block" } );
}

MainCategory.prototype.display = function()
{
    this.setDisplayText();

    this.children.each(function(category)
    {
        category.show();
    });
}

MainCategory.prototype.setDisplayText = function()
{
    $("#" + this.getToggleAnchorId()).html("-");
}

// Hides the category completly.
MainCategory.prototype.hide = function()
{
    this.setHideText();
    
    var listItem = $("#" + this.getListItemId());
    listItem.css( { "display" : "none" } );

    this.children.each(function(category)
    {
        category.hide();
    });
}

MainCategory.prototype.setHideText = function()
{
    $("#" + this.getToggleAnchorId()).html("+");
}

// Only hides the children (including children of children and so on).
MainCategory.prototype.hideChildren = function()
{
    this.setHideText();

    this.children.each(function(child)
    {
        child.hide();
    }.bind(this));
}

MainCategory.prototype.hideRecursive = function()
{
    this.children.each(function(category)
    {
        this.hide(category);
    }.bind(this));
}

MainCategory.prototype.getPathId = function()
{
    var path = [];
    path.push(this.id);
    var compare = this.parent;
    
    while (compare != null)
    {
        path.push(compare.id);
        compare = compare.parent;
    }
    
    return path.reverse().join("_");
}

MainCategory.prototype.getPath = function()
{
    var path = [];
    path.push(this.id);
    var compare = this.parent;
    
    while (compare != null)
    {
        if (compare instanceof Root)
            break;
            
        path.push(compare.id);
        compare = compare.parent;
    }
    
    return path.reverse().join("-");
}

MainCategory.prototype.getLevel = function()
{
    var level = 0;
    var compare = this.parent;
    
    while (compare != null)
    {
        if (compare instanceof Root)
            break;
    
        level++;
        compare = compare.parent;
    }
    
    return level;
}

MainCategory.prototype.getListItemId = function()
{
    return (this.getPathId() + "_li");
}

MainCategory.prototype.getToggleAnchorId = function()
{
    return (this.getPathId() + "_a");
}

MainCategory.prototype.getToggleText = function()
{
    return "+";
}

MainCategory.prototype.getHtml = function()
{
    var sb = new StringBuilder();
    var cssClass = "";
    
    if (this.root.firstListItem)
    {
        cssClass = "first";
        this.root.firstListItem = false;
    }
    
    sb.append("<li" + (cssClass.length > 0 ? " class=\"" + cssClass + "\"" : "") + " id=\"" + this.getListItemId() + "\" style=\"" + this.getListItemStyle() + "\"><a style=\"float: left;\" href=\"" + this.url + "\">" + this.name + "</a>");
    
    if (this.children.length > 0)
    {
        sb.append("<div class=\"btnStandard btnToggleCategory floatLeft\">");
            sb.append("<a id=\"" + this.getToggleAnchorId() + "\" href=\"javascript:rssTreeHandler.toggleCategory('" + this.root.id + "', '" + this.getPath() + "')\">" + this.getToggleText() + "</a>");
        sb.append("</div>");
    }
    
    sb.append("</li>");
    
    this.children.each(function(child)
    {
        sb.append(child.getHtml());
    }.bind(this));
    
    return sb.getValue();
}

MainCategory.prototype.getListItemStyle = function()
{
    return ("display: block;");
}

function Category(id, name, url)
{
    this.base = MainCategory;
    this.base(id, name, url);
}
Category.prototype = new MainCategory;

Category.prototype.getListItemStyle = function()
{
    return ("padding-left:" + (this.getLevel() * 20) + "px;");
}

function Root(id, outputContainerId)
{
    this.id = id;
    this.outputContainerId = outputContainerId;
    this.children = [];
    this.categoryPathMapping = new HashMap();
    this.firstListItem = true;
}

Root.prototype.add = function(category)
{
    category.root = this;
    category.parent = this;
    this.children.push(category);
    this.categoryPathMapping.setItem(category.getPath(), category);
}

Root.prototype.getHtml = function()
{
    var sb = new StringBuilder();
    
    sb.append("<ul>");
        
    this.children.each(function(child)
    {
        sb.append(child.getHtml());
    }.bind(this));
    
    sb.append("</ul>");
    return sb.getValue();
}

Root.prototype.render = function()
{
     $("#" + this.outputContainerId).html(this.getHtml());
}

var rssTreeHandler =
{
    roots: [],
    rootMapping : new HashMap(),
    
    add: function(root)
    {
        this.roots.push(root);
        this.rootMapping.setItem(root.id, root);
        
        // Render the tree.
        root.render();
    },
    
    toggleCategory: function(rootId, categoryPath)
    {
        var root = this.rootMapping.getItem(rootId);
        
        if (root != null)
        {
            var category = root.categoryPathMapping.getItem(categoryPath);
            
            if (category != null)
                category.toggle();
        }
    }
};
