/*
 * typhoon.js
 * $Revision: 1.1 $
 * iso-8859-1
 */

addEvent(window, "load", initSuggest);

function Suggest(input, conf) {

    // title of suggestions
    var masthead = "Produkt-Vorschläge:";
    // title of term suggestions
    var masttermhead = "Suchbegriff-Vorschläge:";
    // what to see and what to hide
    var displayShop    = true;
    var displayTitle = true;
    var displayAuthor = false;
    var displayPrice = false;
    var displayCover = false;

    // max amount of items to display
    var maxAmount = 6;
    // valid this reference even in subfunctions
    var self = this;
    // the xmlhttprequest
    var req = null;
    // the input label thet the suggest is added onto
    var input = input;
    // the target element where the typhoon table will be appended
    var target = document.getElementById("typhoontarget");
    // the checkbox for turning suggest off
    var checkbox = null;
    // the config object
    var config = conf;
    // the table element for suggestions
    var tableElement = null;
    // selected item
    var selected = -1;
    // all items
    var all = new Array();
    // last answer
    var lastAnswer = null;
    var log = new logger(0);
    var isIE = typeof(window.ActiveXObject) != 'undefined';
    var xmlHttp = new BuchXmlHttp();
    // listener functions
    var eventHandler = function(event) {
        window.suggest.handle(event);
    }
    var hideSuggestions = function(event) {
        window.suggest.hide();
    }
    var suppressReturn = function(event) {
        var realEvent = (window.event) ? window.event : event; if (realEvent.keyCode == 13) return false;
    }
    var activeSwitcher = function(event) {
        window.suggest.switchActive();
    }
    var submitter = function(event) {
        window.suggest.submit(event);
    }
    // initialize the suggestion layer
    init();


    /*
     * wird am Anfang aufgerufen, initialisiert alles
     */
    function init() {
        /* cookie-erkennung erstmal fuer's produktiv-deployment rausgenommen */
        /* wenn ich cookies setzen kann, will ich die Ausblendecheckbox einfuegen
         * und evtl. gar nicht initialisieren, falls schon der Cookie gesetzt ist.
         */
        /* (testCookiesEnabled()) {
            var cookieVal = readCookie("typhoonActive");
            if (cookieVal == "false") {
                insertDeactivationCB(false);
                // checkbox einfügen, nicht initialisieren
            } else {
                insertDeactivationCB(true);
                initializeListeners();
                createCookie("typhoonActive", "true", 365);
                // checkbox, init
            }
        } else {
            // nur initialisieren, checkbox nicht einfügen.
            initializeListeners();
        }*/
        initializeListeners();
        addEvent(window, "resize", reloadTarget);
    }

    function reloadTarget() {
        if (document.getElementById("suggestcontainer")) {
            var target = document.getElementById("suggestcontainer");
            var pos = typhoon_getPosition(input);
            target.style.position = "absolute";
            target.style.top = pos.y + 14 + "px";
            target.style.left = pos.x + 1 + "px";
        }
    }

    function initializeListeners() {
        input.setAttribute("autocomplete", "off", 0);
        addEvent(input, "keyup", eventHandler);
        // beim return druecken soll doch bitte nicht das form.submit ausgeloest werden.
        addEvent(input, "keypress", suppressReturn);
        // der versteckt die liste wieder auf mausklick
        addEvent(document.getElementsByTagName("body")[0], "click", hideSuggestions);
    }

    function removeListeners() {
        input.removeAttribute("autocomplete");
        removeEvent(input, "keyup", eventHandler);
        // beim return druecken soll doch bitte nicht das form.submit ausgeloest werden.
        removeEvent(input, "keypress", suppressReturn);
        //input.onkeypress = function(event) { var realEvent = (window.event) ? window.event : event; if (realEvent.keyCode == 13) return false };
        // der versteckt die liste wieder auf mausklick
        removeEvent(document.getElementsByTagName("body")[0], "click", hideSuggestions);
    }

    function insertDeactivationCB(checked) {
        checkbox = createCheckbox(checked);
        var container = document.createElement("div");
        container.className = "deactivation_cb";
        container.appendChild(checkbox);
        container.appendChild(document.createTextNode(" Vorschläge anzeigen"));
        input.parentNode.appendChild(container);
        addEvent(checkbox, "change", activeSwitcher);
    }

    function createCheckbox(checked) {
        var cb = document.createElement("input");
        cb.setAttribute("type", "checkbox", 0);
        if (checked) {
            cb.setAttribute("checked", "checked", 0);
            cb.checked = true;
        }
        return cb;
    }

    function switchActive() {
        var activated = checkbox.checked;
        createCookie("typhoonActive", activated ? "true" : "false", 365);
        if (activated) {
            initializeListeners();
        } else {
            removeListeners();
        }
    }

    /*
     * initialisiert/reinitialisiert die table elemente
     */
    function createTableElement() {
        var table = document.createElement("table");
        table.setAttribute("cellpadding", "0", 0);
        table.setAttribute("cellspacing", "0", 0);
        var pos = typhoon_getPosition(input);
        table.style.top = pos.y + 14 + "px";
        table.style.left = pos.x + 1 + "px";
        table.setAttribute("id", "suggestcontainer", 0);
        table.style.position = "absolute";
        // Append the table to the target Element
        target.appendChild(table);
        addEvent(table, "click", submitter);
        return table;
    }

    function createBodyElement(table) {
        var body = document.createElement("tbody");
        table.appendChild(body);
        return body;
    }

    // for entity conversion
    var entityElement = document.createElement("div");
    function entity(str) {
        entityElement.innerHTML = str;
        return entityElement.innerHTML;
    }

    function showSuggestions() {
        if (req != null && req.readyState && req.readyState == 4) {
            if (req.status && req.status != null && req.status == 200) {
                if (req.responseXML != null && (tableElement == null || lastAnswer != req.responseText)) {
            // IE-Hack: Wenn der Server den Content bei laengeren
            // Antworten aufsplittet, wird der MimeType nicht mehr
            // korrekt gesetzt, und req.responseXML enthaelt nicht
            // das von uns erwartete XML-Dokument. Dies kann man
            // sich dann jedoch selber erzeugen:
            if (isIE) {
                        req.responseXML.loadXML(req.responseText);
                }
                    var table = createTableElement();
                    var body = createBodyElement(table);

                    var books = req.responseXML.getElementsByTagName("book");
                    var terms = req.responseXML.getElementsByTagName("term");

                    while (body.hasChildNodes()) {
                        body.removeChild(father.firstChild);
                    }
                    all = new Array();
                    if (config.trmFrst) {
                        if (config.trmActv) {
                            setTerms(body, terms);
                        }
                        if (config.artActv) {
                            setBooks(body, books);
                        }
                    } else {
                        if (config.artActv) {
                            setBooks(body, books);
                        }
                        if (config.trmActv) {
                            setTerms(body, terms);
                        }
                    }
                    hideLayer();
                    table.style.visibility = "visible";
                    tableElement = table;
                    lastAnswer = req.responseText;
                    req = null;
                }
            }
        else {
            log.info("There was a problem retrieving the XML data:\n" + req.statusText);
            }
        }
    }

    //browser fork
    function getTextContentFromNode(element) {
        try {
            if (element.textContent) return element.textContent;
        }
        catch(e) {
        }
        if (element.text) return element.text;
        var children = element.childNodes;
        var result = "";
        for (var i = 0; i < children.length; i++) {
            var node = children[i];
            if ((node.nodeType >= 3) && (node.nodeType <= 6)) {
                result += node.nodeValue;
            }
            else if (node.nodeType == 1) {
                result += textContent(node);
            }
        }
        // Workaround for konqueror : it can't set element.textContent for some reason, while it doesn't support it... so we use element.text...
        element.text = result;
        return result;
    }

    // erzeugt ein span mit class=<tag> und inhalt des ersten tags
    function createSpan(tag, xml) {

        var max_stringlength    =    50;

        switch (config.mnd) {
            case 3:
                var currencySymbol = 'CHF';
                break;
            case 6:
                var currencySymbol = 'CHF';
                break;
            case 7:
                var currencySymbol = 'CHF';
                break;
            case 8:
                var currencySymbol = 'CHF';
                break;
            case 9:
                var currencySymbol = 'CHF';
                break;
            case 13:
                var currencySymbol = 'CHF';
                break;
            case 15:
                var currencySymbol = 'CHF';
                break;
            case 18:
                var currencySymbol = 'CHF';
                break;
            default:
                var currencySymbol = '&euro;';
                break;
        }


        var el = xml.getElementsByTagName(tag)[0];
        if (el) {
            value = getTextContentFromNode(el);
        }
        else {
            value = "";
        }
        // sonderfall preis
        if (value != "" && tag == "price") {
            while (value.length < 3) {
                value = "0" + value;
            }
            if (currencySymbol == 'CHF') {
                value = value.substring(0,value.length - 2) + "." + value.substring(value.length - 2, value.length);
                value = currencySymbol + " " + value;
            }
        else {
                value = value.substring(0,value.length - 2) + "," + value.substring(value.length - 2, value.length);
                value = entity(currencySymbol) + " " + value;
            }
        }
        // sonderfall autoren
        if (value != "" && tag == "author" && value.length > max_stringlength) {
            value = value.substring(0, max_stringlength) + "...";
            // + "&euro;"
        }
        // sonderfall titel
        if (value != "" && tag == "title" && value.length > max_stringlength) {
            value = value.substring(0, max_stringlength) + "...";
            // + "&euro;"
        }
        var element = createNode("span", value);
        element.className = tag;
        return element;
    }

     function createTermSpan(tag, xml) {

        var max_stringlength    =    50;

        var value = getTextContentFromNode(xml);

        var element = createNode("span", value);
        element.className = tag;
        return element;
    }


    // erzeugt ein div mit class=<tag> und fuegt die elemente des arrays als kinder hinzu
    function createTr(tag) {
        var element = document.createElement("tr");
        element.className = tag;
        return element;
    }

    function createTd(tag, array) {
        var element = document.createElement("td");
        element.className = tag;
        element.setAttribute("nowrap","nowrap", 0);
        for (i = 0; i < array.length; i++) {
            element.appendChild(array[i]);
        }
        return element;
    }

    function createImg(xml) {
        var imageUrlElement = xml.getElementsByTagName("image")[0];
        var content = getTextContentFromNode(imageUrlElement);
        if (imageUrlElement != null && content != null && content != "") {
            var element = document.createElement("img");
            element.setAttribute("src", content, 0);
            return element;
        }
        else {
            return document.createElement("span");
        }
    }

    function createStartSearch(textLeft, textRight, headerClass) {
        var first = createTr("search");
        var link = document.createElement("span");

        var header = document.createElement("span");
        header.className = "typhoon-info-header";
        header.appendChild(document.createTextNode(textLeft));
        link.appendChild(header);

        if (textRight != "") {
            var infotext = document.createElement("span");
            infotext.className = "typhoon-info-text";
            infotext.appendChild(document.createTextNode(textRight));
            link.appendChild(infotext);
        }

        var td = createTd("search", new Array(link));
        td.setAttribute("colspan", "4", 0);
        td.className = "typhoon-general-header";
        if (headerClass != "") {
            td.className = headerClass;
        }
        first.appendChild(td);
        return first;
    }

    function createNoResults() {
        var first = createTr("noresults");
        var msg = document.createElement("span");
        var header = document.createElement("span");
        header.className = "typhoon-info-header-noresults";
        header.appendChild(document.createTextNode("Die Direktsuche ergab leider keine Ergebnisse. Auf gut Glück ..."));
        msg.appendChild(header);
        var td1 = createTd("noresults", new Array());
        td1.setAttribute("width", "0%", 0);
        var td2 = createTd("noresults", new Array(msg));
        td2.setAttribute("colspan", "2", 0);
        first.appendChild(td1);
        first.appendChild(td2);
        return first;
    }

    function setBooks(father, books) {
            // do not display more items than allowed
            var maxBooks = (books.length > maxAmount) ? maxAmount : books.length;

            if (maxBooks == 0) {
                hideSuggestions();
            } else {
                var firstIndex = all.length;
                all[firstIndex] = createStartSearch(masthead, "", "");
                father.appendChild(all[firstIndex]);
                addEvent(all[firstIndex], 'mouseover', function(event) { window.suggest.select(firstIndex); });
                selected = 0;
                for (var i = 0; i < maxBooks; i++) {
                    var elImg = createNode("span", "");
                    elImg.className = "typhoon-image";
                    elImg.appendChild(createImg(books[i]));
                    var elShop        = (displayShop)        ? createSpan("shop", books[i])             : false;
                    var elTitle        = (displayTitle)    ? createSpan("title", books[i])         : false;
                    var elAuthor    = (displayAuthor)    ? createSpan("author", books[i])         : false;
                    var elPrice        = (displayPrice)    ? createSpan("price", books[i])         : false;
                    var trElement    = createTr("book");
                    var coverTd        = (displayCover)    ? createTd("cover", new Array(elImg))     : false;
                    var shopTd        = (displayShop)        ? createTd("shop", new Array(elShop))     : false;
                    if (displayShop) {
                        trElement.appendChild(shopTd);
                    }
                    if (displayCover) {
                        trElement.appendChild(coverTd);
                    }
                    if (displayAuthor) {
                        var titleAndAuthorTd = createTd("titleAndAuthor", new Array(elTitle, elAuthor));
                    } else {
                        var titleAndAuthorTd = createTd("titleAndAuthor", new Array(elTitle));
                    }
                    trElement.appendChild(titleAndAuthorTd);
                    if (displayPrice) {
                        var priceTd = createTd("price", new Array(elPrice));
                        trElement.appendChild(priceTd);
                    }

                    trElement.artikel = getTextContentFromNode(books[i].getElementsByTagName("articleid")[0]);
                    eval("addEvent(trElement, 'mouseover', function(event) { window.suggest.select(" + (firstIndex+i + 1) + "); });");
                    father.appendChild(trElement);
                    all[firstIndex +i+1] = trElement;
                }
                all[firstIndex+maxBooks+1]= createStartSearch("", "Komplette Suche starten", "typhoon-fullsearch-header");
                father.appendChild(all[firstIndex+maxBooks+1]);
                eval("addEvent(all[firstIndex+maxBooks+1], 'mouseover', function(event) { window.suggest.select(" + (firstIndex+maxBooks + 1) + "); });");
            }
            moveSelection(0);
    }

    function setTerms(father, terms) {
            // do not display more items than allowed
            var maxTerms = (terms.length > maxAmount) ? maxAmount : terms.length;

            if (maxTerms == 0) {
                hideSuggestions();
            } else {
                var firstIndex = all.length;
                all[firstIndex] = createStartSearch(masttermhead, "", "typhoon-terms-header");
                father.appendChild(all[firstIndex]);
                addEvent(all[firstIndex], 'mouseover', function(event) { window.suggest.select(firstIndex); });
                selected = 0;
                for (var i = 0; i < maxTerms; i++) {
                    var trElement    = createTr("book");
                    var elTitle        = createTermSpan("term", terms[i]);
                    var titleAndAuthorTd = createTd("titleAndAuthor", new Array(elTitle));
                    titleAndAuthorTd.setAttribute("colspan", "4", 0);
                    trElement.appendChild(titleAndAuthorTd);
                    trElement.isSearchTerm = true;
                    trElement.searchTerm = getTextContentFromNode(terms[i]);
                    eval("addEvent(trElement, 'mouseover', function(event) { window.suggest.select(" + (firstIndex+i + 1) + "); });");
                    father.appendChild(trElement);
                    all[firstIndex +i+1] = trElement;
                }
            }
            moveSelection(0);
    }



    function createNode(tag, content) {
        var newEl = document.createElement(tag);
        var newElContent = document.createTextNode(content);
        newEl.appendChild(newElContent);
        return newEl;
    }

    // self is called from html
    function getSuggestions(word) {
        if (word.length < 1) {
            if (tableElement) {
                tableElement.style.visibility = "hidden";
            }
            lastAnswer = null;
            return;
        }
        if (req != null) {
            req.abort();
        }
        if (config.tkn == "") {
            // no token, no request
            return;
        } else {
            req = xmlHttp.createReq();
        if (req != null) {

            // Mindestens der Firefox setzt bei chunked-messages
            // den MimeType nicht korrekt... deshalb setzen wir
            // den hier hart.
            if (req.overrideMimeType) {
                req.overrideMimeType("text/xml");
            }

            // schauen wir mal, ob wir den shop einschraenken sollen
            word = addShopFilterIfNecessary(word);

            var url = "/typhoon/s/" + config.mnd + "/" + config.sid + "/" + encodeURI(word);
            xmlHttp.openReq(req, url, self.show);
            req.setRequestHeader("TYTOKEN", config.tkn);
            xmlHttp.sendReq(req);
        }
        }
    }

    function addShopFilterIfNecessary(word) {
        var select = document.getElementById('sswg');
        if (select != null && select.value != 'ANY') {
            var shops = select.value.split('_');
            var i = 0;
            var searchstring = word;
            for (i = 0; i < shops.length; i++) {
                if (i != 0) searchstring += ' OR';
                var shopname = shops[i];
                // spezielles handling umlaute
                //if (shopname == 'HOERBUCH') shopname = 'HÖRBUCH';
        if (shopname == 'ELEKTRO') shopname = 'ELEKTRONIK';
                if (shopname == 'FILM') shopname = 'FILM';
                if (shopname == 'SPIEL') shopname = 'SPIEL';
                if (shopname == 'GESELLSCHAFTSSPIEL') shopname = 'GESELLSCHAFTSSPIEL';
                searchstring += " filter(shop:" + shopname.toLowerCase() + ")";
            }
            return searchstring;
        }
        return word;
    }


    function handleEvent(event) {
        var realEvent = getEvent(event);
        if (realEvent.keyCode) {
            if (realEvent.keyCode == 38 || realEvent.keyCode == 40 || realEvent.keyCode == 13) {
                switch (realEvent.keyCode) {
                    case 38:
                        moveSelection(-1);
                        return;
                    case 40:
                        moveSelection(1);
                        return;
                    case 13:
                        submitSelection();
                    return;
                }
            }
        }
        getSuggestions(getEventTarget(realEvent).value);
    }

    function submitSelection() {
        hideLayer();
        var element = all[selected];
        if ((typeof element != 'undefined') && element.isSearchTerm) {
            window.location.href = config.searchurl + ";jsessionid=fdc-" + conf.sid + "?sswg=ANY&" + config.searchElementName + "=" + element.searchTerm;
        }else if ((typeof element != 'undefined') && (element.artikel)) {
            window.location.href = config.url + "/ID" + element.artikel + ".html;jsessionid=fdc-" + conf.sid;
        }
        else {
            input.form.submit();
        }
    }

    function moveSelection(direction) {
        if (direction > 0) {
            if (selected < all.length - 1) {
                selected = selected + 1;
            }
        }
        else {
            if (selected > 0) {
            selected = selected - 1 ;
            }
        }
        applySelection();
    }

    function setSelection(selection) {
        if (selection >= 0 && selection < all.length) {
            selected = selection;
        }
        applySelection();
    }

    function applySelection() {
        for (i = 0; i < all.length; i++) {
            if (i == selected) {
                all[i].className = "typhoon-selected-row";
            } else {
                all[i].className = "typhoon-unselected-row";
            }
        }
    }

    function getEvent(event) {
        return (window.event) ? window.event : event;
    }

    function getEventTarget(event) {
        var realEvent = getEvent(event);
        return (realEvent.target) ? realEvent.target : realEvent.srcElement;
    }

    function typhoon_point(x, y) {
        this.x = x;
        this.y = y;
    }

    function typhoon_getPosition(element) {
        if (element.nodeType == 3) // defeat KHTML bug
            element = element.parentNode;
        return new typhoon_point(typhoon_findPosX(element), typhoon_findPosY(element) + element.offsetHeight);
    }

    function typhoon_findPosX(obj)
    {
        var curleft = 0;
        var origobj = obj;
        if (obj.offsetParent)
        {
            while (obj.offsetParent)
            {
                curleft += obj.offsetLeft;
                obj = obj.offsetParent;
            }
        }
        else if (obj.x)
            curleft += obj.x;
        return curleft;
    }

    function typhoon_findPosY(obj)
    {
        var curtop = 0;
        if (obj.offsetParent)
        {
            while (obj.offsetParent)
            {
                curtop += obj.offsetTop;
                obj = obj.offsetParent;
            }
        }
        else if (obj.y)
            curtop += obj.y;
        return curtop;
    }

    function hideLayer() {
        if (tableElement) {
            tableElement.parentNode.removeChild(tableElement);
        }
        tableElement = null;
    }

    /*
     * declare public methods here
     */
    self.handle = handleEvent;
    self.hide = hideLayer;
    self.show = showSuggestions;
    self.select = setSelection;
    self.submit = submitSelection;
    self.switchActive = switchActive;
}

// funktioniert nur im firefox, landet da auf der konsole.
// dann muss man da nicht mit den alerts rumbasteln
function logger(debugmode) {
    if (window.dump) {
        var console = window;
        var debug = debugmode;
    }
    else {
        var debug = -1;
    }
    this.info = function (message) {
        if (debug >= 0) console.dump("INFO: " + message + "\n");
    }
    this.warning = function (message) {
        if (debug >= 1) console.dump("WARNING: " + message + "\n");
    }
    this.error = function (message) {
        if (debug >= 2) console.dump("ERROR: " + message + "\n");
    }
}

var suggestIsInitialized = false;
// initialisiert, wenn moeglich, die suggest-funktionalitaet
function initSuggest() {
    if (!suggestIsInitialized) {
        var el = document.getElementsByName(sugCnf.searchElementName)[0];
        if ((el) && !(sugCnf == "undefined") && sugCnf.tkn != "") {
            window.suggest = new Suggest(el, sugCnf);
        }
        suggestIsInitialized = true;
    }
}

function tyCnf(tknstr, mndint, sidstr, urlstr, searchurlstr, artActv, trmActv, trmFrst, searchElementNameP) {
    this.tkn = tknstr;
    this.mnd = mndint;
    this.sid = sidstr;
    this.url = urlstr;
    this.searchurl = searchurlstr;
    this.artActv = artActv;
    this.trmActv = trmActv;
    this.trmFrst = true;
    this.searchElementName = "sq";
}

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
    // wer auch immer die untere Zeile hat einkommentiert gelassen, sollte darueber nochmal nachdenken...
    // alert("Handler could not be removed");
  }
}

function removeEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.removeEventListener){
    elm.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.detachEvent){
    var r = elm.detachEvent("on"+evType, fn);
    return r;
  } else {
    // wer auch immer die untere Zeile hat einkommentiert gelassen, sollte darueber nochmal nachdenken...
    // alert("Handler could not be removed");
  }
}


