
function ElAutoComplete(input, options){
    $.extend(this, options);
    this.key = input;
    this.input = $("#" + input);
    this.init();
    this.ajaxManager = $.manageAjax({manageType: 'abortOld', maxReq: 1, blockSameRequest: true});
}

var KEY = {
    UP          : 38,
    DOWN        : 40,
    LEFT        : 37,
    RIGHT       : 39,
    DEL         : 46,
    TAB         : 9,
    RETURN      : 13,
    ESC         : 27,
    COMMA       : 188,
    PAGEUP      : 33,
    PAGEDOWN    : 34,
    BACKSPACE   : 8,
    SPACE       : 32
};

ElAutoComplete.prototype =
{
    delay: 200, // Delay for ajax query
    target : '/ajax.php',

    /**
     * Dispay results options
     */
    settings : {
        
        cities : false
        
    },

    /**
     * Contains search result element (p)
     */
    items : [],

    /**
     * Align of the autocomplete results
     * left | right | xRight(left of results on right of input)
     */
    align: 'left',

    /**
     * Align verticaly the the result relatively to his top
     * bottom | middle | top (TODO)
     */
    vAlign: 'bottom',
    /**
     * Class for container
     */
    className : '',

    /**
     *Class for input when loading
     */
    loadingClass : 'loading',

    /**
     * Current selected item
     */
    selected : null,

    /**
     * Submenu
     */
    submenu : null,

    /**
     * If set to true, if the input is inside a form tag, the form will be submited
     * ENTER key press
     */
    submitOnReturn : false,
    
    init : function()
    {
        var _this = this;

        /*
         * Result container
         */
        this.results = $("<div class='homeSearchContainer homeSearchResults " + this.key + "'></div>");
        $(document.body).prepend(this.results);
        this.input.css({position:'static'});

        this.input.blur(function(event){
            _this.hide();
            return false;
        });
        
        /*
         * Events
         */
        this.input.keydown(function(event)
        {
            switch(event.keyCode)
            {
                case KEY.UP:
                    event.preventDefault();
                    _this.movePrev();
                    break;

                case KEY.DOWN:
                    event.preventDefault();
                    _this.moveNext();
                    break;

                case KEY.PAGEUP:
                    _this.moveFirst();
                    break;
                    
                case KEY.PAGEDOWN:
                    _this.moveLast();
                    break;
                    
                case KEY.ESC:
                    _this.hide();
                    break;

                case KEY.TAB:
                	if (_this.selected != null)
                        _this.selected.trigger('click');
                    _this.hide();

          
                    
                    break;
                case KEY.RETURN:
                    if (_this.selected != null)
                        _this.selected.trigger('click');
                    _this.hide();

                    if (!_this.submitOnReturn){
                        return false;
                    }
                    break;

                case KEY.SPACE:
                    break;
                    
                
                case KEY.LEFT:
                case KEY.RIGHT:
                    break;
                default:
                    _this.sendRequest();
            }
        });

        this.input.click(function(){
           if(this.ajax)
              _this.sendRequest();
        });
    },

    sendRequest : function()
    {
        var _this = this;
        if (this.input.val().length > 1 && this.input.val()!=""){
            this.input.addClass(_this.loadingClass);
            try{
              clearTimeout(requestTimeout);
            } catch(e){}
            requestTimeout = setTimeout(function(){
                _this.ajaxManager.add({
                    type: "post",
                    url : _this.target + '?ajax=' + _this.ajax,
                    data : {
                        keywords : _this.input.val(),
                        settings : $.toJSON(_this.settings)
                    },
                    success : function(response){
                        _this.results.html(response);
                        _this.results.show();
                        var offset = _this.input.offset();

                        // Aligning horizontally the result box
                        var left;
                        if (_this.align == 'left')
                            left = offset.left;
                        else if (_this.align == 'xRight')
                            left = offset.left + _this.input.width()+ 20;
                        else
                            left = offset.left - (_this.results.width()-_this.input.width());

                        // Aligning vertically the result box
                        var top;
                        if (_this.vAlign == 'middle')
                            top = offset.top - (_this.results.height()/2);
                        else
                            top = offset.top + _this.input.height()+10

                        // Position if the result box
                        _this.results.css({
                            zIndex:99000,
                            top: top,
                            left: left,
                            textAlign:'left'
                        });

                        $(function(){
                            var options = {
                                exact:"partial",
                                style_name_suffix:false,
                                highlight: '.homeSearchResults p',
                                nohighlight : ".not_highlightable",
                                keys:_this.input.val()
                            }
                            $('.homeSearchResults p').SearchHighlight(options);
                            _this.addItemEffects();
                            _this.items = _this.results.find(".item");
                        });
                        setTimeout(function(){
                            _this.input.removeClass(_this.loadingClass);
                        },500);
                    }
                });

            },_this.delay);
        } else {
            //this.results.empty();
            this.hide();
        }
    },

    hide : function(){
        var _this = this;
        try{
          clearTimeout(hideTimeout);
        } catch(e){}
        hideTimeout = setTimeout(function(){
            _this.results.hide();
        },350);
    },

    /**
     * Adds effects to mouse over actions
     */
    addItemEffects : function(){
        var _this = this;
        // Mouseover effect
        this.results.find(".item").each(function(){
            //
            $(this).mouseover(function(event){
                event.preventDefault();
                event.stopPropagation();
                _this.select($(this));
                //_this.showSubmenu($(this));
                // Shows submenu
                var item = $(this);
                try{
                    clearTimeout(expandTimeout);
                }catch(e){}
                expandTimeout = setTimeout(function(){
                    _this.showSubmenu(item);
                },350);
                return false;
            });
            $(this).mouseout(function(){
                _this.unselect($(this));
                return false;
            });
        });
        $('.item a.nyroModal').nyroModal();
    },

    /**
     * Selects the item (highlight)
     * @param jquery item
     */
    select : function(item){
        this.unselectAll();

        // Hide visible submenus
        try{
            // If parent is a submenu container
            if (!item.parent('div').hasClass('submenu'))
                this.hideSubmenu();
        } catch(e){};
    
        this.selected = item;
        item.addClass("homeSearchOver");
    },

    /**
     * Unselects item
     */
    unselect : function(item){
        //this.previous = item;
        this.selected = null;
        item.removeClass("homeSearchOver");
    },

    /**
     * Unselects all items
     */
    unselectAll : function(){
        var _this = this;
        this.items.each(function(){
            _this.unselect($(this));
        });
    },

    /**
     * Move to next item
     */
    moveNext : function()
    {
        var item;
        if (this.selected == null)
            item = this.results.find(".item:first");
        else {
            if(this.selected.next("* .item").length == 0)
                item = this.results.find(".item:first");
            else { 
                item = this.selected.next("* .item");
                if ($(item).attr('class') != 'item'){
                    item = this.selected.next("* .item").next("* .item");
                }
            }
        }
        this.unselectAll();
        this.select($(item));
    },

    /**
     * Move to previous item
     */
    movePrev : function()
    {
        var item;
        if (this.selected == null)
            item = this.results.find(".item:last");
        else {
            if(this.selected.prev("* .item").length == 0)
                item = this.results.find(".item:last");
            else {
                item = this.selected.prev("* .item");
                if ($(item).attr('class') != 'item')
                    item = this.selected.prev("* .item").prev("* .item");
            }
        }
        this.unselectAll();
        this.select($(item));
    },

    /**
     * Moves to last element
     */
    moveLast : function()
    {
        var item = this.results.find(".item:last");
        this.unselectAll();
        this.select($(item));
    },
    /**
     * Moves to last element
     */
    moveFirst : function()
    {
        var item = this.results.find(".item:first");
        this.unselectAll();
        this.select($(item));
    },

    /**
     * Displays the submenu if it exists
     * @param object item  Element to expand
     */
    showSubmenu : function(item)
    {
        this.submenu = item.next('.submenu');
        this.submenu.show();
    },

    hideSubmenu : function(){
        this.results.find('.submenu').hide();
    },

    ajaxRequest: function(bool){
        this.ajax = bool;
    },
    
    setTarget : function(target){
        this.target = target;
    },

    setSettings : function(settings){
        this.settings = settings;
    }
};
