/**
* Gets array of contacts from server on page loading.
*
* @return Array(Object) ATTANTION! Receiver must be named as "adress_book" because "jQuery.autocomplete" use this variable. 
* 						"jQuery.autocomplete" does not get the "adress_book" in @params because it could be too large for copy.
*						So "jQuery.autocomplete" use reference to "adress_book" which was created in global(window) context.
*/

jQuery.sc_autocomplete = function(input, options) {
    // Create a link to self
    var me = this;

// Create jQuery object for input element
    var $input = $(input).attr("autocomplete", "off");

    // Apply inputClass if necessary
    if (options.inputClass) $input.addClass(options.inputClass);

    // Create results
    var results = document.createElement("div");
    // Create jQuery object for results
    var $results = $(results);
    $results.hide().addClass(options.resultsClass).css("position", "absolute");
    if( options.width > 0 ) $results.css("width", options.width);

    // Add to body element
    $("body").append(results);

    input.autocompleter = me;

    var supposed = [];
    var formated = [];
    var timeout = null;
    var prev = "";
    var active = 0;
    var keyb = false;
    var hasFocus = false;
    var lastKeyPressCode = null;
    var curContPos = -1;

    $input
    .keydown(function(e) {
        // track last key pressed
        lastKeyPressCode = e.keyCode;
        switch(e.keyCode) {
            case 38: // up
                e.preventDefault();
                moveSelect(-1);
                break;
            case 40: // down
                e.preventDefault();
                moveSelect(1);
                break;
            case 9:  // tab
                if( selectCurrent() ){
                    // make sure to blur off the current field
                    $input.get(0).blur();
                    $input.focus();
                    e.preventDefault();
                }
                break;
            case 13: // return
                if( selectCurrent() ){
                    return false;
                    //e.preventDefault();
                }
                break;
            default:
                active = -1;
                if (timeout) clearTimeout(timeout);
                timeout = setTimeout(function(){
                    onChange();
                }, options.delay);
                break;
        }
    })
    .keypress(function(e){
        //textarea must ignore "return" key!
        if(e.keyCode==13)
            return false;
        else true;
    })
    .focus(function(){
        // track whether the field has focus, we shouldn't process any results if the field no longer has focus
        hasFocus = true;
    })
    .blur(function() {
        // track whether the field has focus
        hasFocus = false;
        hideResults();
    });

    hideResultsNow();
	
    function checkShow(){
        /*$('#log3').text($('#log3').text()+"lastKeyPressCode: "+lastKeyPressCode+" OTHERCODE: " + $input.val().toUpperCase().charCodeAt($input.val().length-1) +"(" + $input.val().charAt($input.val().length-1) +")|||");//this is debug*/
        if(lastKeyPressCode==8)
            return true;
        var str = $.trim($input.val());//user can set carriage before several spaces in the end, but one can't see them.
        return (lastKeyPressCode == str.toUpperCase().charCodeAt(str.length-1));
    }

    function getCurContact(){
        curContPos = $input.val().lastIndexOf(",");
        if(curContPos == -1)
            return $input.val();
        return $.trim($input.val().substring(curContPos+1));
    }
    function onChange() {
        // ignore if the following keys are pressed: [del] [shift] [capslock]
        if( !checkShow() || lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide();
        var v = getCurContact();
        /*$('#log2').text($('#log2').text()+"\nANALIZED PART: "+v);//this is debug*/
        if (v == prev) return;
        prev = v;
        if (v.length >= options.minChars) {
            $input.addClass(options.loadingClass);
            requestData(v);
        } else {
            $input.removeClass(options.loadingClass);
            $results.hide();
        }
    };

    function moveSelect(step) {

        var lis = $("li", results);
        if (!lis) return;

        active += step;

        if (active < 0) {
            active = 0;
        } else if (active >= lis.size()) {
            active = lis.size() - 1;
        }

        lis.removeClass("ac_over");

        $(lis[active]).addClass("ac_over");

    // Weird behaviour in IE
    // if (lis[active] && lis[active].scrollIntoView) {
    // 	lis[active].scrollIntoView(false);
    // }

    };

    function selectCurrent() {
        var li = $("li.ac_over", results)[0];
        if (!li) {
            var $li = $("li", results);
            if (options.selectOnly) {
                if ($li.length == 1) li = $li[0];
            } else if (options.selectFirst) {
                li = $li[0];
            }
        }
        if (li) {
            selectItem(li);
            return true;
        } else {
            return false;
        }
    };

    function selectItem(li) {
        if (!li) {
            li = document.createElement("li");
            li.selectValue = -1;
        }
        var v = "";
        if(options.data[li.selectValue].name.length>0)
            v = '"' + options.data[li.selectValue].name + '" <' + options.data[li.selectValue].email + '>, ';
        else
            v = '<' + options.data[li.selectValue].email + '>, ';
        input.lastSelected = v;
        prev = v;
        $results.html("");
        if(curContPos != -1)
            $input.val($input.val().substring(0,curContPos+1) +" "+v);
        else
            $input.val(v);
        hideResultsNow();
        if (options.onItemSelect) setTimeout(function() {
            options.onItemSelect(li)
        }, 1);
    };

    function showResults() {
        // get the position of the input field right now (in case the DOM is shifted)
        var pos = findPos(input);
        // either use the specified width, or autocalculate based on form element
        var iWidth = (options.width > 0) ? options.width : $input.width();
        // reposition
        moveSelect(0);
        $results.css({
            width: parseInt(iWidth) + "px",
            top: (pos.y + input.offsetHeight) + "px",
            left: pos.x + "px"
        }).show();
    };

    function hideResults() {
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(hideResultsNow, 200);
    };

    function hideResultsNow() {
        if (timeout) clearTimeout(timeout);
        $input.removeClass(options.loadingClass);
        if ($results.is(":visible")) {
            $results.hide();
        }
        if (options.mustMatch) {
            var v = $input.val();
            if (v != input.lastSelected) {
                selectItem(null);
            }
        }
    };

    function receiveData(q) {
        if (supposed) {
            $input.removeClass(options.loadingClass);
            results.innerHTML = "";

            // if the field no longer has focus or if there are no matches, do not display the drop down
            if( !hasFocus || supposed.length == 0 ) return hideResultsNow();

            if ($.browser.msie) {
                // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
                $results.append(document.createElement('iframe'));
            }
            results.appendChild(dataToDom());
            showResults();
        } else {
            hideResultsNow();
        }
    };

    function dataToDom() {
        var ul = document.createElement("ul");
        var num = supposed.length;

        // limited results to a max number
        if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow;

        for (var i=0; i < num; i++) {
            var li = document.createElement("li");
            if(i%2==0) $(li).addClass("ac_odd");
            if(formated[i].name.length>0)
                li.innerHTML = '"' + formated[i].name + '" &lt;' + formated[i].email + "&gt;";
            else
                li.innerHTML = '&lt;' + formated[i].email + "&gt;";
            li.selectValue = supposed[i];
            ul.appendChild(li);
            $(li).hover(
                function() {
                    $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0));
                },
                function() {
                    $(this).removeClass("ac_over");
                }
                ).click(function(e) {
                e.preventDefault(); e.stopPropagation(); selectItem(this)
            });
        }
        return ul;
    };
	

	
    function requestData(q) {
        //check index was selected to supposed
        function alreadySupposed(index){
            for(var i=0;i<supposed.length;i++){
                if(supposed[i]==index)
                    return true;
            }
            return false;
        }
        if (!options.matchCase)
            q = q.toLowerCase();
        supposed = [];
        formated = [];
        /*$('#log1').text($('#log1').text()+"\nCURRENT_VALUE: "+q);//this is debug*/
        //check emails
        for(var i=0;i<options.data.length;i++){
            if(options.data[i].email.toLowerCase().indexOf(q)==0){
                var tmp = {
                    name:"",
                    email:""
                };
                tmp.email = q.bold() + options.data[i].email.substr(q.length);
                tmp.name = options.data[i].name;
                supposed.push(i);
                formated.push(tmp);
            }
        }
        //check first names
        for(var i=0;i<options.data.length;i++){
            if(options.data[i].name.toLowerCase().indexOf(q)==0 && !alreadySupposed(i)){
                var tmp = {
                    name:"",
                    email:""
                };
                var f_q = q.charAt(0).toUpperCase() + q.substr(1);
                tmp.name = f_q.bold() + options.data[i].name.substr(f_q.length);
                tmp.email = options.data[i].email;
                supposed.push(i);
                formated.push(tmp);
            }
        }
        //check last names
        for(var i=0;i<options.data.length;i++){
            name_parts = options.data[i].name.split(" ");
            if(name_parts[1] && name_parts[1].toLowerCase().indexOf(q)==0 && !alreadySupposed(i)){
                var tmp = {
                    name:"",
                    email:""
                };
                var f_q = q.charAt(0).toUpperCase() + q.substr(1);
                tmp.name = name_parts[0] + " " + f_q.bold() + name_parts[1].substr(f_q.length);
                tmp.email = options.data[i].email;
                supposed.push(i);
                formated.push(tmp);
            }
        }
        receiveData(q);
    };


	
    function findPos(obj) {
        var curleft = obj.offsetLeft || 0;
        var curtop = obj.offsetTop || 0;
        while (obj = obj.offsetParent) {
            curleft += obj.offsetLeft
            curtop += obj.offsetTop
        }
        return {
            x:curleft,
            y:curtop
        };
    }
}

jQuery.fn.sc_autocomplete = function(options) {
    /*for(var i=0;i<adress_book.length;i++){
		$('div').text($('div').text() + '"' + adress_book[i].name + '"' + '<' + adress_book[i].email + '>|||||||');
	}*/
    // Make sure options exists
    options = options || {};
    // set some bulk local data
    options.data = ((typeof adress_book == "object") && (adress_book.constructor == Array)) ? adress_book : null;

    // Set default values for required options
    options.inputClass = options.inputClass || "ac_input";
    options.resultsClass = options.resultsClass || "ac_results";
    options.minChars = options.minChars || 1;
    options.delay = options.delay || 400;
    options.matchCase = options.matchCase || 0;
    options.loadingClass = options.loadingClass || "ac_loading";
    options.maxItemsToShow = options.maxItemsToShow || -1;
    options.width = parseInt(options.width, 10) || 0;

    this.each(function() {
        var input = this;
        new jQuery.sc_autocomplete(input, options);
    });

    // Don't break the chain
    return this;
}

function clearManySpaces(str) {
    var pos = str.indexOf('  ');
    if(pos!=-1) return str.replace('  ',' ');//clearManySpaces(str.substr(0,pos) + str.substr(pos+1));
    return str;
}

function cleanEmail(em){
    while(em.indexOf('>')>-1 || em.indexOf('<')>-1){
        em = em.replace("<", '');
        em = em.replace(">", '');
        em = $.trim(em);
    }
    return em;
}

function buildEmailFormat(obj){
    if(!Boolean(typeof obj.email!='undefined' && obj.email)) return "";
    var ret = "";
    if(Boolean(typeof obj.name!='undefined' && obj.name)) ret += '"'+obj.name+'" ';
    ret += "<"+obj.email+">";
    return ret;
}

function cleanName(nm){
    //nm = nm.replace("'", '');
    while(nm.indexOf('"')>-1)
        nm = nm.replace('"', '');
    nm = $.trim(nm);
    return nm;
}
jQuery.fn.getReceivers = function() {
    var $input = $(this).attr("autocomplete", "off");
    if($input && ($input.val().length > 0)){
        var str = $.trim($input.val());
        //if(str.charAt(str.length-1)==',')//delete ',' in the end of string, if it is here.
        //    str=str.substr(0,str.length-1);
        var receivers_strs = clearManySpaces(str).split(',');
        var receivers = [];
        var subitems = [];
        for(var i=0;i<receivers_strs.length;i++) {
            var cur_rec = receivers_strs[i];
            cur_rec = $.trim(cur_rec);
            if(cur_rec==null || cur_rec=="" || cur_rec==undefined || cur_rec.toLowerCase()=="optional") continue;
            cur_rec.replace("&quot;", '"');
            cur_rec.replace("&lt;", '<');
            cur_rec.replace("&gt;", '>');
            subitems = cur_rec.split('<');

            var tmp = { name: "", email: "" };
            var errs = new Array('Wrong format in contact: '+cur_rec);
            var nm = em = "";
            
            // no name in email string
            if(subitems.length==1){
                em = cleanEmail(subitems[0]);
            }
            else if(subitems.length==2){
                nm = cleanName(subitems[0]);
                em = cleanEmail(subitems[1]);
            }
            else return errs[0];

            if(validateEmail(em)){
                tmp.email = em;
                tmp.name = nm;
                receivers.push(tmp);
            }
            else return errs[0];

        }//for

       var result = new Array();
       var found = false;
        for(var i in receivers){
            for(var k in result){
                found = false;
                if(result[k].email==receivers[i].email){
                    if(result[k].name=="" && receivers[i].name!="")
                        result[k].name=receivers[i].name;
                    found = true;
                    break;
                }
            }
            if(!found) result.push(receivers[i]);
        }
        receivers = result;
        return receivers;
    }
    return new Array();
}

jQuery.fn.indexOf = function(e){
    for( var i=0; i<this.length; i++ ){
        if( this[i] == e ) return i;
    }
    return -1;
};
