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

mdp.app.AutoComplete = function(form,handler,settings){
    /* ---[ CLASS VARIABLES ]--- */
    var self = this;
    this.disableClear = false;
    this.enabled = true;
    this.term;
    this.timeout;
    this.interval;
    this.input;
    this.defaultText;
    this.value;
    this.handler = handler;
    this.form = form;
    this.options = {
        detectWidth:true,
        specialClass:""
    };
    this.div;

    $.extend(this.options,settings);

    /* ---[ 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.val().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 = $("<ul>");
        $(suggestions).each(function(i,suggestion){
            var li = $("<li>").bind({
                    "mouseover":function(){ $(this).addClass("hover"); },
                    "mouseout":function(){ $(this).removeClass("hover"); },
                    "click":function(){ self.populate(this); $(self.form).find(".searchButton").trigger("click"); }
            }).html(suggestion).appendTo(list);
        });
        list.appendTo(suggestionContainer);
    };

    this.populate = function(el){
        self.input.val($(el).text());
        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(remoteResult.result != null){
                if(typeof(remoteResult.result) == "string"){
                    self.renderSuggestions($.parseJSON(remoteResult.result));
                }

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

        }
    }

    function getSuggestionsRelativeToInput(){
        return self.div; //$(".suggestions:first",self.input.parent());
    }

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

        /* get the search term input */
        var input = $(self.form).find("input.searchTerm:first");

        /* set default text */
        self.input = input;
        self.defaultText = input.val();

        /* set up the suggestions div */
        self.div = $("<div>").attr({"class":"suggestions"}).css({
            top:input.height() + input.offset().top,
            left:input.offset().left,
            width:self.options.detectWidth?input.width():"",
            position:'absolute'
        }).addClass("hide").addClass(self.options.specialClass).appendTo(document.body);

        /* attach fn to handle autocomplete to the input */
        input.focus(function(){
            if(self.enabled){
                self.input = $(this);
                self.value = self.input.val();
                if(!self.options.disableClear)self.input.val('');
                self.setTimeout();
                self.interval = setInterval(function(){
                    self.handleAutoComplete();
                },500);
            }
        });

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

                /* restore initial value if user enters nothing */
                if(self.input.val() === '' && !self.options.disableClear ){ self.input.val(self.value); }
            }
        });

        /* */
        input.keydown(function(event){
            if(self.enabled){
                self.renewTimeout();
                /* Enter */
                if(event.keyCode == 13){
                    var selected = $(self.div).find(".hover:first");
                    if(selected.length > 0){
                        self.populate(selected);
                    }
                }
                /* Down */
                if(event.keyCode == 40){
                    var suggestions = getSuggestionsRelativeToInput();
                    if(suggestions.length > 0){
                        var selected = $(suggestions).find(".hover:first");
                        if(selected.length == 0){
                            $(suggestions).find("li:first").addClass("hover");
                        }
                        else{
                            selected.removeClass("hover");
                            selected = selected.next();
                            selected.addClass("hover");
                        }
                    }
                }
                /* Up */
                if(event.keyCode == 38){
                    var suggestions = getSuggestionsRelativeToInput();
                    if(suggestions.length > 0){
                        var selected = $(suggestions).find(".hover:first");
                        if(selected.length > 0){
                            selected.removeClass("hover");
                            selected = selected.prev();
                            selected.addClass("hover");
                        }
                    }
                }
                /* Esc */
                if(event.keyCode == 27){
                    self.hide();
                }
            }
        });

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

    }

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

