/*
* Friend suggester box.
*/


var friend_suggester_obj = {};

function friend_suggester_simple(inputEL,onSelect,onEnter,onDatabaseLoaded)
{
    this.inputEL = inputEL || null;
    this.callback_onSelect = onSelect || null;
    this.callback_onEnter = onEnter || null;
    this._init();
}

friend_suggester_simple.prototype._init = function()
{

    this.uid = gen_unique();

    this.select_pos = -1;


    if(!this.inputEL.id)
	this.inputEL.id = 'fss-inputEL-id-'+gen_unique();

    try{
	if(!this.inputEL.style)
	    this.inputEL.setAttribute(style,'');
	this.inputEL.setAttribute('autocomplete','off');
	this.inputEL.setAttribute('disableautocomplete',true);
    }catch(ex){}

    this.build_suggester();


    this.init_events();

    this.database = [];

    this._friend_list_loaded = false;

    this.get_friend_list();


    this.search_build_checker();


    /*this.data*/

    this.render_suggester();

    /* for debug */
    /**
    var debugEL = document.createElement('div');
    onloadRegisterHandler(function(){ document.body.insertBefore(debugEL,document.body.firstChild);  });
    this.debugEL = debugEL;
	**/
    return this;
};

friend_suggester_simple.prototype.get_friend_list=function()
{
    
    if(typeof friend_suggester_obj.friend_list != 'undefined'){
	this.database = friend_suggester_obj.friend_list;
	this._friend_list_loaded = true;
	return friend_suggester_obj.friend_list;
    }

    var ajax = new fbAjax();
    ajax.onDone = function(obj,text){
	try{
	    friend_suggester_obj.friend_list = eval('('+text+')');

	    this.database = friend_suggester_obj.friend_list;

	    this._friend_list_loaded = true;

	    this.build_regexp_string();

	    this.database = [];
	    this.render_suggester();
	    
	    if(this.inputEL.is_focused)
		this.show_suggester();

	}catch(ex){alert(ex);}
    }.bind(this);
    ajax.onFail = function(obj){
	//alert(obj.transport.responseText);
    };

    ajax.post('/friends/ajax/get_list.ue','method=GetFriendList');

    return this;
};

friend_suggester_simple.prototype.use_iframe = function()
{
    return true;
};

friend_suggester_simple.prototype.build_suggester=function()
{
    var listboxEL = document.createElement('div');
    
    listboxEL.id = 'fss-listbox-'+this.uid;
    listboxEL.setAttribute('style','');
    listboxEL.style.zIndex = 120;
    listboxEL.style.position = 'absolute';
    listboxEL.style.display = 'none';
    listboxEL.style.textAlign = 'left';
    listboxEL.style.left = '-10000px';
    listboxEL.style.top = '-10000px';


    listboxEL.style.width = this.inputEL.offsetWidth + 'px';
    //listboxEL.style.height = '100px';
    listboxEL.style.backgroundColor = '#fff';

    onloadRegisterHandler(function(){ document.body.appendChild(listboxEL); });

    this.listboxEL = listboxEL;

    if(this.use_iframe())
	this.build_iframe();


    listboxEL.the_instance = this;

    try{
	this.inputEL.the_instance = this;
    }catch(ex){}

    return this;
};
friend_suggester_simple.prototype.build_iframe=function()
{
    var iframe = document.createElement('iframe');
  
    iframe.setAttribute('style','');
    iframe.style.zIndex = 110;
    iframe.frameBorder='0';
    iframe.style.position='absolute';
    iframe.style.display = 'none';
    iframe.style.top = iframe.style.left = '0px';

    /**filter:alpha(opacity=0);*/
    if("opacity" in iframe.style){
	iframe.style.opacity=0;
    }else if("MozOpacity" in iframe.style){
	iframe.style.MozOpacity=0;
    }else if("filter" in iframe.style){
	iframe.style.filter="alpha(opacity=0)";
    }

    onloadRegisterHandler(function(){ document.body.appendChild(iframe); });
    
    this.iframe = iframe;

    

    return this;
};

friend_suggester_simple.prototype.fix_suggester_position=function(norefix)
{
    
    try{

    var xy = GetPageOffset(this.inputEL);
    var w = this.inputEL.offsetWidth;
    var h = this.inputEL.offsetHeight;

    var winh = GetWindowHeight(window);
  
    this.listboxEL.style.top = Math.floor(xy.y + h - 1) + 'px';
    this.listboxEL.style.left = Math.floor(xy.x) + 'px';
    this.listboxEL.style.width = w + 'px';


    var itemsEL = ge(this.items_wrapper_id);
    
    itemsEL.style.width = (w-2)+'px';

    var items_height = Math.ceil(itemsEL.scrollHeight);

	var winScrollTop = GetScrollTop(window);

	//alert(winScrollTop);

	var hspace = Math.floor(winh - (xy.y - winScrollTop) - h - 10);
    
    //alert(hspace+'-'+items_height);
    //itemsEL.style.height = Math.ceil(itemsEL.scrollHeight)+'px';


    var ih = Math.min(items_height , hspace);
    
    itemsEL.style.height = ih + 'px';

    if(typeof itemsEL.scroll_event_inited == 'undefined'){
	/**
	var x = document.createElement('div');
	x.id = 'debug';
	document.body.insertBefore(x,document.body.firstChild);
	addEventBase(itemsEL,'scroll',function(e){ ge('debug').innerHTML = this.scrollTop; });
	itemsEL.scroll_event_inited = true;
	**/
    }

    if(this.use_iframe()){
	var bw = this.listboxEL.offsetWidth;
	var bh = this.listboxEL.offsetHeight;
	this.iframe.style.width = bw + 'px';
	this.iframe.style.height = bh + 'px';
	this.iframe.style.top = Math.floor(xy.y + h -1) + 'px';
	this.iframe.style.left = Math.floor(xy.x) + 'px';
    }

    if(!norefix){
	setTimeout(function(){ this.fix_suggester_position(true); }.bind(this),100);
    }

    }catch(ex){}

    return this;
};

friend_suggester_simple.prototype.close_suggester = function()
{
    this.listboxEL.style.display = 'none';
    if(this.use_iframe())
	this.iframe.style.display = 'none';
    return this;
};

friend_suggester_simple.prototype.show_suggester = function()
{

    if(this._last_select_item_time && new Date().getTime() - this._last_select_item_time < 500
       && this.inputEL.value == ''
      ) {
	this.close_suggester();
	return this;
    }

    this.listboxEL.style.display = 'block';
    if(this.use_iframe())
	this.iframe.style.display = '';

    this.fix_suggester_position();


    return this;
};


friend_suggester_simple.prototype.init_events = function()
{

    var onShow = function(e){
	stopPropagation(e);

	if(typeof friend_suggester_obj.friend_list != 'undefined'){
	    if(this.database.length == 0){

		if(Trim(this.inputEL.value)){
		    this.search_start_input();
		}else{
		
		    this.database = friend_suggester_obj.friend_list;
		    this.render_suggester();
		}
		
	    }
	}

	this.show_suggester();
    }.bind(this);

    var onClose = function(e){
	this.close_suggester();
    }.bind(this);

    var onFocus = function(e){
	this.inputEL.is_focused=1;

	if(this._friend_list_loaded){
	    this.database = [];
	    this.render_suggester();
	    this.show_suggester();
	}
    }.bind(this);
    var onBlur = function(e){
	this.inputEL.is_focused=0;
    }.bind(this);
    
    addEventBase(this.inputEL,'focus',onFocus);

    addEventBase(this.inputEL,'click',onShow);

    addEventBase(this.listboxEL,'click',function(e){ stopPropagation(e); });
    
    addEventBase(document,'click',onClose);

    addEventBase(window,'resize',function(e){ this.fix_suggester_position(); }.bind(this));
    //addEventBase(document.documentElement,'scroll',function(e){ alert('OO');});

    var onKeyUP = function(e){
	e = e || window.event;
	this.event_onkeyup(e);
	return false;
    }.bind(this);
    addEventBase(this.inputEL,'keyup',onKeyUP);

    var onKeyDown = function(e){
	e = e || window.event;
	this.event_onkeydown(e);

	return false;
    }.bind(this);
    addEventBase(this.inputEL,'keydown',onKeyDown);


    this.inputEL.onchange = function(){
	this.search_start_input();
    }.bind(this);
    
    return;
};

friend_suggester_simple.prototype.render_suggester=function()
{

    var uid = this.uid;

    var icon_prefix = 'uicon-'+uid;

    this.items_wrapper_id = 'items-wrapper-'+uid;

    var flist = this.database;

    var html = [''];

    html.push( '<div style="border:1px solid #bdc7d8;border-top:0px solid #ddd;"><div id="'+this.items_wrapper_id+'" style="" class="user_suggest_items">');


    for(var i=0;this._friend_list_loaded && i<flist.length;i++){
	var f = flist[i];

	html.push('<div class="user_suggest_item'+(i == 0 ? ' user_suggest_item_first':'')+'"');
	html.push(' onmouseover="friend_suggester_simple.get_instance(this).suggest_item_MOVE('+i+');"');
	//html.push(' onmouseout="RemoveClass(this,\'user_suggest_item_MO\')"');
	html.push(' onclick="friend_suggester_simple.get_instance(this).select_item('+i+');"');
	html.push(' id="user_suggest_item_'+uid+'_'+i+'"');
	html.push('>');
	html.push('<table cellpadding="0" cellspacing="0" width="100%"><tbody><tr>');
	
	html.push('<td class="usi_nickname">'/*<div>*/);
	html.push(this.suggest_item_format(f.nickname));
	html.push(/*</div>*/'</td>');

	html.push('<td class="usi_icon"><div style="height:30px;width:45px;text-align:left;" id="'+icon_prefix+i+'">&nbsp;</div>');
	html.push('</td>');

	html.push('</tr></tbody></table>');
	html.push('</div>');
    }


    if(!this._friend_list_loaded){

	html.push('<div style="background-color:#eee;padding:3px 5px;"><em>正在加载好友数据...</em></div>');

    }else{

    
	if(flist.length == 0){ 

	    var key = this.inputEL.value;


	    if(typeof friend_suggester_obj.friend_list != 'undefined' 
	       && friend_suggester_obj.friend_list.length == 0){

		html.push('<div style="background-color:#eee;padding:3px 5px;">你还没有好友！</div>');

	    }else{

		if(!Trim(key)){

		    html.push('<div style="background-color:#eee;padding:3px 5px;">输入好友名字，或者<br>点击输入框显示所有好友！</div>');

		}else{

		    html.push('<div style="background-color:#eee;padding:3px 5px;">'
			      +HtmlEscape(Trim(key))+'不是你的好友！</div>');
		}
	    }

	}

    }

    html.push('</div></div>');


    //html.push('<scr'+'ipt type="text/javascript"> setTimeout(\'friend_suggester_icon_render("'+icon_prefix+'");\',100); </scr'+'ipt>');
    
    set_inner_html(this.listboxEL,html.join(''));
};

friend_suggester_simple.prototype.suggest_item_format=function(nickname)
{
    var key = Trim(this.inputEL.value);
    if(!key)
	return HtmlEscapeInsertWbrs(nickname,10,'','');

    var n = nickname.replace(new RegExp("("+regexp_escape(key)+")","ig"),"<wbr><b class=\"k\">$1</b><wbr>");

    return n;
};

friend_suggester_simple.prototype.get_the_items_box=function()
{
    return this.listboxEL.firstChild.firstChild;
}

friend_suggester_simple.prototype.select_item = function(idx)
{

    this.select_pos = idx;

    if(this.database[idx]){
	var theObj = this.database[idx];
	if(this.callback_onSelect)
	    this.callback_onSelect(theObj);
    }else{
	if(this.callback_onEnter)
	    this.callback_onEnter(this.inputEL.value);
    }

    this.close_suggester();

    this.inputEL.value = '';
    this.input_old_value = '';
    this.database = [];

    this._last_select_item_time = new Date().getTime();

    return this;
};

friend_suggester_simple.prototype.suggest_item_MOVE = function(idx)
{

    this.suggest_item_MU(this.select_pos);

    this.select_pos = idx;

    this.suggest_item_MO(idx);
    
    return this;
};

friend_suggester_simple.prototype.select_item_down = function(dir)
{

    var flist = this.database;

    if(dir != -1)
	dir = 1;

    this.select_pos+=dir;

    if(dir > 0)
	this.select_pos = Math.min(this.select_pos,flist.length-1);
    else
	this.select_pos = Math.max(-1,this.select_pos);


    this.locate_the_select_item(dir);
    
    return this;
};
friend_suggester_simple.prototype.select_item_up = function()
{
    return this.select_item_down(-1);
};
friend_suggester_simple.prototype.select_item_scrollTo=function(y)
{
    var Lbox = this.get_the_items_box();
    
    try{ Lbox.scrollTop = y; }catch(ex){}

    return this;
};
friend_suggester_simple.prototype.select_item_pagedown=function(dir)
{
    if(dir != -1)
	dir = 1;

    var flist = this.database;

    var bh = this.listboxEL.offsetHeight;
    var Lbox = this.get_the_items_box();

    if(Lbox.scrollHeight > bh){
	
	var oldScrollTop = Lbox.scrollTop;
	
	var toScrollTop;
	if(dir>0)
	    toScrollTop = Math.min(Lbox.scrollHeight - bh,Math.ceil(oldScrollTop + bh));
	else
	    toScrollTop = Math.max(0,Math.floor(oldScrollTop - bh));

	this.select_item_scrollTo(toScrollTop);

	/* calc the pos */
	
	var pos = Math.min(flist.length-1,
	    Math.max(0,Math.floor((Lbox.scrollTop + bh /2) / Lbox.scrollHeight * flist.length)));

	var dltHeight = Lbox.scrollTop + bh - Lbox.scrollHeight;


	/**this.debugEL.innerHTML = dltHeight;**/

	/* move to end */
	if(dltHeight < 3 && dltHeight > -3){
	    pos = flist.length-1;
	}

	/* move to start */
	if(Lbox.scrollTop < 3)
	    pos = 0;

	this.suggest_item_MOVE(pos);

    }

    return this;
};
friend_suggester_simple.prototype.select_item_pageup=function()
{
    return this.select_item_pagedown(-1);
};
friend_suggester_simple.prototype.select_item_scrollToHome=function()
{
    this.select_item_scrollTo(0);
    this.select_item_pageup();
};
friend_suggester_simple.prototype.select_item_scrollToEnd=function()
{
    var Lbox = this.get_the_items_box();
    var y = Math.floor(Lbox.scrollHeight -3);
    this.select_item_scrollTo(y);
    this.select_item_pagedown();
};
friend_suggester_simple.prototype.suggest_item_MO=function(idx)
{
    var id = 'user_suggest_item_'+this.uid+'_'+idx;
    try{
	var el = ge(id);
	AddClass(el,'user_suggest_item_MO');
    }catch(ex){}
    return this;
};
friend_suggester_simple.prototype.suggest_item_MU=function(idx)
{
    var id = 'user_suggest_item_'+this.uid+'_'+idx;
    try{
	var el = ge(id);
	RemoveClass(el,'user_suggest_item_MO');
    }catch(ex){}
    return this;
};
friend_suggester_simple.prototype.locate_the_select_item=function(dir)
{
    var flist = this.database;
    
    var start = Math.max(0,this.select_pos-3);
    var end = Math.min(this.select_pos+3,flist.length-1);
    for(var i=start;i<=end;i++){
	if(i == this.select_pos)
	    this.suggest_item_MO(i);
	else
	    this.suggest_item_MU(i);
    }

    if(this.select_pos < 0)
	return this;


    /* scroll the box up/down */

    var curEL = ge('user_suggest_item_'+this.uid+'_'+this.select_pos);

    var bxy = GetPageOffset(this.listboxEL);
    var ixy = GetPageOffset(curEL);
    
    var bh = this.listboxEL.offsetHeight;

    var Lbox = this.get_the_items_box();

    var itop = Math.floor(ixy.y);
    var ibottom = Math.ceil(ixy.y + curEL.offsetHeight);

    if(dir>0){
	
	if(ibottom > bxy.y + bh + Lbox.scrollTop){
	    Lbox.scrollTop = Math.min(Lbox.scrollHeight,Math.ceil(ibottom - bxy.y - bh));
	}
	
    }else{
	
	if(itop < bxy.y+Lbox.scrollTop){
	    Lbox.scrollTop = Math.max(0,Math.ceil(itop - bxy.y));
	}
    }
    
    /**
    this.debugEL.innerHTML = 'box{x:'+bxy.x+',y:'+bxy.y+',h:'+bh+',sT:'+Lbox.scrollTop+'} item{yT:'+itop+',yB:'+ibottom+'}';
**/

    return this;
};

friend_suggester_simple.prototype.build_regexp_string=function()
{
    var flist = friend_suggester_obj.friend_list;

    var regexps = [];
    for(var i=0;i<flist.length;i++){
	regexps.push(flist[i].nickname.replace(/\r?\n/,'')+'[%'+i+'%]');
    }
    regexps.push('');

    friend_suggester_obj.regexps_string = regexps.join('\n');

    //alert(friend_suggester_obj.regexps_string);

    return this;
};


friend_suggester_simple.prototype.event_onkeyup=function(e)
{

    var key_code = EV_GetKeyCode(e);

    /**alert(key_code);**/

    switch(key_code){
    case 40:case 38:
    case 34:case 33:
    case 36:case 35:
	
    case 13:case 9:
	return this;
	break;
    default:
	break;
    }    

    this.search_start_input();
    return this;
};

friend_suggester_simple.prototype.event_onkeydown=function(e)
{
    
    var key_code = EV_GetKeyCode(e);

    /**alert(key_code);**/

    switch(key_code){
    case 40:
	this.select_item_down();
	break;
    case 38:
	this.select_item_up();
	break;
    case 34: /* page down */
	this.select_item_pagedown();
	break;
    case 33: /* page up */
	this.select_item_pageup();
	break;
    case 36: /* home */
	this.select_item_scrollToHome();
	break;
    case 35: /* end */
	this.select_item_scrollToEnd();
	break;
    case 13:
    case 9:
	
	this.select_item(this.select_pos);
	//alert('enter');
	//stopPropagation(e);
	event_prevent(e);
	setTimeout('ge("'+this.inputEL.id+'").focus()',10);
	break;
    default:
	break;
    }
    
    return this;
};

/* --- for search --- */
friend_suggester_simple.prototype.search_start_input=function()
{
    //this._search_last_input_timestamp = (new Date()).getTime();
    return this;
};

friend_suggester_simple.prototype.search_build_checker=function()
{
    if(typeof this._search_checker_time_hdl == 'undefined'){
	this._search_checker_time_hdl = setInterval(function(){ this.search_checker(); }.bind(this),100);
    }
    return this;
};
friend_suggester_simple.prototype.search_checker=function()
{
    //var now = (new Date()).getTime();

    /*
    if(this._search_last_input_timestamp && now - this._search_last_input_timestamp > 80){
	this._search_last_input_timestamp = null;
*/

    if(!this.input_old_value){
	this.input_old_value = '';
    }
    
    var new_value = this.inputEL.value;
    
    if( new_value != this.input_old_value){
    
	this.input_old_value = new_value;

	var n = this.search();

	if(n>0){
	    this.render_suggester();

	    this.show_suggester();

	    this.suggest_item_MOVE(0);
	}else{
	    
	    if(!Trim(this.inputEL.value) && typeof friend_suggester_obj.friend_list != 'undefined' ){
		// do not render all list,too slow.
		// this.database = friend_suggester_obj.friend_list;
	    }

	    this.render_suggester();
	    this.show_suggester();
	    this.suggest_item_MOVE(-1);
	}
	
    }
    
    return this;
};
/*
* search from the friend list ,return result length.
*/
friend_suggester_simple.prototype.search=function(key)
{
    if(!key){
	key = Trim(this.inputEL.value);
    }

    /**this.debugEL.innerHTML = key;**/

    var result=[];


    if(!key){
	this.database = result;
	return 0;
    }


    try{
	var rt = new RegExp(""+regexp_escape(key)+".*?\\[%(\\d+)%\\]","ig");

	//alert(rt);
	var m = friend_suggester_obj.regexps_string.match(rt);

	for(var i=0;m && i<m.length;i++){
	    
	    var index = m[i].replace(/^.*\[%(\d+)%\].*$/,"$1")*1;
	    
	    if(typeof friend_suggester_obj.friend_list[index] != 'undefined'){
		result.push(friend_suggester_obj.friend_list[index]);
	    }

	}


	/**this.debugEL.innerHTML += result;**/

    }catch(ex){
	alert(ex);

	return 0;
    }


    if(result.length || 1){
	this.database = result;
    }

    return result.length;
};

/* ----- utilits ----- */
function friend_suggester_icon_render(prefix)
{
    var flist = this.database;
    for(var i=0;i<flist.length;i++){
	setTimeout('set_inner_html(ge("'+prefix+i+'"),\'<img src="'+flist[i].buddyicon+'" style="width:30px;height:30px;border:0;" />\');',100);
    }
}

friend_suggester_simple.get_instance = function(el)
{
    var e = el;
    var loop = 20;
    while( e && typeof e.the_instance == 'undefined' && loop-- > 0){
	e = e.parentNode;
    }

    return e.the_instance;
};