function Search(sid, inp, settings, url) {
    var oThis = this;
    
    this.settings = {min_length: 1};
    this.cache = {}; // Кеш за търсенето
    this.pre_cache = null;
    this.last_search = {};
    this.index = -1;
    this.url = url ? url : '/search/ajax_handle.do?action=suggest';
    
    this.time_out = null;
    
    !settings && (settings = {});
    extend(settings, this.settings);
    
    this.init = function () {
        inp.old_onkeydown = inp.onkeydown;
        inp.onkeydown = function (e) {
            settings.onkeydown && settings.onkeydown(e);
            oThis.move(e);
            if(inp.old_onkeydown) inp.old_onkeydown();
        }
        
        inp.old_onkeyup = inp.onkeyup;
        inp.onkeyup = function (e) {
            settings.onkeyup && settings.onkeyup();
            oThis.checkEvent(e, this);
            if(inp.old_onkeyup) inp.old_onkeyup();
        }
        
        inp.old_onblur = inp.onblur;
        inp.onblur = function (e) {
            settings.onblur && settings.onblur(oThis);
            
            if(oThis.suggest_panel) {
                if(oThis.chekcTarget(e)) return false;
                
                oThis.time_out && clearTimeout(oThis.time_out);
                oThis.time_out = setTimeout(function () {hide(oThis.suggest_panel.parentNode)}, 300);
            }
            if(inp.old_onblur) inp.old_onblur();
        };
        
        inp.old_onfocus = inp.onfocus;
        inp.onfocus = function () {
            settings.onfocus && settings.onfocus();
            if(inp.old_onfocus) inp.old_onfocus();
        }
        
        document.body.onclick = function (e) {
            if(oThis.suggest_panel) {
                if(oThis.chekcTarget(e)) return true;
                
                if(oThis.time_out) clearTimeout(oThis.time_out);
                oThis.time_out = setTimeout(function () {hide(oThis.suggest_panel.parentNode)}, 300);
            }
        };
        
        inp.setAttribute("autocomplete", "off");
        
        if(settings['onblur_c']) {
            inp.onblur = function(e) {
                if(!e) e = window.event;
                
                //console.log(oThis.exact_match);
                if(oThis.exact_match > -1 && inp.value != '') {
                    var rows = oThis.suggest_panel.getElementsByTagName('div');
                    
                    oThis.select(oThis.pre_cache['data'][oThis.exact_match]);
                    
                    oThis.suggest_panel && hide(oThis.suggest_panel.parentNode);
                } else {
                    //console.log('index: '+oThis.index);
                    if(oThis.suggest_panel) {
                        var rows = oThis.suggest_panel.getElementsByTagName('div');
                        
                        if(oThis.index == -1 || inp.value == '' || rows.length == 1 && rows[0].innerHTML.indexOf('no suggestions') > -1) {
                            //console.log('reset');
                            inp.ids = 0;
                        }
                    }
                }
            }
        }
        
        this.inp = inp;
        if(settings['cache_only']) {
            this.pre_cache = new Object();
            extend(this.pre_cache, settings['cache']);
        }
    }
    
    this.chekcTarget = function (e) {
        if (!e) e = window.event;
        
        var targ = (e.target) ? e.target : ((e.srcElement) ? e.srcElement : ((targ.nodeType == 3) ? targ.parentNode : null));
        if(this.is_in(targ, this.suggest_panel)) {
            return true;
        }
        
        return false;
    }
    
    this.is_in = function (obj, in_obj) {
        while(obj) {
            if(obj === in_obj) return true;
            obj = obj.parentNode;
        }
        
        return false;
    }
    
    this.move = function (e) {
        if (!e) e = window.event;
        
        var key_code = e.keyCode || e.which;
        
        switch(key_code) {
            case 38: this.move_up(); stopEvent(e); break; //UP
            case 40: this.move_down(); stopEvent(e); break; //DOWN
            case 27: this.suggest_panel && hide(this.suggest_panel.parentNode); break;
        }
        
        return true;
    }
    
    this.checkEvent = function (e, inp) {
        if (!e) e = window.event;
        
        var key_code = e.keyCode || e.which;
        
        
        if(key_code >= 65 || key_code == 32 || key_code == 8 || (key_code > 45 && key_code < 58)) {
            // Правим търсене и показваме панела
            this.ShowSearch(inp.value);
        }
        
        if(key_code == 13 || key_code == 46 || settings.separator && (key_code == settings.separator || key_code == 8)) {
            var rows = oThis.suggest_panel.getElementsByTagName('div');
            
            if (
                oThis.index >= 0 &&
                rows[oThis.index] &&
                (
                    rows[oThis.index].s_type == 'users' ||
                    rows[oThis.index].s_type == 'serials' ||
                    rows[oThis.index].s_type == 'data'
                ) ||
                settings.separator && (key_code == settings.separator || key_code == 8 || key_code == 46)) {
                
                stopEvent(e);
                var res = false;
                
                if(oThis.index > -1 && rows[oThis.index]) res = rows[oThis.index].onclick(e);
                else if(settings.select) {res = settings.select(null, this, key_code, inp);}
                
                return res;
            }    
        }
    }
    
    this.ShowSearch = function (search) {
        if(search && search.length >= settings.min_length) {
            if(!this.cache[search] && !this.pre_cache) {
                this.getSuggestions(search, inp);
            } else {
                this.showSuggestions(this.cache[search] || this.pre_cache, inp, search);
            }
        } else {
            this.suggest_panel.innerHTML = '';
            this.suggest_panel && hide(this.suggest_panel.parentNode);
        }
        
    }
        this.getSuggestions = function(search, inp) {
            var request = {
                url: this.url,
                data: {
                    search: search
                },
                onSuccess: function (res) {
                    var list = eval('('+res+')');
                    
                    if(!list) list = {'video': new Array(), 'users': new Array()};
                    
                    oThis.cache[search] = list;
                    oThis.showSuggestions(list, inp, search);
                },
                onFailure: function (res) {
                    oThis.showTip();
                }
            };
            AJAX(request);
        }
    
    this.createConteinter = function () {
        if(!this.suggest_panel) {
            var cont = document.createElement('div');
            
            this.shadow = document.createElement('div');
            this.suggest_panel = document.createElement('div');
            
            cont.className = 'suggest-list';
            
            this.shadow.className = 'shadow';
            
            this.suggest_panel.className = 'list';
            this.suggest_panel.innerHTML = '';
            
            cont.appendChild(this.shadow);
            cont.appendChild(this.suggest_panel);
            
            this.suggest_panel.onclick = function (e) {
                if(!e) e = window.event;
                stopEvent(e);
                
                if(oThis.time_out) clearTimeout(oThis.time_out);
                
                return false;
            }
            
            if(settings.cont) $(settings.cont).appendChild(cont);
            else if (document.body.firstChild.nodeType == 1) document.body.firstChild.appendChild(cont);
            else nextNode(document.body.firstChild).appendChild(cont);
        }
    }
    
    this.showSuggestions = function(list, inp, search) {
        this.createConteinter();
        
        var found = true;
        
        this.exact_match = -1;
        
        if(list &&
            ((list['video'] && list['video'].length > 0) ||
             (list['users'] && list['users'].length > 0) ||
             (list['data'] && list['data'].length > 0) ||
             (list['serials'] && list['serials'].length > 0))) {
            
            show(this.suggest_panel.parentNode);
            
            this.suggest_panel.parentNode.style.top = findPosY(inp)+inp.clientHeight+'px';
            this.suggest_panel.parentNode.style.left = findPosX(inp)+'px';
            
            this.suggest_panel.innerHTML = '';
            
            this.last_search = new Array();
            
            if(list['video']) {
                var row = document.createElement('p');
                row.className = 'no-top';
                row.innerHTML = '<b>Videoclipuri</b>';
                this.suggest_panel.appendChild(row);
                
                for(var i=0; i<list['video'].length; i++) {
                    var row = document.createElement('div'),
                        exp = '(?:^|[\s\(\)\.\,]+)?('+RegExp.escape(search.trim())+')';
                        regExp = new RegExp(exp, 'gi');
                    
                    row["s_type"] = 'video';
                    row["data"] = list['video'][i];
                    row["index"] = i;
                    row.innerHTML = list['video'][i].replace(regExp, '<strong>$1</strong>');
                    row.onclick = function () { oThis.select(this.data, this.index); settings.select && settings.select() || inp.form.submit(); };
                    row.onmouseover = function () { this.className = 'sel'; };
                    row.onmouseout = function () { this.className = ''; }
                    
                    this.suggest_panel.appendChild(row);
                    
                    this.last_search.push(list['video'][i]);
                }
            }
            
            if(list['users']) {
                var row = document.createElement('p');
                row.innerHTML = '<b>Users</b>';
                this.suggest_panel.appendChild(row);
                
                for(var i=0; i<list['users'].length; i++) {
                    var row = document.createElement('div'),
                        exp = "(^|[\.\,\(\)]+)("+RegExp.escape(search.trim())+')';
                        regExp = new RegExp(exp, 'gi');
                    
                    row["s_type"] = 'users';
                    row["data"] = list['users'][i]['title'];
                    row["data_usr"] = list['users'][i]['usr'];
                    row["data_"] = list['users'][i];
                    row["index"] = i;
                    row.innerHTML = list['users'][i]['title'].replace(regExp, '$1<strong>$2</strong>');
                    row.onclick = function (e) {
                        if(!e) e = window.event;
                        
                        stopEvent(e);
                        if(settings.user_handler) settings.user_handler(this.data_);
                        else location.href='/'+this.data_usr;
                        return false;
                    };
                    row.onmouseover = function () { this.className = 'sel'; };
                    row.onmouseout = function () { this.className = ''; }
                    
                    this.suggest_panel.appendChild(row);
                    
                    this.last_search.push(list['users'][i]['title']);
                }
            }
            
            
            if(list['serials']) {
                var row = document.createElement('p');
                row.innerHTML = '<b>Seriale</b>';
                this.suggest_panel.appendChild(row);
                
                for(var i=0; i<list['serials'].length; i++) {
                    var row = document.createElement('div'),
                        exp = "(^|[\.\,\(\) ]+)("+RegExp.escape(search.trim())+')';
                        regExp = new RegExp(exp, 'gi');
                    
                    row["s_type"] = 'serials';
                    row["data"] = list['serials'][i]['title'];
                    row["data_"] = list['serials'][i];
                    row["index"] = i;
                    row.innerHTML = list['serials'][i]['title'].replace(regExp, '$1<strong>$2</strong>');
                    row.onclick = function (e) {
                        location.href='/serials/browse.do?sid='+this.data_['id'];
                        inp.form.action = '/serials/browse.do?sid='+this.data_['id'];
                        if(!e) e = window.event;
                        stopEvent(e);
                        
                        return false;
                    };
                    row.onmouseover = function () { this.className = 'sel'; };
                    row.onmouseout = function () { this.className = ''; }
                    
                    this.suggest_panel.appendChild(row);
                    
                    this.last_search.push(list['serials'][i]['title']);
                }
            }
            
            if(list['data']) {
                found = false;
                
                var exp = "(^|[\.\,\(\) ]+)("+RegExp.escape(search.trim().split(",").pop().trim() || search.trim())+')';
                
                for(var i=0; i<list['data'].length; i++) {
                    var row = document.createElement('div'),
                        regExp = new RegExp(exp, 'gi');
                    
                    if(!regExp.test(list['data'][i]['title']) && search.trim().length > 0) continue;
                    
                    found = true;
                    
                    if(search.trim() == list['data'][i]['title']) {
                        this.exact_match = i;
                    }
                    
                    row["s_type"] = 'data';
                    row["data"] = list['data'][i];
                    row["index"] = i;
                    row.innerHTML = list['data'][i]['title'].replace(regExp, '$1<strong>$2</strong>');
                    row.onclick = function () { settings.select && settings.select(this.data, oThis, null, inp) || oThis.select(this.data, this.index, true) || inp.form.submit(); hide(oThis.suggest_panel.parentNode) };
                    row.onmouseover = function () { this.className = 'sel'; };
                    row.onmouseout = function () { this.className = ''; }
                    
                    this.suggest_panel.appendChild(row);
                    
                    this.last_search.push(list['data'][i]);
                }
            }
            
            if(!found) {
                this.index = -1;
                if(search.trim().split(",").pop().trim().length > 0) {
                    show(this.suggest_panel.parentNode);
                    
                    this.suggest_panel.parentNode.style.top = findPosY(inp)+inp.clientHeight+'px';
                    this.suggest_panel.parentNode.style.left = findPosX(inp)+'px';
                    
                    this.suggest_panel.innerHTML = '';
                    var row = document.createElement('div');
                    
                    row.innerHTML = 'no suggestions for <strong>'+search.trim().split(",").pop().trim()+'</strong>';
                    this.suggest_panel.appendChild(row);
                } else {
                    hide(this.suggest_panel.parentNode);
                }
            }
            
            
        } else {
            show(this.suggest_panel.parentNode);
            
            this.suggest_panel.parentNode.style.top = findPosY(inp)+inp.clientHeight+'px';
            this.suggest_panel.parentNode.style.left = findPosX(inp)+'px';
            
            this.suggest_panel.innerHTML = '';
            var row = document.createElement('div');
            
            row.innerHTML = 'no suggestions for <strong>'+search+'</strong>';
            this.suggest_panel.appendChild(row);
        }
        
        this.shadow.style.height = this.suggest_panel.clientHeight + 'px';
        this.shadow.style.width = this.suggest_panel.clientWidth + 'px';
    }
    
    this.showTip = function () {
        this.createConteinter();
        
        show(this.suggest_panel.parentNode);
        
        this.suggest_panel.parentNode.style.top = findPosY(inp)+inp.clientHeight+'px';
        this.suggest_panel.parentNode.style.left = findPosX(inp)+'px';
        
        this.suggest_panel.innerHTML = '';
        var row = document.createElement('div');
        
        row.innerHTML = 'type 3 or more leters';
        this.suggest_panel.appendChild(row);
        
        this.shadow.style.height = this.suggest_panel.clientHeight + 'px';
        this.shadow.style.width = this.suggest_panel.clientWidth + 'px';
    }
    
    this.select = function (data, index, rtr) {
        if(typeof(data) == 'object') {
            inp.value = data.title;
            inp.ids = data.id;
        } else {
            inp.value = data;
        }
        
        if(index) {
            this.index = index;
            inp.focus();
        }
        
        return rtr || false;
    }
    
    this.move_down = function () {
        if(!this.suggest_panel) return false;
        
        var max = this.last_search.length,
            rows = this.suggest_panel.getElementsByTagName('div');
        
        if (this.index < max) {
            if(this.index >= 0 && rows[this.index]) {
                rows[this.index].className = '';
            }
            
            if(rows[++this.index]) {
                rows[this.index].className = 'sel';
            } else {
                this.index = 0;
                rows[this.index].className = 'sel';
            }
        }
        
        if(rows[this.index]) this.select(rows[this.index].data);
        
        //oThis.search_panel && oThis.search_panel[rows[this.index].s_type].onclick(null, true) && hide(oThis.search_panel);
    }
    
    this.move_up = function () {
        if(!this.suggest_panel) return false;
        
        var max = this.last_search.length,
            rows = this.suggest_panel.getElementsByTagName('div');
        
        if (this.index > 0) {
            if(this.index >= 0 && rows[this.index]) {
                rows[this.index].className = '';
            }
            
            rows[--this.index].className = 'sel';
        } else {
            rows[0].className = '';
            this.index = max-1;
            rows[this.index].className = 'sel';
        }
        
        if(rows[this.index]) this.select(rows[this.index].data);
        
        //oThis.search_panel && oThis.search_panel[rows[this.index].s_type].onclick(null, true) && hide(oThis.search_panel);
    }
}


function MultiSearch(suggestions) {
    
    this.init = function (inp_list) {
        for(var i=0; i<inp_list.length; i++) {
            (new Search('', inp_list[i], {
                min_length: 1,
                cache_only: 1,
                onblur_c: 1,
                cache: suggestions
            })).init();
        }
    }
}