/**
 * @author Fahrettin Kutyol
 * This is the rebuilt for dojo 1.2.x of the former 0.4 shopsuggest widget.
 * This widget had to be coded from scratch, because the fundamental design of widgets
 * had been changed since dojo 0.9.x. Unlike to the old version this widget doesn't extend
 * a combobox widget.
 *
 *  Summary:
 *  this is classical suggestion input box. by typing characters the suggestions are shown.
 *  in this version there are several improvements of the feel for a better user experience.
 *
 
 */
dojo.provide("haufedojo.widget.shopsuggest");

// debug now goes that way. 
console.debug("providing haufe.widget.shopsuggest");

// requirering the refactored widget superclass
dojo.require("dijit.z_Widget");
dojo.require("dijit.z_Templated");

// building the widget class
dojo.declare("haufedojo.widget.shopsuggest", //our subclass
 [dijit.z_Widget, dijit.z_Templated], // superclasses
{

    hoverColor: "#c9c9c9",// color of the suggest hover
    resultsLength: undefined,// length of the result list. this result length -1 represents the last item
    currentItem: undefined, // the current selected item (by mouse)
    currentPrefix: undefined,// the summ of the words typed in the input area
    isShowing: false, // does the suggest pane show
    noSuggestion: true, // true if there are no suggestions for the prefix
    position: undefined, // equals to current Item but choosen by the arrow keys
    keyAction: false, // detects if a key has been pressed. needed to synchronize key selects with mouse hovers
    shadowShift: 5, // the shift of the shadow
    templatePath: "/haufedojo/widget/templates/shopsuggest.html", // loading the widget template
    
    //This is a follow up of the Constructor
    postCreate: function(){
        
        //importing the css
        this.importCss("/haufedojo/widget/templates/shopsuggest.css");
        
        //connecting of the suggestion box
        this.connect(this.realSuggestionBox, "onkeypress", "onKeyPress");
        this.connect(this.realSuggestionBox, "onblur", "fadeOut");
        this.connect(this.realSuggestionBox, "onclick", "onFocus");
        
        // creating the suggestions wrapper
        this.suggestionWrapper = document.createElement("div");
        this.suggestionWrapper.className = "dojoComboBoxOptions";
        var inputBoxBounds = dojo.coords(this.realSuggestionBox, true);
        sws = this.suggestionWrapper.style;
        sws.left = inputBoxBounds.x + "px";
        
        // -1 is the magic number. don't change or you will be accursed
        sws.top = (inputBoxBounds.y + inputBoxBounds.h - 1) + "px";
        dojo.body().appendChild(this.suggestionWrapper);
        
        // creating the shadowbox
        this.shadow = document.createElement("div");
        this.shadow.className = "shopSuggestShadow";
        var ss = this.shadow.style;
        ss.backgroundColor = "#000000";
        ss.position = "absolute";
        dojo._setOpacity(this.shadow, 0.4);
        // don't forget about the magic number if you wanna live
        ss.top = (inputBoxBounds.y + inputBoxBounds.h - 1 + this.shadowShift) + "px";
        ss.left = (inputBoxBounds.x + this.shadowShift) + "px";
        dojo.body().appendChild(this.shadow); 
    },
    
    // fired if a key is pressed in the suggestion input box
    onKeyPress: function(/*DOMEvent*/evt){
        var checkNewSuggestion = true;
        switch (evt.keyCode) {
            // actions if arrow up is pressed
            case dojo.keys.UP_ARROW:
                checkNewSuggestion = false;
                if (this.isShowing && this.position != undefined && this.position != 0) {
                    this.keyAction = true;
                    this.setHighlite(false);
                }
                else 
                    if (this.isShowing) {
                        this.position = undefined;
                        this.purgePosition(-1);
                        this.fadeOut();
                    }
                break;
            // actions if arrow down is pressed    
            case dojo.keys.DOWN_ARROW:
                checkNewSuggestion = false;
                if (!this.isShowing && !this.noSuggestion) {
                    this.showSuggestion();
                }
                else {
                    if (this.position != (this.resultsLength - 1)) {
                        this.keyAction = true;
                        this.setHighlite(true);
                    }
                }
                break;
            // actions if escape key is pressed
            case dojo.keys.ESCAPE:
                checkNewSuggestion = false;
                this.purgePosition();
                this.position = undefined;
                if (!this.isShowing && !this.noSuggestion) {
                    this.showSuggestion();
                }
                else {
                    this.fadeOut();
                }
                
                if (dojo.isIE) {
                    setTimeout(dojo.hitch(this, function(){
                        this.realSuggestionBox.value = this.currentPrefix;
                    }), 200);
                }
                break;
            // actions if enter is pressed. this means selecting the prefix and submit    
            case dojo.keys.ENTER:
                checkNewSuggestion = false;
                this.hideSuggestion();
                if (this.position != undefined) {
                    this.submitForm(dojo.byId('suggestion-' + this.position));
                }
                break;
            // actions if left / right arrow key is pressed. doesn't do anything returns key action    
            case dojo.keys.LEFT_ARROW:
            case dojo.keys.RIGHT_ARROW:
                checkNewSuggestion = false;
                break;
        }
        
        // if a key is pressed and if this is not one of the special keys
        // this checks the content of the inputbox and fires the xhr to get 
        // the suggestions. the delay is needed because otherwise the currently pressed key is
        // not a part of the prefix. 
        if (checkNewSuggestion) {
            setTimeout(dojo.hitch(this, this.checkPrefix), 200);
        }
    },
    
    // this function checks the entered prefix and gets the suggestions via xhr
    checkPrefix: function(){
        this.position = undefined;
        this.resultItem = new Array();
        var prefix = this.realSuggestionBox.value;
        if (prefix == this.currentPrefix) {
            return;
        } else {
            this.currentPrefix = prefix;
        }
        var categoryId = dojo.byId("CategoryID");
        var cId = "";
        if (categoryId) {
            cId = encodeURIComponent(categoryId.value);
        }
        var searchUrl = "searchGetSuggestions?prefix=" + prefix + "&categoryId=" + cId;
        
        
        // Callback function to set xhr response and adjust some boundings
        var callback = dojo.hitch(this, function(response, ioArgs){
            try {
                jsonData = dojo.fromJson(response);
            } 
            catch (e) {
                console.debug("No JSON Data");
            }
            this.suggestionWrapper.innerHTML = "";
            this.resultsLength = jsonData.length;
            this.appendResults(jsonData);
            
        })
        
        // Loading the content using href
        dojo.xhrGet({
            url: searchUrl,
            load: callback,
            error: function(response, ioArgs){
                console.log("Failed XHR: ", response, ioArgs);
            }
        });
        
    },
    
    // Internal widget css requirement doesn't exist anymore in dojo 1.x
    // This is a hack to import a css file
    importCss: function(fileName){
        var fileref = document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", fileName);
        if (typeof fileref != "undefined") 
            document.getElementsByTagName("head")[0].appendChild(fileref);
    },
    
    // this function is feeding the results into the suggestions box
    // ripped and modified from the former shopsuggest widget
    appendResults: function(/*Array*/results){
        
        if (!results.length) {
            this.noSuggestion = true;
            this.position = undefined;
            this.isShowing = false;
            this.hideSuggestion();
        }
        
        if (results.length) {
            this.noSuggestion = false;
            var divroot = document.createElement("div");
            var divheadl = document.createElement("div");
            var divheadr = document.createElement("div");
            var divhead = document.createElement("div");
            
            divroot.className = "dojoDivRoot";
            divhead.className = "dojoDivHead";
            divheadl.appendChild(document.createTextNode("Empfehlungen"));
            divheadr.appendChild(document.createTextNode("(Treffer)"));
            divheadl.className = "dojoDivHeadLeft";
            divheadr.className = "dojoDivHeadRight";
            
            divhead.appendChild(divheadl);
            divhead.appendChild(divheadr);
            divroot.appendChild(divhead);
            
            var first = 0; // counting the suggestion items
            // feeding the suggestion box with the items
            while (results.length) {
                var newname = "";
                var tr = results.shift();
                if (tr) {
                    if (tr[0].length > 23) {
                        newname = tr[0].substring(0, 23);
                        newname = newname + " ...";
                    }
                    else {
                        newname = tr[0];
                    }
                    var div = document.createElement("div");
                    var divl = document.createElement("div");
                    var divr = document.createElement("div");
                    div.id = "suggestion-" + first;
                    div.setAttribute("sgId", first);
                    divl.appendChild(document.createTextNode(newname));
                    divr.appendChild(document.createTextNode("(" + tr[1] + ")"));
                    
                    divl.setAttribute("resultName", tr[0]);
                    divl.setAttribute("title", tr[0]);
                    divl.className = "dojoComboBoxItemLeft";
                    divr.setAttribute("resultValue", tr[1]);
                    divr.className = "dojoComboBoxItemRight";
                    div.className = "dojoComboBoxItem " + ((first % 2) ? "dojoComboBoxItemEven" : "dojoComboBoxItemOdd") + ((first === 0) ? " dojoComboBoxItemFirst " : "");
                    
                    div.appendChild(divl);
                    div.appendChild(divr);
                    
                    // binding this (each) item to a mouse events
                    this.connect(div, "onmouseover", "itemMouseOver");
                    this.connect(div, "onmouseout", "itemMouseOut");
                    this.connect(div, "onclick", "itemOnClick");
                    
                    divroot.appendChild(div);
                    first++;
                }
            }
            this.suggestionWrapper.appendChild(divroot);
            this.showSuggestion();
        }  
    },
    
    // cleaning the highlite of the position
    purgePosition: function(pos){
        if (!pos) {
            pos = this.position;
        }
        if (pos) {
            if (pos == -1) {
                pos = 0;
            }
            dojo.byId('suggestion-' + pos).style.backgroundColor = "transparent";
        }
        
    },
    
    // fired by mouse over. mouse hover effect when suggestions are showing for one specific item
    itemMouseOver: function(/*DOMEvent*/evt){
        if (this.keyAction) {
            this.purgePosition();
            this.keyAction = false;
        }
        evt.target.parentNode.style.backgroundColor = this.hoverColor;
        var sgId = evt.target.parentNode.getAttribute("sgId");
        this.position = parseInt(sgId);
        if (this.currentItem) {
            dojo.byId('suggestion-' + sgId).style.backgroundColor = "transparent";
        }
        this.currentItem = sgId;
    },
    
    // fired by mouse out by a specific suggestion item
    itemMouseOut: function(/*DOMEvent*/evt){
        if (this.keyAction) {
            this.purgePosition();
            this.keyAction = false;
        }
        evt.target.parentNode.style.backgroundColor = "transparent";
        this.position = undefined;
        this.currentItem = undefined;
    },
    
    // fired by mouse click of specific suggestion item
    itemOnClick: function(/*DOMEvent*/evt){
        this.hideSuggestion();
        this.submitForm(evt.target.parentNode);
        
    },
    
    // submitting the form
    submitForm: function(node){
        var childs = node.childNodes;
        var name = childs[0].getAttribute("resultName");
        var value = childs[1].getAttribute("resultValue");
        this.comboBoxValue.value = value;
        this.comboBoxSelectionValue.value = value;
        this.realSuggestionBox.value = name;
        document.searchS.submit();
    },
    
    // showing the suggestions
    showSuggestion: function(){
        if (!this.isShowing) {
            this.suggestionWrapper.style.visiblility = "hidden";
            this.shadow.style.visiblility = "hidden";
            this.suggestionWrapper.style.display = "block";
            this.shadow.style.display = "block";
            dojo._setOpacity(this.suggestionWrapper, 0);
            dojo._setOpacity(this.shadow, 0);
        }
        var suggestionBounds = dojo.coords(this.suggestionWrapper, false);
        this.shadow.style.width = suggestionBounds.w + "px";
        this.shadow.style.height = suggestionBounds.h + "px";
        if (!this.isShowing) {
            this.fadeIn();
        }
        else {
        
        }
    },
    
    // hidding the suggestions
    hideSuggestion: function(){
        this.suggestionWrapper.style.display = "none";
        this.shadow.style.display = "none";
    },
    
    // suggestion input box has been entered
    onFocus: function(/*DOMEvent*/evt){
        var prefix = this.realSuggestionBox.value;
        if (prefix != "" && this.resultsLength) {
            this.showSuggestion();
        }
    },
    
    // suggestion box fade in
    fadeIn: function(){
        // if already showing, return
        if (this.isShowing) 
            return;
        
        var inputBoxBounds = dojo.coords(this.realSuggestionBox, true);
        this.suggestionWrapper.style.left = inputBoxBounds.x + "px";
        this.shadow.style.left = (inputBoxBounds.x + this.shadowShift) + "px";
        
        // setting the fade in delay
        var fadeInDelay = 150;
        
        this.suggestionWrapper.style.visiblility = "visible";
        this.shadow.style.visiblility = "visible";
        this.isShowing = true;
        
        //fading in the suggestion wrapper
        dojo.animateProperty({
            node: this.suggestionWrapper,
            duration: fadeInDelay,
            properties: {
                opacity: 1
            }
        }).play();
        
        //fading in the suggestion shadow           
        dojo.animateProperty({
            node: this.shadow,
            duration: fadeInDelay,
            properties: {
                opacity: 0.4
            }
        }).play();
    },
    
    // suggestion box fade out
    fadeOut: function(){
        this.purgePosition();
        
        //setting the fade out delay and reseting some flags to default
        var fadeOutDelay = 200;
        this.isShowing = false;
        this.position = undefined;
        
        //fading out the suggestion wrapper
        dojo.animateProperty({
            node: this.suggestionWrapper,
            duration: fadeOutDelay,
            properties: {
                opacity: 0
            },
            onEnd: dojo.hitch(this, function(){
                this.suggestionWrapper.style.display = "none";
            })
        }).play();
        
        //fading out the shadow
        dojo.animateProperty({
            node: this.shadow,
            duration: fadeOutDelay,
            properties: {
                opacity: 0
            },
            onEnd: dojo.hitch(this, function(){
                this.shadow.style.display = "none";
            })
        }).play();
    },
    
    // setting the highlite of a suggestion item
    // based on the boolean increment we are shifting the highlite 
    // up or down for one position.
    // if increment is true we shift one down. means current position + 1
    // if increment is false or null we shift one up. means current position -1 
    setHighlite: function(/*boolean*/increment){
        var pos = this.position;
        var add = -1;
        if (increment) {
            add = 1;
        }
        
        if (pos != undefined) {
            dojo.byId('suggestion-' + pos).style.backgroundColor = "transparent";
            var newPos = pos + add;
            dojo.byId('suggestion-' + newPos).style.backgroundColor = this.hoverColor;
            this.position = newPos;  
        } else {
            dojo.byId('suggestion-' + 0).style.backgroundColor = this.hoverColor;
            this.position = 0;
        }
    }    
});
