if (typeof(sonar) != "object" || sonar == null) sonar = {};
if (typeof(sonar.module) != "object" || sonar.module == null) sonar.module = {};
//==============================================================================
// @library
//      sonar.module.menu
// @functions
//      createMenu(uri, args)
// @required
//      sonar.element
//      sonar.event
//      sonar.external
//==============================================================================
sonar.module.menu =
{
    /***************************************************************************
     * @function
     *      createMenu(uri, args)
     * @arguments
     *      parentID                     ==> (document.body)
     *      rootTag                      ==> ("menu")
     *      itemTag                      ==> ("item")
     *      cssPrefix                    ==> ()
     *      createOption
     *          selectedIndex            ==> (-1)
     *          displayType              ==> "self" | "skip" | "sibling" | ("all")
     *          useEvent                 ==> true | (false)
     *      onCreateItem(node, li, p, a) ==> ()
     * @used
     *      sonar.element.getChildElementsByTagName(oid, tag)
     *      sonar.event.addEvent(oid, name, func)
     *      sonar.event.validateEvent(thisObj, event)
     *      sonar.external.loadXML(uri)
     **************************************************************************/
    createMenu : function(uri, args)
    {
        var m_document = null;
        var m_root     = null;
        var m_select   = [];

        //Inner Initialize Function
        var initializeFunc = function()
        {
            uri  = typeof(uri) == "string" && uri.length > 0 ? uri : null;
            args = typeof(args) == "object" && args != null ? args : {};

            if (uri)
            {
                args.parentID     = typeof(args.parentID) == "object" && args.parentID != null && args.parentID.nodeType == 1 ? args.parentID : document.getElementById(args.parentID);
                args.rootTag      = typeof(args.rootTag) == "string" && args.rootTag.length > 0 ? args.rootTag.toLowerCase() : "menu";
                args.itemTag      = typeof(args.itemTag) == "string" && args.itemTag.length > 0 ? args.itemTag.toLowerCase() : "item";
                args.cssPrefix    = typeof(args.cssPrefix) == "string" && args.cssPrefix.length > 0 ? args.cssPrefix : null;
                args.createOption = typeof(args.createOption) == "object" && args.createOption != null && args.createOption.constructor == Array ? args.createOption : [];
                args.onCreateItem = typeof(args.onCreateItem) == "function" && (!Function.prototype.call || typeof(args.onCreateItem.call) == "function") ? args.onCreateItem : null;

                for (var i = 0; i < args.createOption.length; i++)
                {
                    args.createOption[i].selectedIndex = /^[0-9]+$/.test(args.createOption[i].selectedIndex) ? parseInt(args.createOption[i].selectedIndex) : -1;
                    args.createOption[i].displayType   = /^self|skip|sibling|all$/i.test(args.createOption[i].displayType) ? args.createOption[i].displayType.toLowerCase() : "all";
                    args.createOption[i].useEvent      = /^true$/i.test(args.createOption[i].useEvent);
                }

                if (!args.parentID) args.parentID = document.body;
            }
        }();

        //Inner CreateItem Function
        var createItemFunc = function(node, useEvent)
        {
            var li = document.createElement("li");
            var p  = li.appendChild(document.createElement("p"));
            var a  = p.appendChild(document.createElement("a"));

            if (args.onCreateItem) {
                if (args.onCreateItem(node, li, p, a) == false) return null;
            }
            else {
                a.href   = node.getAttribute("link");
                a.target = node.getAttribute("target");
                a.alt    = node.getAttribute("text");
                a.appendChild(document.createTextNode(a.alt));
            }

            if (useEvent) {
                sonar.event.addEvent(li, "onmouseover", function(e)
                {
                    var evt = e || window.event;

                    if (sonar.event.validateEvent(li, evt))
                    {
                        var sibling = li.parentNode.childNodes;

                        for (var i=0; i<sibling.length; i++)
                        {
                            var sub = sonar.element.getChildElementsByTagName(sibling[i], "ul")[0];

                            if (sub) sub.style.display = sibling[i] == li ? "" : "none";
                        }
                    }

                    evt.cancelBubble = true;
                });

                sonar.event.addEvent(li, "onmouseout", function(e)
                {
                    var evt = e || window.event;

                    if (sonar.event.validateEvent(li, evt))
                    {
                        var sub = sonar.element.getChildElementsByTagName(li, "ul")[0];

                        if (sub) sub.style.display = "none";
                    }

                    evt.cancelBubble = true;
                });
            }

            return li;
        }

        //Inner Transform Function
        var transformFunc = function(node, obj, depth)
        {
            var children = sonar.element.getChildElementsByTagName(node, args.itemTag);
            var ul       = document.createElement("ul");
            var li       = null;

            if (args.createOption.length > 0)
            {
                var selectedIndex = args.createOption[depth].selectedIndex;
                var displayType   = args.createOption[depth].displayType;
                var useEvent      = args.createOption[depth].useEvent;

                switch (displayType)
                {
                    case "self":
                        if (node == m_select[depth-1])
                        {
                            if (selectedIndex > -1 && selectedIndex < children.length)
                            {
                                li = createItemFunc(children[selectedIndex], useEvent);

                                if (li)
                                {
                                    ul.appendChild(li);

                                    if (args.createOption.length > depth+1 && children[selectedIndex].hasChildNodes())
                                    {
                                        transformFunc(children[selectedIndex], li, depth+1);
                                    }
                                }
                            }
                        }
                        break;

                    case "skip":
                        if (node == m_select[depth-1])
                        {
                            if (selectedIndex > -1 && selectedIndex < children.length)
                            {
                                if (args.createOption.length > depth+1 && children[selectedIndex].hasChildNodes())
                                {
                                    transformFunc(children[selectedIndex], obj, depth+1);
                                }
                            }
                        }
                        break;

                    case "sibling":
                        if (node == m_select[depth-1])
                        {
                            for (var i = 0; i < children.length; i++)
                            {
                                li = createItemFunc(children[i], useEvent);

                                if (li)
                                {
                                    ul.appendChild(li);

                                    if (args.createOption.length > depth+1 && children[i].hasChildNodes())
                                    {
                                        transformFunc(children[i], li, depth+1);
                                    }
                                }
                            }
                        }
                        break;

                    case "all":
                        for (var i = 0; i < children.length; i++)
                        {
                            li = createItemFunc(children[i], useEvent);

                            if (li)
                            {
                                ul.appendChild(li);

                                if (args.createOption.length > depth+1 && children[i].hasChildNodes())
                                {
                                    transformFunc(children[i], li, depth+1);

                                    if (useEvent && children[i] != m_select[depth])
                                    {
                                        var sub = sonar.element.getChildElementsByTagName(li, "ul")[0];

                                        if (sub) sub.style.display = "none";
                                    }
                                }
                            }
                        }
                        break;
                }
            }
            else
            {
                for (var i = 0; i < children.length; i++)
                {
                    li = createItemFunc(children[i], false);

                    if (li)
                    {
                        ul.appendChild(li);

                        if (children[i].hasChildNodes())
                        {
                            transformFunc(children[i], li, depth+1);
                        }
                    }
                }
            }

            if (ul.hasChildNodes())
            {
                if (args.cssPrefix != null) ul.className = args.cssPrefix + (depth+1);

                obj.appendChild(ul);
            }
        }

        //Inner Main Function
        var mainFunc = function()
        {
            if (uri)
            {
                //m_document = sonar.external.loadAjaxSync(uri, { responseType : "xml" }); //For Web Server
                m_document = sonar.external.loadXML(uri); //For Local System
                m_root     = m_document ? sonar.element.getChildElementsByTagName(m_document, args.rootTag)[0] : null;

                if (m_root && m_root.hasChildNodes())
                {
                    m_select[-1] = m_root;

                    for (var i = 0; i < args.createOption.length; i++)
                    {
                        var children = sonar.element.getChildElementsByTagName(m_select[i-1], args.itemTag);
                        var index    = args.createOption[i].selectedIndex;

                        if (children && index > -1 && index < children.length)
                        {
                            children[index].setAttribute("selected", true);

                            m_select[i] = children[index];
                        }
                    }

                    transformFunc(m_root, args.parentID, 0);
                }
            }
        }();
    }
}