/**
 * 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.enabled = true;
    this.term;
    this.timeout;
    this.interval;
    this.input;
    this.defaultText;
    this.value;
    this.handler = handler;
    this.form = form;
    this.options = options;
    this.div;

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

        /* initialization code */
        setupEventListeners();

    }

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


    /* ---[ PRIVATE METHODS ]--- */
    this.handleAutoComplete = function(){
        /* Process string : Remove anything not whitespace, alpha, or numeric and trim whitespace from ends */
        var newTerm = this.input.getValue().replace(/[^a-zA-Z 0-9 \s]/g, "").trim();
        if(this.term !== newTerm && newTerm !== ""){
            /* Call DWR Method */
            self.handler(newTerm,actionCallback);
        }
        this.term = newTerm;
    };

    this.renderSuggestions = function(suggestions){
        var suggestionContainer = getSuggestionsRelativeToInput();
        suggestionContainer.empty().removeClass("hide"); 

        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); $E(".searchButton",self.form).click(); }
                }
            }).setHTML(suggestion).injectInside(list);
        });
        list.injectInside(suggestionContainer);
    };

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

    this.hide = function(){
        getSuggestionsRelativeToInput().addClass("hide");
    };

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

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

    this.enable = function(){
        this.enabled = true;
    };

    this.disable = function(){
        this.enabled = false;
        this.hide();
    };

    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 self.div; //$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 */
        self.div = new Element("div",{"class":"suggestions"}).setStyles({
            top:input.getSize().size.y + input.getPosition().y,
            left:input.getPosition().x,
            width:input.getSize().size.x
        }).addClass("hide").injectInside(document.body);

        /* attach fn to handle autocomplete to the input */
        input.addEvent("focus",function(){
            if(self.enabled){
                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(){
            if(self.enabled){
                clearInterval(self.interval);

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

        /* */
        input.addEvent("keydown",function(event){
            if(self.enabled){
                self.renewTimeout();
                var event = new Event(event);
                if(event.key == 'enter'){
                    var selected = $E(".hover",self.div);
                    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");

    }

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