// class TreeNode
function TreeNode(userObject)
{
    this.childNodes     = [];
    this.userObject     = userObject;
    this.expanded       = false;
}

// public void addNode(TreeNode node);
TreeNode.prototype.addNode = function(node)
{
    if(node == null)
    {
        throw new Error("TreeNode.addChild() - parameter 'node' cannot be null");
    }
    
    if(node.parent)
    {
        node.parent.removeNode(node);
    }
    
    this.childNodes.push(node);
    node.parent = this;
}

// public void insertNode = function(index, node);
TreeNode.prototype.insertNode = function(index, node)
{
    if(node == null)
    {
        throw new Error("TreeNode.insertNode() - parameter 'node' cannot be null");
    } else if(index < 0 || index > this.childNodes.length)
    {
        throw new Error("TreeNode.insertNode(index = " + index + ") - index out of bounds");
    } else if(index == this.childNodes.length)
    {
        this.addNode(node);
    } else
    {
        for(var i = this.childNodes.length - 1; i >= index; i++)
        {
            this.childNodes[i + 1] = this.childNodes[i];
        }
        
        this.childNodes[index] = node;
        node.parent = this;
    }
}

// public void removeNode(TreeNode node);
TreeNode.prototype.removeNode = function(node)
{
    var index = this.getIndexOf(node);
    
    if(index != null)
    {
        this.childNodes.splice(index, 1);
        delete node.parent;
    }
    
    return (index != -1);
}

// public int getIndexOf();
TreeNode.prototype.getIndexOf = function(node)
{
    for(var i = 0; i < this.childNodes.length; i++)
    {
        if(this.childNodes[i] == node)
        {
            return i;
        }
    }
    
    return -1;
}

// public Node getNode(int index);
TreeNode.prototype.getNode = function(index)
{
    if(index < 0 || index >= this.childNodes.length)
    {
        throw new Error("TreeNode.getNode(index = " + index + ") - index out of bounds");
    } else
    {
        return this.childNodes[index];
    }
}

// public int getNodeCount();
TreeNode.prototype.getNodeCount = function()
{
    return this.childNodes.length;
}

// public Node getParent();
TreeNode.prototype.getParent = function()
{
    return this.parent;
}

// public Object getUserObject();
TreeNode.prototype.getUserObject = function()
{
    return this.userObject;
}

// public void setUserObject(Object object);
TreeNode.prototype.setUserObject = function(userObject)
{
    this.userObject = userObject;
}

// public boolean isLeaf();
TreeNode.prototype.isLeaf = function()
{
    return (this.childNodes.length == 0);
}

// public void setExpanded(boolean expanded);
TreeNode.prototype.setExpanded = function(expanded)
{
    this.expanded = expanded;
}

// public boolean isExpanded();
TreeNode.prototype.isExpanded = function()
{
    return this.expanded;
}
