
var OTOS = window.OTOS || {};
OTOS.Tree = function () {

    return {

        /**
         * The id of the tree element
         */
        TREE_ID: 'navigationTree',


        /**
         * The image url of the node's add-image (when adding elements to the content)
         */
        TOGGLE_IMAGE_ADD:   'icons/arrow_right.gif',


        /**
         * The image url of the node's remove-image (when removing elements from the content)
         */
        TOGGLE_IMAGE_DEL:   'icons/arrow_left.gif',

        /**
         * Creates the navigation tree
         *
         * @param   {array}     treeNodes   An array containing all the first-level nodes as objects.
         *                                  The nodes can contain arrays of subnodes and so on.
         * @return  The generated tree element
         * @type    {element}
         */
        createTree: function (treeNodes) {

            var tree = Builder.node('ul', { id: OTOS.Tree.TREE_ID });

            for (var i = 0; i < treeNodes.length; i++) {
                tree.appendChild(OTOS.Tree.createTreeNode(treeNodes[i]));
            } // for

            return tree;

        },


        /**
         * Parses the serverData and generates an array containing the tree info, which then
         * can be passed directly to createTree.
         *
         * @param   {object}    serverData      Object containing information about the server. One property
         *                                      is 'cameras', which contain an array of camera-objects containing
         *                                      information about the camera. Camera-object has a property 'imageAreas',
         *                                      which contain an array of imageareas, which each has information about the
         *                                      imagearea.
         * @return  An array containing the tree info
         * @type    {array}
         */
        createTreeInfoArray: function (serverData) {

            var treeInfo = [];

            // go through all the servers

            for (var i in serverData) {

                var serverObj = { title:        serverData[i]['name'],
                                  subItems:     [],
                                  titleLink:    "OTOS.Server.showServer('" + i + "')",
                                  toggleLink:   "OTOS.Server.toggleServer('" + i + "')",
                                  id:           SERVER_LINK_ID_PREFIX + '_' + i,
                                  className:    'serverNode' };

                // go through all the cameras of the server

                for (var j in serverData[i]['cameras']) {

                    var camObj = { title:       serverData[i]['cameras'][j]['name'],
                                   subItems:    [],
                                   titleLink:   "OTOS.Camera.showCameraAndStatistics('" + i + "', '" + j + "')",
                                   toggleLink:  "OTOS.Camera.cameraInfo('" + i + "', '" + j + "', true)",
                                   id:          CAMERA_LINK_ID_PREFIX + '_' + j,
                                   className:  'cameraNode' };

                    // go through all the imageareas of the camera

                    for (var k in serverData[i]['cameras'][j]['imageAreas']) {

                        var area = serverData[i]['cameras'][j]['imageAreas'][k];

                        // the corresponding link is shown only if the area type is 0 and status is 1

                        if (area['type'] == 0 && area['status'] == 1) {
                            var areaObj = { title:      area['name'],
                                            subItems:   [],
                                            titleLink:  "OTOS.Statistics.showStatisticsOnly('" + i + "', '" + j + "', '" + k + "')",
                                            toggleLink: "OTOS.Statistics.toggleStatistics('" + i + "', '" + j + "', '" + k + "')",
                                            id:         STATISTICS_LINK_ID_PREFIX + '_' + k,
                                            className:  'statisticsNode' };
                        } // if

                        camObj['subItems'].push(areaObj);

                    } // for

                    serverObj['subItems'].push(camObj);

                } // for

                treeInfo.push(serverObj);

            } // for

            return treeInfo;

        },


        /**
         * Creates one tree node. If node has childnodes, it calls this function recursively.
         *
         * @param   {object}    obj     The node object
         * @return  The node element
         * @type    {element}
         */
        createTreeNode: function (obj) {

            var treeNode    = Builder.node('li', { id: obj['id'] }),
                title       = Builder.node('span', { className: 'title ' + obj['className'] }, [
                                    Builder.node('a', { href: 'javascript: void(0)' }, [ obj['title'] ])]),
                toggle      = Builder.node('span', { className: 'toggle' }, [
                                    Builder.node('a', { href: 'javascript: void(0)' }, [
                                        Builder.node('img', { src: OTOS.Tree.TOGGLE_IMAGE_ADD })])]);

            // if the node has childnodes, we'll create the expand-link

            if (obj['subItems'].length > 0) {

                treeNode.appendChild(Builder.node('span', { className: 'expand' }, [
                        Builder.node('a', { href: 'javascript: void(0)' }, [ '+' ])]));

                OTOS.Tree.createExpandLinkObserver(treeNode);

            } // if

            treeNode.appendChild(title);
            treeNode.appendChild(toggle);

            // if the node has childnodes, we'll create the childnodes by calling this function recursively

            if (obj['subItems'].length > 0) {

                var subItem = Builder.node('ul');

                for (var i = 0; i < obj['subItems'].length; i++) {
                    subItem.appendChild(OTOS.Tree.createTreeNode(obj['subItems'][i]));
                } // for

                treeNode.appendChild(subItem);

            } // if

            // event handlers

            OTOS.Tree.createTreeLinkObserver(title.firstChild, obj['titleLink']);
            OTOS.Tree.createTreeLinkObserver(toggle.firstChild, obj['toggleLink']);

            return treeNode;

        },


        /**
         * Creates the event observer for the node's expand-link's onclick-event
         *
         * @param   {element}   el  The node element
         */
        createExpandLinkObserver: function (el) {
            Event.observe(OTOS.Dom.getFirstChildByClassName('expand', el), 'click', function () {
                OTOS.Tree.toggleSubItems(el, null);
            });
        },


        /**
         * Creates the event observer for the node's treelink's (the node's text) onclick-event
         *
         * @param   {element}   el          The node element
         * @param   {function}  callback    The function to be called when the link is clicked
         */
        createTreeLinkObserver: function (el, callback) {
            Event.observe(el, 'click', function () { eval(callback); });
        },


        /**
         * Toggles the node's subitems
         *
         * @param   {element}   node    The node
         * @param   {mixed}     show    Can have values null, false and true. If the value is null, the
         *                              subitems are toggled (shown if hidden, and hidden if shown). If the
         *                              value is true, the subitems are shown and if the value is false,
         *                              the subitems are hidden. After the operation the togglelink in front
         *                              of the node is updated (changed from - to + or from + to -)
         */
        toggleSubItems: function (node, show) {

            var subItemList = node.getElementsByTagName('ul');

            if (subItemList.length > 0) {

                var subItems    = subItemList[0];
                    expandLink  = OTOS.Dom.getFirstChildByClassName('expand', node).firstChild.firstChild;

                if (show == null) {
                    Element.toggle(subItems);
                } else if (show == false) {
                    Element.hide(subItems);
                } else if (show == true){
                    Element.show(subItems);
                } // else

                expandLink.nodeValue = Element.visible(subItems) ? '-' : '+';

            } // if

        },


        /**
         * Function updates the browser in the navigation after the content area is cleared.
         * Because the content area is empty, we have to update all the minus signs to plus signs
         * (or the images if we're using them).
         */
        updateTree: function () {
            $A(document.getElementsByClassName('toggle', $(OTOS.Tree.TREE_ID))).each(function (item) {
                item.firstChild.firstChild.src = OTOS.Tree.TOGGLE_IMAGE_ADD;
            });
        },


        /**
         * Changes the image of the node's toggle link from ADD to DEL or from DEL to ADD,
         * depending on the situation.
         *
         * @param   {element}   node    The tree's node
         */
        changeToggleNodeValue: function (node) {

            if ($(OTOS.Tree.TREE_ID) !== undefined) {
                var toggleImg = OTOS.Dom.getFirstChildByClassName('toggle', node).firstChild.firstChild;
                toggleImg.src = toggleImg.src.indexOf(OTOS.Tree.TOGGLE_IMAGE_ADD) > -1
                                    ? OTOS.Tree.TOGGLE_IMAGE_DEL
                                    : OTOS.Tree.TOGGLE_IMAGE_ADD;
            } // if

        }

    };

}();
