/**
 * AutoComplete
 *
 * @author Boz
 * @classDescription Suggests search queries based on existing content.
 * @css
 *
 *  .autocomplete
 *  .suggestions
 *  .searchTerm
 *
 * Assumptions:
 *
 **/

mdp.app.AutoComplete = function(form,handler,options){
    /* ---[ CLASS VARIABLES ]--- */
    var self = this;
    this.term;
    this.timeout;
    this.interval;
    this.input;
    this.defaultText;
    this.value;
    this.handler = handler;
    this.form = form;

    /* ---[ CONSTRUCTOR ]--- */
    function init(){

        /* initialization code */
        setupEventListeners();

    }

    /* ---[ PUBLIC METHODS ]--- */


    /* ---[ PRIVATE METHODS ]--- */
    this.handleAutoComplete = function(){
        //Dwr method
        var newTerm = this.input.getValue().replace(/[^a-zA-Z 0-9]/g, "").trim();
        if(this.term !== newTerm && newTerm !== ""){
            self.handler(newTerm,actionCallback);
        }
        this.term = newTerm;
    };

    this.renderSuggestions = function(suggestions){
        var suggestionContainer = getSuggestionsRelativeToInput();
        suggestionContainer.empty().removeProperty("style"); 

        var list = new Element("ul");
        $A(suggestions).each(function(suggestion,i){
            var li = new Element("li",{
                events:{
                    "mouseover":function(){ $(this).addClass("hover"); },
                    "mouseout":function(){ $(this).removeClass("hover"); },
                    "click":function(){ self.populate(this); self.form.submit(); }
                }
            }).setHTML(suggestion).injectInside(list);
        });
        list.injectInside(suggestionContainer);
    };

    this.populate = function(el){
        self.input.value = $(el).getText();
        self.hide();
    };

    this.hide = function(){
        getSuggestionsRelativeToInput().setStyle("display","none");
    };

    this.renewTimeout = function(){
        clearTimeout(self.timeout);
        self.setTimeout();
    };

    this.setTimeout = function(){
       self.timeout = setTimeout(function(){
            self.hide();
        },5000);
    };

    function actionCallback(remoteResult){
        if (remoteResult.statusCode == 0) {
            /* Success! */
            if(typeof(remoteResult.result) == "string"){
                self.renderSuggestions(eval(remoteResult.result));
            }

            if(typeof(remoteResult.result) == "object"){
                self.renderSuggestions(remoteResult.result);
            }

        }
    }

    function getSuggestionsRelativeToInput(){
        return $E(".suggestions",self.input.getParent());
    }

    /* ---[ EVENT LISTENERS ]--- */
    function setupEventListeners(){

        /* get the search term input */
        var input = $E("input.searchTerm",form);

        /* set default text */
        self.input = input;
        self.defaultText = input.value;

        /* set up the suggestions div */
        new Element("div",{"class":"suggestions","style":"display:none"}).injectAfter(input);

        /* attach fn to handle autocomplete to the input */
        input.addEvent("focus",function(){
            self.input = $(this);
            self.value = self.input.value;
            self.input.value = '';
            self.setTimeout();
            self.interval = setInterval(function(){
                self.handleAutoComplete();
            },500);
        });

        /* stop suggestioning things when the input is blurred */
        input.addEvent("blur",function(){
            clearInterval(self.interval);

            /* restore initial value if user enters nothing */
            if(self.input.value === ''){ self.input.value = self.value; }
        });

        /* */
        input.addEvent("keydown",function(event){
            self.renewTimeout();
            var event = new Event(event);
            if(event.key == 'enter'){
                var selected = $E(".hover",form);
                if(selected != null){
                    self.populate(selected);
                }
            }
            if(event.key == 'down'){
                var suggestions = getSuggestionsRelativeToInput();
                if(suggestions != null){
                    var selected = $E(".hover",suggestions);
                    if(selected == null){
                        $E("li",suggestions).addClass("hover");
                    }
                    else{
                        selected.removeClass("hover");
                        selected = selected.getNext();
                        selected.addClass("hover");
                    }
                }
            }
            if(event.key == 'up'){
                var suggestions = getSuggestionsRelativeToInput();
                if(suggestions != null){
                    var selected = $E(".hover",suggestions);
                    if(selected != null){
                        selected.removeClass("hover");
                        selected = selected.getPrevious();
                        selected.addClass("hover");
                    }
                }
            }
            if(event.key == 'esc'){
                self.hide();
            }
        });

        /* turn off browser auto complete */
        input.setProperty("autocomplete","off");

        /* prevent empty and default text searches */
        form.addEvent("submit",function(e){
            if(self.input.value == "" || self.input.value == self.defaultText){
                new Event(e).preventDefault();
            }
        });

        /* clean url */
        if(typeof(options) != 'undefined' && typeof(options.cleanurls) != 'undefined' && options.cleanurls){
            input.getParent().addEvent("submit",function(){
                var term = $E(".searchTerm",this);
                if(term.value == ''){return false;}
                else{
                    this.action = "/search/"+ term.value;
                }
            });
        }

    }

    /* ---[ RUN ]--- */
    init();
};
