/**
 * Javascript-Funktionen fuer den Zugriff auf den TopicTree
 * Author:  <a href="mailto:vsctech@fiz-chemie.de>Eike Jordan</a>
 *
 * Benoetigt: DOMUtil.js
 *            chemgapedia_common.js
 * state: beta
 *
 * $HeadURL: http://trac.gruen.fiz-chemie.de/svn/vs/vscms/trunk/src/vsengine/static/javascript/topicsAPI.js $
 * $Revision: 10994 $
 *
 * Copyright 2001-2006 FIZ CHEMIE Berlin
 */

/**
 * Logger configuration
 */
if (typeof logger == 'undefined') {
    var logger = log4javascript.getLogger("control");
    var layout = new log4javascript.PatternLayout("[%-5p] %m");
    var appender = new log4javascript.PopUpAppender(layout);
    log4javascript.setEnabled(false);
    appender.setThreshold(log4javascript.Level.DEBUG);
    logger.addAppender(appender);
} else {
    try {
        throw new Error("logger already installed.");
    } catch(e) {
        logger.trace(e.message + " " + e.fileName + ", " + e.lineNumber);
    }
};

/**
 * Container for requested items.
 * Replace with topics.js if no AJAX is possible
 */
var Topics = {};
/**
 * TopicTree Class Object
 */
var topicTree = {};

/**
 * Filter for meta information from Topics
 */
topicTree.isValidName = function(nodeName) {
    var isValid = false;
    if (nodeName != 'translations' && nodeName != 'length' && nodeName != 'key') {
        isValid = true;
    }
    return isValid;
};

/**
 * @title A String subject:area:specialism
 * Returns a normalized Array of
 * ["subject", "area", "specialism"]
 * Missing parts are set to null
 */
topicTree.getTitles = function/*Array*/(/*String*/title) {
    var topicsArray = new Array();
    var titles = title.split(":");

    topicsArray = topicsArray.concat(titles);

    for (var l = titles.length; l < 3; l++) {
        topicsArray.push(null);
    }

    return topicsArray;
};

/**
 * helper function for topicTree.toggle
 * went up to the next "div" node in the topictree
 * returns the root node of a subtree.
 */
topicTree.getTopicParent = function(obj) {
    var listItem;
    while (obj.nodeName.toLowerCase() != 'div') {
        if (obj.nodeName.toLowerCase() == 'body') {
            return null;
        }
        obj = obj.parentNode;
    }
    return obj;
};

/**
 * Returns a single TopicNode
 */
topicTree.createTopicNode = function(nodeKey, linkTitle, linkValue, locale, subTree) {
    var subTree = subTree;

    var currentItem = DOMUtil.createElement("div");

    currentItem.setAttribute("title", linkTitle);
    currentItem.setAttribute("id", nodeKey);
    currentItem.setAttribute("xml:lang", locale);
    currentItem.setAttribute("class", "treeitem-inactive");

    var displayT = DOMUtil.createElement("table");
    var displayTable = DOMUtil.createElement("tbody");
    var displayRow = DOMUtil.createElement("tr");

    var iconCell = DOMUtil.createElement("td");
    iconCell.setAttribute("class", "icon");
    if (browser.id.IE && !browser.id.OP) {
        iconCell.style.paddingRight = "4px";
        iconCell.style.verticalAlign = "top";
        iconCell.style.width = "5%";
    }
    var iconElement = DOMUtil.createElement("img");
    if (browser.id.IE && !browser.id.OP) {
        iconElement.style.marginTop = "4px";
    }
    if (subTree) {
        iconElement.setAttribute("src", "/vsengine/images/plus-inactive.gif");
        if (browser.id.IE && !browser.id.OP) {
            // Hier kommt der IE! Und der ignoriert den onclick EventHandler,
            // wenn mit setAttribute gearbeitet wird
            iconElement.onclick = topicTree.toggle;
        } else {
            // TODO: fuer die uebrigen relevanten Browser testen
            iconElement.setAttribute("onclick", "topicTree.toggle(this)");
        }
        iconElement.setAttribute("alt", "TreeToggle");
    } else {
        iconElement.setAttribute("src", "/vsengine/images/leaf-inactive.gif");
    }
    iconCell.appendChild(iconElement);

    var linkCell = DOMUtil.createElement("td");
    var linkElement = DOMUtil.createElement("a");
    var linkText = document.createTextNode(linkTitle);
    linkElement.setAttribute("class", "topictree");
    linkElement.setAttribute("href", linkValue);
    linkElement.appendChild(linkText);
    linkCell.appendChild(linkElement);

    displayRow.appendChild(iconCell);
    displayRow.appendChild(linkCell);

    displayTable.appendChild(displayRow);
    displayT.appendChild(displayTable);
    currentItem.appendChild(displayT);
    if (subTree) {
        var subTreeDiv = DOMUtil.createElement("div");
        currentItem.appendChild(subTreeDiv);
    }
    return currentItem;
}

/**
 * erzeugt aus dem Key eine URL
 */
topicTree.getURLKey = function(key) {
    var titles = key.split(":");
    var l = titles.length;
    var URLKey = "";
    for (var i=0; i<titles.length; i++) {
        var title = String(titles[i].trim());
        if (title!=null && title!="") {
            URLKey += URLCoder.encode(titles[i]);
            if (i < titles.length - 1) {
                URLKey += "/";
            }
        }
    }

    return URLKey;
}

/**
 * erzeugt einen TopicTree
 */
topicTree.createTreeNode = function(subject, area, specialism, locale, scope) {
    var treeContainer = DOMUtil.createElement("div");
    treeContainer.setAttribute("style", "display: block;");
    var subject = subject;
    var area = area;
    var specialism = specialism;
    var locale = locale; // requested language

    var topicTreeNode;   // requested tree node from the Topics object
    var URLKey;  //
    var requestedKey;    // der Schluessel des angeforderten (Teil-)Baumes

    var scope; // tra|vlu
    var hasSubTree = false;

    if (subject && area && specialism) { // Dieser Fall wird nicht auftreten
        topicTreeNode = Topics[subject][area][specialism];
    } else if (subject && area) {
        topicTreeNode = Topics[subject][area];
        requestedKey = Topics[subject][area]["key"];
    } else if (subject) {
        requestedKey = Topics[subject]["key"];
        topicTreeNode = Topics[subject];
        hasSubTree = true;
    } else {
        requestedKey = "";
        topicTreeNode = Topics;
        hasSubTree = true;
    }

    var scope = scope;
    logger.debug("scope: [" + scope + "]");
//    var scope = DOMUtil.getScope();

    for (var item in topicTreeNode) {
        if (topicTree.isValidName(item)) {

            var currentKey = scope + ":" + topicTreeNode[item]["key"];
            URLKey = topicTree.getURLKey(currentKey);
            var linkTitle = topicTreeNode[item]["translations"][locale];
            var linkValue = "/vsengine/topics/" + locale + "/" +
                            URLKey + "/index.html";
            var treeNode = topicTree.createTopicNode(currentKey, linkTitle, linkValue, locale, hasSubTree);
            treeContainer.appendChild(treeNode);
        }
    }

    return treeContainer;
}

/**
 * liefert einen (Teil-)Baum aus dem TopicTree zurueck
 * die Sprache wird duch @locale angegeben. Default ist "de"
 */
topicTree.getTreeNode = function(topicArray, localeValue, scope) {
    var treeNode;
    var localizedTitle;
    var subject = topicArray[0];
    var area = topicArray[1];
    var specialism = topicArray[2];
    var locale = (localeValue != null) ? localeValue : "de";
    var scope = scope;
    //alert("topicTree.createTreeNode(" + subject + ", " + area + ", " + specialism + ", " + locale + ", " + scope + ")");
    treeNode = topicTree.createTreeNode(subject, area, specialism, locale, scope);
    return treeNode;
}

/**
 * topic tree toggle
 */
topicTree.toggle = function(obj) {
    if (!obj) {
        var event = window.event;
        event.cancelBubble = true;
        if (event.stopPropagation) {
            event.stopPropagation();
        }
        if (event.srcElement) {
            var obj = event.srcElement;
        }
    }
    //debugger;
    var currentDisplay;
    var listItem = topicTree.getTopicParent(obj);
    var img, node, nodeName, nodeTitle, scope;
    if (obj.nodeName.toLowerCase() == 'img' && listItem.nodeName.toLowerCase() == 'div') {
        img = obj;
        node = listItem;
        var nodeTitle = node.title;
        var nodeID = node.id;
        if (nodeID.indexOf(":") != -1) {
            scope = nodeID.split(":")[0];
        }
        //alert("nodeId [" + nodeID + "][" + nodeID.indexOf(":") + "][" + scope + "]");
        var nodeKey = node.id;
        var locale = node.getAttribute("xml:lang");
        //node.style.border = "solid 1px red";
    } else {
        return;
    }
    if (node.nodeName.toLowerCase() != 'div') return;

    var isopen = (img.src.indexOf('minus') != -1);
    var isactive = (img.src.indexOf('inactive') == -1);
    var isleaf = (img.src.indexOf('spec') != -1);

    if (isleaf) return;

    for (var i = 0; i < node.childNodes.length; i++) {
        var currentNode = node.childNodes[i];
        if (currentNode.nodeType == '1' && currentNode.nodeName.toLowerCase() == 'div') {
            //alert(currentNode.childNodes.length);
            if (currentNode.childNodes.length == 0) {
                var parentNode = currentNode.parentNode;
                parentNode.removeChild(currentNode);
                topicTree.Ajax.getRemoteXML(nodeKey, locale, parentNode, scope);
            }

            currentDisplay = DOMUtil.getElementStyle(currentNode, 'display', 'display');

            // currentDisplay is unknown, probably a Konqueror/Safari
            // So lets guess from the context.
            if (currentDisplay == '') {
                currentDisplay = isopen ? 'block' : 'none';
            }

            if (currentDisplay == 'none') {
                currentNode.style.display = 'block';
            } else {
                currentNode.style.display = 'none';
            }
        }
    }

    if (isopen) {
        if (isactive) {
            img.src = '/vsengine/images/plus-active.gif';
        } else {
            img.src = '/vsengine/images/plus-inactive.gif';
        }
    } else {
        if (isactive) {
            img.src = '/vsengine/images/minus-active.gif';
        } else {
            img.src = '/vsengine/images/minus-inactive.gif';
        }
    }
}
/**
 * ermittelt alle message elemente von node
 */
topicTree.getMessages = function(node) {
    var messages = new Array();
    for (var i = 0; i < node.childNodes.length; i++) {
        var currentChild = node.childNodes[i];
        if (currentChild.nodeType == '1' && currentChild.nodeName == 'message') {
            messages.push(currentChild);
        }
    }
    return messages;
}

/**
 * Erzeugt oder erweitert das Topics-Array
 */
topicTree.writeTopics = function(key, titles) {
    var currentTitles = titles;
    var currentKey = key;

    switch (currentTitles.length) {
        case 1:
            if (!Topics[currentTitles[0]]) Topics[currentTitles[0]] = new Object();
            if (!Topics[currentTitles[0]]["translations"]) Topics[currentTitles[0]]["translations"] = new Object();
            if (!Topics[currentTitles[0]]["key"]) Topics[currentTitles[0]]["key"] = currentKey;
            msgObj =  Topics[currentTitles[0]]["translations"]
            break;
        case 2:
            if (!Topics[currentTitles[0]]) Topics[currentTitles[0]] = new Object();
            if (!Topics[currentTitles[0]]["key"]) Topics[currentTitles[0]]["key"] = currentTitles[0];
            if (!Topics[currentTitles[0]][currentTitles[1]]) Topics[currentTitles[0]][currentTitles[1]] = new Object();
            if (!Topics[currentTitles[0]][currentTitles[1]]["translations"]) Topics[currentTitles[0]][currentTitles[1]]["translations"] = new Object();
            if (!Topics[currentTitles[0]][currentTitles[1]]["key"]) Topics[currentTitles[0]][currentTitles[1]]["key"] = currentKey;
            msgObj =  Topics[currentTitles[0]][currentTitles[1]]["translations"];
            break;
        case 3:
            if (!Topics[currentTitles[0]]) Topics[currentTitles[0]] = new Object();
            if (!Topics[currentTitles[0]]["key"]) Topics[currentTitles[0]]["key"] = currentTitles[0];
            if (!Topics[currentTitles[0]][currentTitles[1]]) Topics[currentTitles[0]][currentTitles[1]] = new Object();
            if (!Topics[currentTitles[0]][currentTitles[1]]["key"]) Topics[currentTitles[0]][currentTitles[1]]["key"] = currentTitles[0] + ":" + currentTitles[1];
            if (!Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]) Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]] = new Object();
            if (!Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]["translations"]) Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]["translations"] = new Object();
            if (!Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]["key"]) Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]["key"] = currentKey;
            msgObj =  Topics[currentTitles[0]][currentTitles[1]][currentTitles[2]]["translations"];
            break;
        default:
            break;
    }
}

var Keys = new Array(); // Kontrollarray fuer Keys

topicTree.processNode = function(node) {
    var XMLDocument = node;
    for (var i=0; i < XMLDocument.childNodes.length; i++) {
        var currentNode = XMLDocument.childNodes[i];
        switch (currentNode.nodeType) {
            case 1: // element node
                if (currentNode.getAttribute("key")) {
                    var currentKey = currentNode.getAttribute("key");
                    Keys.push(currentKey);
                    var currentTitles = currentKey.split(":");
                    topicTree.writeTopics(currentKey, currentTitles);

                    var messages = topicTree.getMessages(currentNode);
                    for (var m = 0; m < messages.length; m++) {
                        var message = messages[m];
                        var lang = message.getAttribute("xml:lang");
                        if (! lang) lang = message.getAttribute("lang"); // Opera

                        msgObj[lang] = DOMUtil.getTextContent(message);

                    }
                    topicTree.processNode(currentNode);
                }
                break;
            default:
                break;
        }
    }
}

function XML2Topics(XMLObj, locale, target, scope) {
    var XMLDocument = XMLObj;
    var context = XMLDocument.getAttribute("key"); // context without scope
    var locale = (!locale) ? "de" : locale;
    var target = target;
    // generates new tree / subtree if necessary
    // currently there is only one tree for both the vlus and the trajectories !!!
    topicTree.processNode(XMLDocument);

    var Titles = topicTree.getTitles(context);
    var treeNode = topicTree.getTreeNode(Titles, locale, scope);
    var ins = target;
    ins.appendChild(treeNode);
}

topicTree.Ajax = new Object();
topicTree.Ajax.xmlHttp = null;
topicTree.Ajax.status = null;    // HTTP status code des letzten Requests
topicTree.Ajax.msg = "";         // ReadyState message
topicTree.Ajax.remoteXML = null;

topicTree.Ajax.getRemoteXML = function(topicKey, locale, target, scope) {
    var xmlHttp = DOMUtil.createXMLHttpRequest();;
    var locale = locale;
    var target = target;
    var scope = scope;
    var locati = document.location;
    for (var prop in locati) {
        logger.info("[" + prop + "] - [" + locati[prop] + "]");
    }

    var key = "";
    if (topicKey) {
        key = topicTree.getURLKey(topicKey) + "/";
        logger.debug("key: [" + key + "]");
    }

    topicTree.Ajax.xmlHttp = xmlHttp;

    // Server, der die topics.xml bereithaelt;
    // muss fuer die Testseite entsprechend eingestellt werden
    var server = "";
    //var server = "http://thyr.darkzone.fiz-chemie.de";

    // seek bildet den aktuelle Kontext ab. Z.Zt. wird weder Sprache noch
    // der scope unterschieden. Die vorhandenen Sprachen sind alle in einer Datei
    // untergebracht.
    // Scope: Die Topicbaeume vlu/tra unterscheiden sich nicht. Scope ist aber
    // wichtig fuer die Unterscheidbarkeit der Keys; z.B. vlu:Chemie/tra:Chemie
    // mommentan wird der Key fuer das Ansprechen des Knotens nicht verwendet.
    // Stattdessen bekommt der Toggle 'this' uebergeben.
    //var seek = "/workspace/vscms-trunk/src/vsengine/static/javascript/topics/" + key;
    var seek = "/vsengine/topics/de/" + key;


    var file = "topics.xml";
    var URL = server + seek + file;

    if (xmlHttp) {
        xmlHttp.open('GET', URL, true);
        xmlHttp.onreadystatechange = function() {
            switch (xmlHttp.readyState) {
                case 4:
                    topicTree.Ajax.status = xmlHttp.status;
                    topicTree.Ajax.msg = "complete";

                    if (xmlHttp.status != 200) {
                        topicTree.Ajax.msg = "Status: [" + xmlHttp.status + "] " + URL;
                        alert(topicTree.Ajax.msg);
                    } else {
                        XML2Topics(xmlHttp.responseXML.documentElement, locale, target, scope);
                    }
                    break;
                default:
                    break;
            }
        };
        xmlHttp.send(null);
    }
}
