/*
 * Content-seperated javascript tree widget
 * Copyright (C) 2005 SilverStripe Limited
 * Feel free to use this on your websites, but please leave this message in the fies
 * http://www.silverstripe.com/blog
 * Portions (C) 2009, JetBrains, inc.
 * http://www.jetbrains.com
 */


//Some stuff to make an iframe/parent works easier
document.currentSelection = null;
document.highlightMenuSelection = highlightMenuSelection;
document.initTree = initTree;
document.getMain = function() {
    var e = Ext.get("main");
    if (e) {
        var s = e.dom.src.split("/");
        return s[s.length - 1];
    }
    return "";
};
var prefix = "_tocItem";

function highlightMenuSelection(i) {
    var p = document.location.href.split("?")[1];
    if (p) {
        //Check for ReSharper call which is different from that of IDEA.
        if (p.toLowerCase().indexOf("keyword=") != -1) p = p.split("=")[1];
    }
    i = (i) ? i : (p) ? p : document.getElementById("featureTree").getElementsByTagName("li").item(0).getElementsByTagName("a").item(0).id;
    if (i.indexOf(prefix) < 0) i = prefix + i;
    var e = document.getElementById(i);
    if (e) {
        if (document.currentSelection) {
            if (document.currentSelection.id !== e.id) {
                document.currentSelection.style.color = "blue";
                document.currentSelection.style.background = "white";
            } else return;
        }
        document.currentSelection = e;
        document.currentSelection.style.color = "white";
        document.currentSelection.style.background = "black";
        document.currentSelection.scrollIntoView();
        if (document.getMain() != e.rel) Ext.get('main').dom.src = e.rel;
    }
}

function SendSearchRequest(s) {
    if (s) {
        if (s.length > 0) {
            var xmlHttp;
            xmlHttp = createXmlHttp();
            if (xmlHttp) {
                xmlHttp.onreadystatechange = function () {
                    if (xmlHttp.readyState == 4) {
                        if (xmlHttp.status < 300) {
                            Ext.get('searchResults').dom.innerHTML = xmlHttp.responseText;
                        }
                    }
                };
                Ext.get('searchResults').dom.innerHTML = "Searching for: <i>" + s + "</i>";
                xmlHttp.open("GET", getWebPath() + "search.jsp?q=" + s, true);
                xmlHttp.send(null);
            }
        }
    }
}

function syncNavigationToContent(i) {
    if (i.indexOf(prefix) < 0) i = prefix + i;
    var ul = parent.document.getElementById("featureTree");
    if (ul) {
        //We're open in a view with TOC, so let's sync it to our location.
        if (parent.document.currentSelection) {
            //We're already in sync, quit
            if (parent.document.currentSelection.id == i) return;
        }
        if (parent.document.getElementById(i)) {
            //TOC already contains an element we can sync with, call a highlighter on it.
            parent.document.highlightMenuSelection(i);
        } else {
            //Otherwise, query server to get missing TOC elements
            var xmlHttp = createXmlHttp();
            if (xmlHttp) {
                xmlHttp.onreadystatechange = function () {
                    if (xmlHttp.readyState == 4) {
                        if (xmlHttp.status < 300) {
                            //Elements received, put'em in appropriate place.
                            ul.innerHTML = xmlHttp.responseText;
                            //Call default tree builder on newly received elements.
                            parent.document.initTree(ul.getElementsByTagName("ul").item(0));
                            //And make sure highlighting goes there, too.
                            parent.document.highlightMenuSelection(i);
                        }
                    }
                };
                xmlHttp.open("GET", getWebPath() + "getHelp.jsp?a=" + i.replace(prefix, ""), true);
                xmlHttp.send(null);
            }
        }
    } else {
        //Display a link that can take you to this page with TOC.
        var nav = document.getElementById("_tdNavigator");
        nav.innerHTML = "<a href='" + getWebPath() + "?" + i.replace(prefix, "") + "' style='color:red;'>Click here to show Table of Contents</a>";
        // Hide a permalink link so that it does not duplicate what's already in an addressbar.
        document.getElementById("_permalink").style.display = "none";
    }
}

function autoInit_trees() {
    var candidates = document.getElementsByTagName('ul');
    for (var i = 0; i < candidates.length; i++) {
        if (candidates[i].className && candidates[i].className.indexOf('tree') != -1) {
            initTree(candidates[i]);
            candidates[i].className = candidates[i].className.replace(/ ?unformatted ?/, ' ');
        }
    }
}
/*
 * Initialise a tree node, converting all its LIs appropriately
 */
function initTree(el) {
    var i,j;
    var spanA, spanB, spanC;
    var startingPoint, stoppingPoint, childUL;
    // Find all LIs to process
    for (i = 0; i < el.childNodes.length; i++) {
        if (el.childNodes[i].tagName && el.childNodes[i].tagName.toLowerCase() == 'li') {
            var li = el.childNodes[i];

            // Create our extra spans
            spanA = document.createElement('span');
            spanB = document.createElement('span');
            spanC = document.createElement('span');

            var browser = navigator.userAgent;
            if (browser.indexOf("MSIE") > -1 || browser.indexOf("Safari") > -1) spanB.innerHTML = '&thinsp;';
            spanA.appendChild(spanB);
            spanA.appendChild(spanC);

            //			spanA.className = 'a ' + li.className.replace('closed','spanClosed');
            spanA.className = 'a ' + li.className.replace('closed', 'spanClosed');
            spanA.onMouseOver = function() {
            };
            spanB.className = 'b';
            spanB.onclick = treeToggle;
            spanC.className = 'c';

            // Find the UL within the LI, if it exists
            stoppingPoint = li.childNodes.length;
            startingPoint = 0;
            childUL = null;
            for (j = 0; j < li.childNodes.length; j++) {
                if (li.childNodes[j].tagName && li.childNodes[j].tagName.toLowerCase() == 'div') {
                    startingPoint = j + 1;
                    continue;
                }

                if (li.childNodes[j].tagName && li.childNodes[j].tagName.toLowerCase() == 'ul') {
                    childUL = li.childNodes[j];
                    stoppingPoint = j;
                    break;
                }
            }

            // Move all the nodes up until that point into spanC
            for (j = startingPoint; j < stoppingPoint; j++) {
                spanC.appendChild(li.childNodes[startingPoint]);
            }

            // Insert the outermost extra span into the tree
            if (li.childNodes.length > startingPoint) li.insertBefore(spanA, li.childNodes[startingPoint]);
            else li.appendChild(spanA);

            // Process the children
            if (childUL != null) {
                if (initTree(childUL)) {
                    addClass(li, 'children', 'closed');
                    addClass(spanA, 'children', 'spanClosed');
                }
            }
        }
    }
    if (li) {
        // li and spanA will still be set to the last item
        addClass(li, 'last', 'closed');
        addClass(spanA, 'last', 'spanClosed');
        return true;
    } else {
        return false;
    }

}
/*
 * +/- toggle the tree, where el is the <span class="b"> node
 * force, will force it to "open" or "close"
 */
function treeToggle(el, force) {
    el = this;
    while (el != null && (!el.tagName || el.tagName.toLowerCase() != "li")) {
        el = el.parentNode;
    }

    // Get UL within the LI
    var childSet = findChildWithTag(el, 'ul');
    var topSpan = findChildWithTag(el, 'span');

    if (force != null) {

        if (force == "open") {
            treeOpen(topSpan, el);
        }
        else if (force == "close") {
            treeClose(topSpan, el);
        }
    }

    else if (childSet != null) {
        var li = childSet.getElementsByTagName("li").item(0);
        // Is open, close it
        if (!el.className.match(/(^| )closed($| )/)) {
            treeClose(topSpan, el);
            // Is closed, open it
        } else {
            //It's empty, send query to server to get its content.
            treeOpen(topSpan, el);
            if (li.innerHTML.indexOf("Loading...") != -1) {
                var xmlHttp = createXmlHttp();
                if (xmlHttp) {
                    xmlHttp.onreadystatechange = function () {
                        if (xmlHttp.readyState == 4) {
                            if (xmlHttp.status < 300) {
                                childSet.innerHTML = xmlHttp.responseText;
                                initTree(childSet);
                            }
                        }
                    };
                    xmlHttp.open("GET", getWebPath() + "getHelp.jsp?i=" + li.id, true);
                    xmlHttp.send(null);
                }
            }

        }
    }
}
function treeOpen(a, b) {
    removeClass(a, 'spanClosed');
    removeClass(b, 'closed');
}
function treeClose(a, b) {
    addClass(a, 'spanClosed');
    addClass(b, 'closed');
}
/*
 * Find the a child of el of type tag
 */
function findChildWithTag(el, tag) {
    for (var i = 0; i < el.childNodes.length; i++) {
        if (el.childNodes[i].tagName != null && el.childNodes[i].tagName.toLowerCase() == tag) {
            return el.childNodes[i];

        }
    }
    return null;
}
/*
 * Functions to add and remove class names
 * Mac IE hates unnecessary spaces
 */
function addClass(el, cls, forceBefore) {
    if (forceBefore != null && el.className.match(new RegExp('(^| )' + forceBefore))) {
        el.className = el.className.replace(new RegExp("( |^)" + forceBefore), '$1' + cls + ' ' + forceBefore);

    } else if (!el.className.match(new RegExp('(^| )' + cls + '($| )'))) {
        el.className += ' ' + cls;
        el.className = el.className.replace(/(^ +)|( +$)/g, '');
    }
}
function removeClass(el, cls) {
    var old = el.className;
    var newCls = ' ' + el.className + ' ';
    newCls = newCls.replace(new RegExp(' (' + cls + ' +)+', 'g'), ' ');
    el.className = newCls.replace(/(^ +)|( +$)/g, '');
}
Behaviour.addLoadEvent(autoInit_trees);

/*custom functions*/
function isDOMsupported() {
    var returnValue = false;
    if (document.getElementById && document.getElementsByTagName && document.createTextNode) {
        returnValue = true;
    }
    return returnValue;
}
/**
 * 0/1 to expand or collapse the tree
 * @param param
 */

function ExpandCollapse(param) {
    var li = document.getElementsByTagName("li");
    var span = document.getElementsByTagName("span");
    for (var i = 0; i < li.length; i++) {
        if (param == 1) {
            removeClass(li[i], 'closed');
        }
        if (param == 0) {
            addClass(li[i], 'closed', false);
        }
    }
    for (i = 0; i < span.length; i++) {
        if (param == 1)
            removeClass(span[i], 'spanClosed');
    }
    for (i = 0; i < span.length; i++) {
        if (param == 0)
            addClass(span[i], 'spanClosed', false);
    }

}

//Code below brings AJAX functionality to speed up tree loading.

function createXmlHttp() {
    var xmlHttp;
    try {
        xmlHttp = new XMLHttpRequest();
    }
    catch (e) {
        try {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {
                return null;
            }
        }
    }
    return xmlHttp;
}

// Returns the current page location from address bar.
function getWebPath() {
    var p = document.location.href.split("/");
    p.splice(p.length - 1, 1);
    return p.join("/") + "/";
}
