
/**
 * TTreeNode
 */
var TTreeNode = TClass.extend({}, {

    /**
     * Constructor
     */
    initialize: function() {
        this.id = null;
        this.attributes = {};
        this.nodePointer = null;
        this.subNodes = new Array();
        this.subNodesCount = 0;
        this.parentId = null;
        this.isLastLeaf = false;
    },


    /**
     * Add node
     */
    addNode: function(nodeObj) {
        if (this.nodePointer) {
            this.nodePointer.isLastLeaf = false;
        }

        this.subNodes.push(nodeObj);
        this.subNodesCount++;
        nodeObj.zindex = this.subNodesCount;
        nodeObj.isLastLeaf = true;
        this.nodePointer = nodeObj;
    },


    /**
     * Find node
     */
    findNode: function(id) {
        if (this.id == id) {
            return this;
        }

        for (i in this.subNodes) {
             if (this.subNodes[i].id == id) {
                 return this.subNodes[i];
             }
             var temp = this.subNodes[i].findNode(id);
             if (temp != null) {
                 return temp;
             }
        }

        return null;
    },


    /**
     * Find node by attribute key-value pair
     */
    findNodeByAttrKey: function(key, value) {
        if (this.attributes[key] == value) {
            return this;
        }

        for (var i in this.subNodes) {
             if (this.subNodes[i].attributes[key] == value) {
                 return this.subNodes[i];
             }
             var temp = this.subNodes[i].findNodeByAttrKey(key, value);
             if (temp != null) {
                 return temp;
             }
        }

        return null;
    },


    /**
     * as string
     */
    asString: function() {
        return json_encode(this.attributes);
    }

});



/**
 * TTree
 */
var TTree = TClass.extend(TTreeNode, {

    /**
     * Constructor
     */
    initialize: function() {
        $C(TTreeNode).initialize.call(this);
    }
});



/**
 * TMenu
 */
var TMenu = TClass.extend(TWebControl, {

    /**
     * Constructor
     */
    initialize: function(name) {
        $C(TWebControl).initialize.call(this, name);

        this.tree = new TTree();
        this.value = null;

        this.pendingNodes = new Array();
        this.pendingNodesOpen = true;
    },


    /**
     * Set target frame
     */
    setTargetFrame: function(aTargetFrame) {
        this.fTargetFrame = aTargetFrame;
    },


    /**
     * Set target function
     */
    setTargetFunction: function(aTargetFunction) {
        this.fTargetFunction = aTargetFunction;
    },


    /**
     * Set cached icons
     */
    setCachedIcons: function(aCachedIcons) {
        if (aCachedIcons) {
            this.fCachedIcons += aCachedIcons;
        }
    },


    /**
     * Set root
     */
    setRoot: function(id, text) {
        this.tree = new TTree();
        this.tree.id = id;
        this.tree.attributes["text"] = text;
        this.tree.attributes["level"] = 0;
    },


    /**
     * Set items
     */
    setItems: function(aItems) {
        this.clearItems();
        for (var i=0; i<aItems.length; i++) {
            var obj = aItems[i];
            this.addItem(obj.id, obj.a, obj.p);
        }

        this.processPendingNodes();
    },


    /**
     * Add menu item
     */
    addItem: function(id, attributes, parentId) {
        if (!parentId || parentId == "") {
            this.tree = new TTree();
            this.tree.id = id;
            this.tree.attributes["text"] = attributes["text"];
            this.tree.attributes["level"] = 0;
            return;
        }

        parentNode = this.tree.findNode(parentId);

        if (parentNode) {
            node = new TTreeNode();
            node.id = id;
            node.parentId = parentId;
            for (key in attributes)
                 node.attributes[key] = attributes[key];
            node.attributes["level"] = parentNode.attributes["level"] + 1;
            parentNode.addNode(node);

            return true;
        }
        else if (this.pendingNodesOpen) {
            this.pendingNodes[this.pendingNodes.length] = {0 : id, 1 : attributes, 2 : parentId};
        }

        return false;
    },


    /**
     * Process pending nodes
     */
    processPendingNodes: function() {
        this.pendingNodesOpen = false;

        if (this.pendingNodes.length == 0) {
            return;
        }

        var temp = new Array();
        var counter = 0;
        for (i in this.pendingNodes) {
            if (this.addItem(this.pendingNodes[i][0], this.pendingNodes[i][1], this.pendingNodes[i][2])) {
                counter++;
            }
            else {
                temp[temp.length] = this.pendingNodes[i];
            }
        }

        this.pendingNodes = temp;

        if (counter > 0) {
            return counter + this.processPendingNodes();
        }

        return counter;
        
    },


    /**
     * Show pending nodes
     */
    showPendingNodes: function() {
        var str = "";
        for (i in this.pendingNodes) {
            str += this.pendingNodes[i][0] + "-" + this.pendingNodes[i][1] + "-" + this.pendingNodes[i][2]["text"] + "\n";
        }

        alert(str);
    },


    /**
     * Clear items
     */
    clearItems: function() {
        this.tree = new TTree();
        this.pendingNodes = new Array();
    },


    /**
     * Set value
     */
    setValue: function(value) {
        this.value = value;
    }

});