# ****************************************************************************
# Surgeweb Addressbook autocompletion, taken directly from webmail implementation. 
#  and sourcing data from surgeplus!!
# Needs to be tidied up and redundant functions etc removed for surgeweb implementation.
# BUT it seems to work fine without any changes so that is real nice!!
# ****************************************************************************


#// Autocomplete implementation for webmail and wmail
#// Author: Marijn Weehuizen		Dec 2006

#// Data pertaning to currently active autocompletion
var autocomplete;

var init_autocomplete=ac_pageload;

var use_cache=false;
var use_shortlist=false;
var cache_array=[];

var max_adr=7;

ac_scriptload();

// ----------------------------
// -- Initialisation --
// ----------------------------
function ac_scriptload(){
#	address_book = new Object;
	autocomplete = new Object;
	cache_array[1]= new Object; // cache;	// autocomplete cache
}
function ac_pageload(){
	var x;
	x=dge('to_field'); 
	if (x) ac_register_ctl(x, "default source");	
	x=dge('cc_field');
	if (x) ac_register_ctl(x, "default source");	
	x=dge('bcc_field') 
	if (x) ac_register_ctl(x, "default source");	
#	if(!address__book.data){
#		// invalid check as it matches empty address book. dogh!
#		//download_addressbook();
#	}
	autocomplete.selected=0;
}
function ac_register_ctl(ctl,src){
	if (ctl==U) return;
	add_event(ctl,'keydown',ac_keydown);
	add_event(ctl,'blur',ac_blur);
	add_event(ctl,'focus',ac_focus);
}
function download_addressbook()
{
	alert("starting background abk download (unimplemented)");
}

// ----------------------------
// -- Autocompletion event handling --
// ----------------------------

function ac_keydown(e) {
	if (!e) var e=window.event;
	generalise_event_info(e);
	var defaults=true;
	switch(e.keyCode)
	{
		case 188: // COMMA
		case 186: // SEMICOLON
			if (e.shiftKey){
				ac_defaultkey(e)
				break;			
			}
			// drop through to tab
		case  vkTab:
			if (ac_docomplete(e))
				defaults=false;
			break;
		case vkEnter:
			if (!ac_docomplete(e)){
				focus_next_surgeweb_edit_ctl(target(e));
			}
#			stopEvent(e);
			defaults=false;
			break;
		case vkEsc:
			ac_escape(e);
			defaults=false;
			break;
		case vkUpArrow:
		case vkDownArrow:
			ac_arrowkey(e)
			break;
		case vkLeftArrow:
		case vkRightArrow:
		default:
			ac_defaultkey(e)
			break;
	}
	if (!defaults) stopEvent(e);
	return defaults;
}
function ac_blur(e) { 
	need_vcheck=false;
	var t=target(e)
	dbg('***** AC ac_blur');
	if(t /*&& !pref.no_fancy_rcpt*/){
		var txt = e.value;
		ac_docomplete(e,true);
	}
	ac_hide(autocomplete);
	if(need_vcheck) vcheck_run();
}
function ac_focus(e) { 
	if (!e) var e=window.event;
	generalise_event_info(e);
	ac_defaultkey(e); 
}

function ac_dd_mousemove(e) {
	if (!e) var e=window.event;
	generalise_event_info2(e);
	var x=se(e);
	if (x.id.indexOf('i_')!=0) x=x.parentNode;
	if (x.id.indexOf('i_')!=0) return;
	var ac=autocomplete;
	ac.selected=x.id.substr(2);
	ac_show(ac.ctl,ac);
}
function ac_dd_mouseup(e) {
	if (!e) var e=window.event;
	generalise_event_info2(e);
	var x=se(e);
	if (x.id.indexOf('i_')!=0) x=x.parentNode;
	if (x.id.indexOf('i_')!=0) return;
	var ac=autocomplete;
	ac.selected=x.id.substr(2);
# 	now action on blur?!
#	ret=ac_complete(ac.ctl,ac,',',true);
	focus_ctl=ac.ctl;
	dbg('***** AC ac_dd_mouseup');	
	setTimeout('return_focus();',10);
}
function ac_dd_focus(e) {
	if (!e) var e=window.event;
	generalise_event_info2(e);
	var x=se(e);
	if (x.id.indexOf('ac')!=0) return;
	var ac=autocomplete;
	ac.cancelhide=true;
}
function ac_dd_blur(e) {
	if (!e) var e=window.event;
	generalise_event_info2(e);
	var x=se(e);
	if (x.id.indexOf('ac')!=0) return;
	var ac=autocomplete;
	ac_hide(ac);
}

var focus_ctl;
function return_focus(){
	dbg('***** AC return_focus');	
	var oldpos=cursor_position(focus_ctl);
	setCaretPosition(focus_ctl,oldpos>0?oldpos:9999);
}

var ac_timer;
// -- Core autocomplete functionality --
function ac_defaultkey(e){
	// run main ac trough timer to catch multiple keys and provide us access to
	// text area contents
	if (ac_timer) clearTimeout(ac_timer);
	ac_timer=setTimeout('ac_defaultkey_delayed("'+e.target.id+'")',200);
	autocomplete.ctl=e.target;
}
function ac_defaultkey_delayed(id){
	ac_timer=null;
	var ac=autocomplete;
	var textarea=dge(id);
	if (textarea.value.length==0) return ac_hide(ac);
	var posn=cursor_position(textarea);
	if(posn==0) return ac_hide(ac);
	var txt=relevantText(textarea.value,posn);
	if(txt.length==0 || txt==' ') return ac_hide(ac);
	var ac_c;
	if(sw.is_popup)
		ac_c=sw_win.ac_lookup_string(txt, sw_win.abooks, ac);
	else
		ac_c=ac_lookup_string(txt, abooks, ac);
	if (ac_c==U) return ac_hide(ac);
	
	ac_show(textarea,ac);
}
// -- Additional autocomplete functionality --
function ac_arrowkey(e){
	var new_selected = autocomplete.selected + (e.keyCode==38?-1:+1);
	if (new_selected<0 || new_selected>autocomplete.displayed_length)
		return;
	autocomplete.selected=new_selected;
	ac_show(e.target,autocomplete);
}

function ac_escape(e){
	var ac=autocomplete;
	ac_hide(ac);
}

function ac_docomplete(e, nofocus){
	var ac=autocomplete;
	dbg('***** AC ac_docomplete NOFOCUS='+nofocus);
	ret=ac_complete(target(e),ac,',',U,nofocus);
	ac_hide(ac);
	if (ret && !nofocus){
		focus_ctl=ac.ctl;
		setTimeout('return_focus();',10);
	}
	return ret;
}


// ----------------------------
// --- Addressbook lookup ---
// ----------------------------

// --- lookup autocomplete data (optionally cached, retrieve data on demand?) ---
function ac_lookup_string(lookup_text,db,ac)
{
    lookup_text=lookup_text.toLowerCase();
    var e=split_address(lookup_text);
    var name=e[0], email=e[1];
    if(!name&&!email) return 0;
    var ret=[];
    ret.name=name; ret.email=email;
	if(!use_cache){
		ret.match=abk_match_addresses(db,ret.name,ret.email);
	}else{
		var mycache=cache_array[1];
		var q=mycache.find(lookup_text);
		if(l){
			ret.match=q;
		}else{
			for(var i=lookup_text.length-1;i>0;i--){
				var n=lookup_text.substr(0,i);
				q=mycache.find(n);
				if(q) break;
			}
			var db=(q!=null)?q:abk.data;
			ret.match=abk_match_addresses(db,ret.name,ret.email);
			mycache.add(lookup_text,result)
		}
	}
    ac.search=ret;
    if(!ret.match || !ret.match[0]) return U;
    return ret.match[0].c;
}

// --- autocomplete actual data comparison ---
function abk_match_addresses(db,qname,qemail)		//QQAB
{
	var bk,i,j,c,dat,order,ret,rb,len,n,g,ii;
	ret=[];
	
#	Search the user's own addressbook, ordered by most used addresses first
	bk=db['User'];
	if(!bk) return ret;
	dat=bk.data;
	order=bk.ac_order;
	for(i=0;i<order.length;i++){
		c=dat[order[i]];
		if(!abk_match_one(c,qname,qemail)) continue;
		for(n=0;n<c.email.length;n++){
			len=ret.length;
			ret[len]={'c':c,'n':n}
			if(len>max_adr) return ret;
		}
	}
	for (ii in bk.groups){
		g=bk.groups[ii];
		if(!abk_gmatch_one(g,qname)) continue;
		ret[ret.length]={'c':{group:true, name:{first:g.name, last:''}, email:[{type:'work',value:'group'}]},'n':0}
		if(len>max_adr) return ret;
	}
	
# 	Search extra addressbooks you may have access to in the order the addresses are in the book
	rb=abooks.read_books;
	for(j=0;j<rb.length;j++){
		if(rb[j]=='User')continue;
		
		bk=db[rb[j]];
		dat=bk.data;
		for(var i=0;i<dat.length;i++){
			var c=dat[i]
			if(!abk_match_one(c,qname,qemail)) continue;
			for(n=0;n<c.email.length;n++){
				len=ret.length;
				let new_c = {'c':c,'n':n}
				if(ac_exists(ret,new_c)) continue;
				ret[len] = new_c;
				if(len>max_adr) return ret;
			}
		}
		for (ii in bk.groups){
			g=bk.groups[ii];
			if(!abk_gmatch_one(g,qname)) continue;
			if(g.name==bk.name){
				var g_name = g.name;
			}else{
				var g_name = g.name +' ('+bk.name+')';
			}
			let new_c = {'c':{group:true, name:{first:g_name, last:''}, email:[{type:'work',value:'group'}]},'n':0}
			if(ac_exists(ret,new_c)) continue;
			ret[ret.length] = new_c;
			if(len>max_adr) return ret;
		}
	}	
	return ret;
}
function ac_exists(list, c)
{
	for(ii in list){
		let el = list[ii];
		if(c_name(el.c) == c_name(c.c) && c_email(el.c)==c_email(c.c)) {
			return true;
		}
	}
	return false;
}

function abk_match_one(c,qname,qemail)
{
	if(!c.email) return false;
	
	var email=c_email(c).toLowerCase();
	if(qemail && email.indexOf(qemail)==0) return true;

	var fullname=c_name(c).toLowerCase();
	var nickname=c.nick.toLowerCase();
	var company=c.company&&c.company.value?c.company.value.toLowerCase():'';
	if(qname){
		if(fullname && mystrstr(fullname,qname)>=0 ) return true;
		if(use_shortlist&&nickname && mystrstr(nickname,qname)>=0 ) return true;
		if(email.indexOf(qname)==0) return true;
		if(company.indexOf(qname)==0) return true;
	}
	
	return false
}
function abk_gmatch_one(g,qname,qemail)
{
	if(qname.length==0 || g.contacts.length==0) return false;
	var n = g.name.toLowerCase();
	if(n.indexOf(qname)==-1) return false;
	return true;
}

// --- Actual display of the appropriate autocomplete div ---
function ac_show(ctl,ac)
{
    var data=[];
    var mymatch=ac.search.match;
    var total_adr=mymatch.length;
	if (total_adr==0)
		return;
    if(ac.selected>=total_adr) 
    	ac.selected=total_adr-1;

    var txt;
    for(var i=0;i<total_adr&&i<max_adr;i++){
        var c=mymatch[i]['c'];
        var n=mymatch[i]['n'];
        if (use_shortlist&&(c.nick!=c_email(c,n)) && c.shortlist) {
        	txt=bold_substring(c.nick,ac.search.name);
        }else{
        	txt=format_entry(c,n,ac.search);
        }
        var tmp1="";
        var tmp2="";
		if(i==ac.selected) tmp1=" sel";
		ac.displayed_length=i;
		data.push('<span style="'+tmp2+'" class="l'+tmp1+'" id="i_'+i+'">'+txt+"</span>");
    }
 	var dropdown=get_element("ac");    
 	if (!dropdown.ac_init){
		add_event(dropdown,'mousemove',ac_dd_mousemove);		
		add_event(dropdown,'mousedown',ac_dd_mouseup);		
		add_event(dropdown,'focus',ac_dd_focus);		
		add_event(dropdown,'blur',ac_dd_blur);		
 		dropdown.ac_init='true';
 	}
    dropdown.innerHTML=data.join('');
	pos_dropdown_by_ctl(dropdown,ctl)
	ac.active=true;
}

// --- do the autocompletion ---
function ac_complete(ctl,ac,sep,mouse,nofocus) 
{
	dbg('***** AC ac_complete');
	var new_address;
	var txt=ctl.value;
	var posn=cursor_position(ctl);
	var ret = false;
	var is_group = false;
    if(ac.active) {
    	var ac_result = ac.search.match[ac.selected]
		is_group = ac_result.c.group
		new_address=ac_format_address(ac_result);
		dbg('***** AC ac_complete NEWADDRESS 1 ='+new_address);
		ret = true;
	}else{
		if(txt.length==0 || txt==' ' || pref.no_fancy_rcpt) return ret;
		new_address=txt;
		dbg('***** AC ac_complete NEWADDRESS 1B ='+new_address+' txt=['+txt+']');
		need_vcheck=true;
	}
	var cur=get_current_chunk(txt,posn,find_quoted_chunks(txt));
	dbg('***** AC ac_complete posn='+posn+' txt=['+encode_lt_gt(txt)+'] cur='+cur+' subs=['+encode_lt_gt(txt.substring(cur[0]))+']');
	
	var sep2="";
	if(cur[1]==txt.length || txt.charAt(cur[1])!="," && txt.charAt(cur[1])!=";")
		sep2=sep+" ";

	dbg('***** AC ac_complete NEWADDRESS 2 ='+new_address+' sep2=['+sep2+']');

	var new_txt=txt.substring(0,cur[0])+new_address+sep2+txt.substring(cur[1]);
	var new_posn=cur[0]+new_address.length+sep2.length;

	if (ctl.id == 'cal_popover_invitees'){
		if(is_group){
			ctl.value = cp_expand_group(new_address);
		}else{
			ctl.value = new_address;
		}
		attendee_check_pending(ctl);
	} else if (!ctl.edit_fancy){
		dbg('***** AC ac_complete PLAIN_TEXT newtext='+new_txt);
		ctl_set(ctl,new_txt,new_posn,nofocus);
	}else{
		var o=ctl.parentNode;
		var node=cl_add_contact(text2contact(new_address, is_group),0,o);
		vcheck_run();
		hcheck_trigger();
		ctl.value='';
	}
	return ret;
}

// --------------------------------------
// -- Autocomplete supporting functionality ---

function relevantText(all_text,cursor_posn){
    var quoted_chunks=find_quoted_chunks(all_text);						// returns array of begin/end pairs
    var chunk=get_current_chunk(all_text,cursor_posn,quoted_chunks);
    var tmp=all_text.substring(chunk[0],chunk[1]);
    return tmp.replace(/\"/g,"")
}
function format_entry(c,n,srch){
    var name,email;
    name=clean_whitespace(c_name(c,n));
    if(name!=''){
    	name=replace_quotes(name);
    	email=' <'+c_email(c,n)+'>';
    }else{
    	name='';
    	email=c_email(c,n);
    }
 	var result = '';
    if(c.group!=U && false){
    	result = bold_substring(name,srch.name)
    } else {
    	result = bold_substring(name,srch.name) + bold_substring(email,srch.email?srch.email:srch.name);
    }
    return result;
}
function bold_substring(a,b){
    if(b!=""){
        var c=mystrstr(a.toLowerCase(),b);
        if(c!=-1){
            return xencode(a.substr(0,c))+"<b>"+xencode(a.substr(c,b.length))+"</b>"+xencode(a.substr(c+b.length))
        }
    }
    return xencode(a)
}

function ac_hide(ac){
	ac.cancelhide=false;
	setTimeout('hide_now();',50);
}
function hide_now(){
	var ac=autocomplete;
	if(ac.cancelhide==true) return;
	ac.active=false;
	ac.selected=0;
	hide("ac");
}

function ac_format_address(cc){
    var name=c_name(cc.c);
    name=clean_whitespace(name);
    if(cc.c.group){
    	var result = name;
    }else{
	    var result = (name!=''?name+' ':"")+"<"+c_email(cc.c,cc.n)+">";
    }
	return result;
}
function ctl_set(ctl,txt,posn,nofocus){
    ctl.value=txt;
    if(nofocus) return;
    ctl_set_cursor(ctl,posn);
}
function ctl_set_cursor(ctl,posn){
    if(def(ctl.selectionEnd)&&def(ctl.selectionStart)){
        ctl.selectionStart=posn;
        ctl.selectionEnd=posn
    } else if(document.selection&&ctl.createTextRange){
        var r=ctl.createTextRange();
        r.collapse(true);
        r.move("character",posn);
        r.select()
    }
}

// ---



