var CCRelease =
{
	Version: '4.0.0',

	NULL: function()
	{
	},
	Create: function()
	{
		return function()
		{
			this.Constructor.apply(this, arguments);
		}
	}
};
Object.extend = function(Dest, Source)
{
	for (property in Source)
	{
		Dest[property] = Source[property];
	}
	return Dest;
};
Object.prototype.Extend = function(Obj)
{
	return Object.extend.apply(this, [this, Obj]);
};
//成员方法回调支持
//注意混淆时不能混淆view
Function.prototype.Bind = function(Obj)
{
	var Method=this,args=[];
	for(var i=1,len=arguments.length;i<len;i++)
	{
		args[i-1]=arguments[i];
	}
	return function(e) //firefox event
	{
		e&&e.view&&e.target?e.view.event=e:0;
		return Method.apply(Obj,!args.length?arguments:args);
	}
};
function GetSrcElement(_event){return _event? ((_event.srcElement)?_event.srcElement:_event.target):null;}
function Trim(str)
{
	return str.replace(/^\s+/g, "" ).replace(/\s+$/g, "" );
}
//CCRelease.AutoComplete是纯虚类，
//CCRelease.AutoCompleteAllAddr和CCRelease.AutoCompleteQQFriend是两个实例化的类
//CCRelease.AutoCompleteAllAddr自动完成的选择范围在整个地址本
//CCRelease.AutoCompleteQQFriend自动完成的选择范围只限于QQ好友
//用户可以通过重载GetAddrList，自行添加其他范围的自动完成类
CCRelease.AutoComplete = CCRelease.Create();
CCRelease.AutoComplete.prototype=
{
	//
	//改用iframe来装载自动完成表格，因为只有iframe才能遮盖iframe和其他可视化组件
	//Frame是指iframe的逻辑组件，FrameElement是指Frame的作为页面元素的表现物体，InputArea是要自动完成的输入框
	//ifLoadAtInit:是否初始化的时候加载.true:初始化时加载.false:默认,使用到时才加载(AddrFocusIn时)
	//如果传入的Frame和FrameElement是个没有加载过的ifrmae（即没有指定src)，那么
	//本来想改成只要调用者输入Input就可用的接口，但查阅msdn后发现frame和iframe不可动态创建，只能由调用者在外部建立后传进来
	Constructor:function()
	{ 
		ACHTMLFILE="../html/autocomplete_box.html";
		this.m_ShowedAC = false;		//层是否在显示的状态
		this.m_ACFrame = null;
		this.m_ACTable = null;
		this.m_ACFrameElement = null;
		this.m_AddrTextCtrl = null;	//最后一个启动自动完成的TEXT控件
		this.m_LastPatternAddr = null;	//搜索结果集中的匹配字串符
		this.m_AddrLineNo = -1;		//所选的记录在ACTable中的行号
		this.m_AddrList = [];
		this.m_isKeyEvent = false;
		this.m_isInEvent = false;
		this.DefaultTxt=new Object;
		this.DefaultCssText=new Object;
		this.ifSwitchDefaultTxt=false;
		this.ifSwitchDefaultCss = null;
		this.m_RightAlignWidth = null;	 //右对齐，并且偏移距
		this.m_bResultToFocus = false;
	},
	Init:function(InputArea,Frame,FrameElement,ifLoadAtInit,ifSwitchDefaultTxt,ifSwitchDefaultCss,ClickObj,RightAlignWidth,bResultToFocus)
	{
		this.m_isKeyEvent = false;
		this.m_isInEvent = false;
		this.m_AddrTextCtrl = InputArea;
		this.m_ACFrame = Frame;
		this.m_ACFrameElement = FrameElement;
		this.ifSwitchDefaultTxt = ifSwitchDefaultTxt;
		this.ifSwitchDefaultCss = ifSwitchDefaultCss;
		this.m_RightAlignWidth = RightAlignWidth;
		this.m_bResultToFocus = bResultToFocus;
		if(ifLoadAtInit)
		{
			this.LoadIFrame();
		}
		try
		{
			InputArea.onfocus=this.AddrFocusIn.Bind(this);
			InputArea.onblur=this.AddrFocusOut.Bind(this);
			InputArea.onkeydown=this.KeyDownEvent.Bind(this);
			InputArea.onkeyup=this.KeyUpEvent.Bind(this);
			InputArea.onkeypress=function(){if(window.event.keyCode==13) return false;};
			InputArea.autocomplete="off";
			this.DefaultTxt=InputArea.value;
			this.DefaultCssText=InputArea.style.cssText;
			if (ClickObj != null) ClickObj.onclick=this.ClickEvent.Bind(this);
		}catch(e)
		{
			alert(e.description);
		}
	},
	LoadIFrame:function()
	{
//		这两个属性似乎设置无效，还是需要在html里面定义
		this.m_ACFrameElement.src = ACHTMLFILE;
		this.m_ACFrameElement.Loaded =true;
	},
	GetTargetTextCtrl:function(){
		var TargetTextCtrl = null;
		if (this.m_bResultToFocus) try {TargetTextCtrl = S(GetFocus())} catch(e) {}
		return TargetTextCtrl ? TargetTextCtrl : this.m_AddrTextCtrl;
	},
	RemoveRepeatAddr:function()
	{
		var TargetTextCtrl = this.GetTargetTextCtrl();
		if(this.m_isInEvent || TargetTextCtrl == null )
		{
			return;
		}		
		if(this.m_isKeyEvent == true)
		{
			this.m_isKeyEvent = false;
			return;
		}
		if (window.FormatAddr)
		{
			this.m_isInEvent = true;
			PutTextareaValue(TargetTextCtrl, FormatAddr(TargetTextCtrl.value));
			this.m_isInEvent = false;
		}
	},
	GetDivPos:function(myElement)
	{
		var lElement = myElement;
		var ltop=lElement.offsetTop;
		var lleft=lElement.offsetLeft;
		var lwidth = lElement.offsetWidth;
		
		while(lElement = lElement.offsetParent)
		{
			ltop += lElement.offsetTop;
			lleft += lElement.offsetLeft;
		}
		this.m_ACFrameElement.style.left = this.m_RightAlignWidth != null ? (lleft + lwidth - parseInt(this.m_ACFrameElement.style.width) + parseInt(this.m_RightAlignWidth)) : (lleft-1);
		this.m_ACFrameElement.style.top = ltop + myElement.offsetHeight+1;
	},

	ShowAC:function()
	{
		if(this.m_ACTable.rows.length == 0)
		{
			return;
		}
		
		if(this.m_AddrLineNo == -1)
		{
			this.m_AddrLineNo = 0;
			this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd_on";
		}

		this.m_ACFrameElement.style.display = "";
		
		if(this.m_ACTable.offsetHeight > 354)
		{
			this.m_ACFrameElement.style.height = 354;
			this.m_ACFrameElement.style.width = this.m_ACTable.offsetWidth + 19;
		}else
		{
			this.m_ACFrameElement.style.height = this.m_ACTable.offsetHeight;
			this.m_ACFrameElement.style.width = this.m_ACTable.offsetWidth;
		}

		this.GetDivPos(this.m_AddrTextCtrl);

		this.m_ShowedAC = true;
	},

	//关闭自动完成窗口
	CloseAC:function()
	{
		if(this.m_AddrLineNo != -1 &&this.m_ACTable)
		{
			this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd";
		}
		
		this.m_ACFrameElement.style.display = "none";

		this.m_AddrLineNo = -1;
		this.m_ShowedAC = false;
	},

	AddrFocusIn:function()
	{
		try
		{
			if (!this.m_bResultToFocus) SetFocus(this.m_AddrTextCtrl.id);
		}catch(e){}
		if(!this.m_ACFrameElement.Loaded)
		{
			this.LoadIFrame();
		}
		if(this.ifSwitchDefaultTxt && this.m_AddrTextCtrl.value==this.DefaultTxt)
		{
			this.m_AddrTextCtrl.value="";
			this.m_AddrTextCtrl.style.cssText=this.ifSwitchDefaultCss ? this.ifSwitchDefaultCss : this.DefaultCssText;
		}
	},

	AddrFocusOut:function()
	{
		this.m_isKeyEvent = false;
		this.m_isInEvent = false;

		this.CloseAC();
		if(this.ifSwitchDefaultTxt && this.m_AddrTextCtrl.value=="")
		{
			this.m_AddrTextCtrl.value=this.DefaultTxt;
			this.m_AddrTextCtrl.style.cssText=this.DefaultCssText;
		}

		PutTextareaValue(this.m_AddrTextCtrl, FormatAddr(this.m_AddrTextCtrl.value));
	},
	MoveCursor:function(nFlag)
	{
		var LineNum = this.m_ACTable.rows.length;
		this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd";
		this.m_AddrLineNo = (this.m_AddrLineNo + nFlag +  LineNum) % LineNum;
		this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd_on";
		this.m_ACTable.rows[this.m_AddrLineNo].cells[0].scrollIntoView(false);
	},

	KeyDownEvent:function()
	{
		
		this.m_isKeyEvent = true;
		//↑=38,↓=40
		if (!this.m_ShowedAC)
		{
			return;
		}
		var KeyCode = window.event.keyCode;
		switch (KeyCode)
		{
			case 27:	//esc
				this.CloseAC();
				window.event.returnValue = false;
				return;
			case 38:
				this.MoveCursor(-1);
				break;
			case 40:
				this.MoveCursor(1);
				break;
		}
	},
	KeyUpEvent:function()
	{
		if (window.event.ctrlKey)
		{
			return;
		}
		if(!this.m_ACFrameElement.Loaded)
		{
			this.LoadIFrame();
		}
		if(!this.m_ACTable)
		{
			this.m_ACTable = this.m_ACFrame.document.getElementById("AutoCompleteTable");
			if(!this.m_ACTable){ return;};
		}
		var KeyCode = window.event.keyCode;
		var Pattern = this.GetPatternStr();
		switch(KeyCode)
		{
			case 32:			//按空格，显示全部地址
				this.GenACTable((Pattern=="")?" ":Pattern);
				this.ShowAC();
				//this.GenACTableByAddrList(Pattern,this.m_ACTable.rows.length);
				//this.ShowAC();
				break;
			case 13:		//回车
				if (this.m_ShowedAC)
				{
					this.SelectAddr();
					window.event.returnValue = false;
				}
				break;
			case 27:	//esc
			case 38:
			case 40:
				break;
			default:
				if(Pattern.length == 0)
				{
					this.CloseAC();
				}
				else
				{
					this.GenACTable(Pattern);
				}
				break;
		}
	},
	GenMailAddr:function(Index)
	{
		var item = this.m_AddrList[Index];
		//update
		return (item.GroupIdx==null)?this.m_AddrList[Index].Name :GetGroupMemberDetailListStr(item.GroupIdx);
	},
	SelectAddr:function()
	{
		if(this.m_AddrLineNo == -1)
		{
			return;
		}
		var AddrValue = this.m_AddrTextCtrl.value;
		var LastPos;
		var MailAddr;
		var Idx;
		this.m_isKeyEvent = false;
		LastPos = this.GetPatternPos(AddrValue) + 1;
		Idx = this.m_ACTable.rows[this.m_AddrLineNo].value;
		MailAddr = HtmlDecode(this.GenMailAddr(Idx));
		var PreAddr = "";
		var TargetTextCtrl = this.GetTargetTextCtrl();
		if (TargetTextCtrl == this.m_AddrTextCtrl)
		{
			PreAddr = AddrValue.substr(0, LastPos) + (LastPos > 0 ? "" : "");
		}
		else
		{
			PreAddr = Trim(TargetTextCtrl.value);
			if (PreAddr != "") PreAddr += PreAddr.substr(PreAddr.length-1, 1) != ";" ? ";" : "";
			this.m_AddrTextCtrl.value = "";
		}
		TargetTextCtrl.value =  PreAddr + MailAddr + ";";
		this.CloseAC();
		this.m_AddrTextCtrl.focus();
		this.RemoveRepeatAddr();
	},

	GetPatternStr:function(KeyCode)
	{
		var AddrValue = this.m_AddrTextCtrl.value;
		var LastPos = this.GetPatternPos(AddrValue);
		if(LastPos != -1)
		{
			AddrValue = AddrValue.substr(LastPos + 1)
		}
		return  Trim(AddrValue);
	},
	GetPatternPos:function(AddrValue)
	{
	　　//分号
		var idx = AddrValue.lastIndexOf(';');
		//逗号
		var idx1 = AddrValue.lastIndexOf(',');
		//全角分号
		var idx2 = AddrValue.lastIndexOf('；');
		//全角逗号
		var idx3 = AddrValue.lastIndexOf('，');
		
		idx = Math.max(idx, idx1);
		idx = Math.max(idx, idx2);
		idx = Math.max(idx, idx3);
		return idx;
	},

	ClearACTable:function()
	{
		if(this.m_ACTable)
		{
			for(var Loop = this.m_ACTable.rows.length - 1; Loop > -1; Loop --)
			{
				this.m_ACTable.deleteRow(Loop);
			}
		}
		this.m_AddrLineNo = -1;
	},
	//将符合搜索结果的地址全部填入ACTable，在用户按键并且当前的搜索结果不足以再进一步搜索时调用。
	GenACTableByAddrList:function(Pattern)
	{
		if (!this.m_AddrList)
		{
			return;
		}
		var Loop = 0;
		var LineNo = 0;
		var MatchStr;
		this.m_ACTable.onmouseover = this.ItemMouseEnter.Bind(this);
		this.m_ACTable.onmousedown = this.ItemClick.Bind(this);
		for (Loop = this.m_AddrList.length - 1; Loop >= 0; Loop--)
		{
			
			//if (Pattern == " ")
			if (Pattern.length == 0)
			{
			    //update
				MatchStr = this.m_AddrList[Loop].Name;
			}else
			{

				MatchStr = this.GetMatchResultStr(Loop, Pattern); //遍历数组，遇到匹配的，就format成高亮，返回html
				if(MatchStr == "")
				{
					continue;
				}
			}	
			var TR = this.m_ACTable.insertRow(LineNo);
			TR.value = Loop;
			var TD = TR.insertCell(0);
			TD.className = "frtd";
			TD.noWrap = true;
			TD.value = LineNo;
			TD.innerHTML = MatchStr;
		
			LineNo ++;
			MatchStr = null;
			TD = null;
			TR = null;
		}
	},
//如果新的pattern是 oldPattern + xxx，则在现有table中过滤
	GenACTableBySelf:function(Pattern)  
	{
		var Loop, Idx, LineNo = 0;
		var MatchStr;
		//var time1 = (new Date()).getTime();
		if(this.m_AddrLineNo >= 0)
		{
			this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd";	
			this.m_AddrLineNo = -1;
		}

		for (Loop = 0; Loop < this.m_ACTable.rows.length; Loop++)
		{
			Idx = this.m_ACTable.rows[Loop].value;		//获取在地址本列表中的索引
			MatchStr = this.GetMatchResultStr(Idx, Pattern);
			if(MatchStr == "")
			{
				this.m_ACTable.deleteRow(Loop);
				Loop --;
				continue;
			}
			this.m_ACTable.rows[Loop].cells[0].value = LineNo;
			this.m_ACTable.rows[Loop].cells[0].innerHTML = MatchStr;
			
			LineNo ++;
		}
			//alert("pattern:" + Pattern + "\n row:" + LineNo);
	},
	RebindEvents:function()
	{
		if(this.m_ACTable)
		{
			this.m_ACTable.onmouseover = this.ItemMouseEnter.Bind(this);
			this.m_ACTable.onmousedown= this.ItemClick.Bind(this);
		}
		return;
	},
	GenACTable:function(Pattern)
	{
		var lowerPat;
		lowerPat = Trim(Pattern.toLowerCase());
		this.RebindEvents();
		/*alert(this.m_LastPatternAddr == lowerPat)
		by matthew ,当删除所有地址，再敲入首字母，在这里退出，导致无法显示地址列表
		if(this.m_LastPatternAddr == lowerPat )
		{
			return ;
		}*/
		this.m_AddrList = this.GetAddrList();
		if(this.m_LastPatternAddr != "" && lowerPat.indexOf(this.m_LastPatternAddr) == 0) 
		{
			this.GenACTableBySelf(lowerPat);
		}
		else
		{
			this.ClearACTable();
			this.GenACTableByAddrList(lowerPat);
		}
		this.m_LastPatternAddr = lowerPat;
		(this.m_ACTable.rows.length == 0)?this.CloseAC():this.ShowAC();
	},
	getAddrList:function()
	{
		//此为虚函数，永远不要调到这个函数 leonard
		alert("内部错误，请实例化这个类并重载这个函数！");
		return new Object();
	},
	//高亮搜索的关键字, 生成一行的主要html
	GetMatchResultStr:function(Idx, iPattern)
	{
		Pattern = HtmlEncode(iPattern.toLowerCase().replace(/&/g,"&amp;"));	
		try
		{
			/*
			   match顺序
			   	1.Name
			   	2.Email @前面
			   	3.PinYin
			*/
			var tempStr = "";
			var addr = this.m_AddrList[Idx];
			var addrName = addr.Name.toLowerCase();
			var addrEMail = addr.EMail;
			//var SubMail = addrEMail.toLowerCase().substr(0,addrEMail.indexOf("@"));
			var mathIdx = addrName.indexOf(Pattern); 
			if(mathIdx != 0)
			{
				//matchIdx = SubMail.indexOf(Pattern);
				mathIdx = addrEMail.indexOf(Pattern);
				if(mathIdx != 0) 
				{
					mathIdx = addr.PinYin.indexOf(Pattern);
					if(mathIdx != 0)
					{
						tempStr = "";
					}
					else
					{
					    //update
						tempStr = addrName;
					}
				}
				else
				{
				    //update
					tempStr = [ addrName ].join("");
				}
			}
			else
			{
			    //update
				tempStr = [addrName.substr(0, mathIdx)
				 ,"<b>"
				 ,Pattern
				 ,"</b>" 			 
				 , addrName.substr(mathIdx + Pattern.length)
				 ].join("");
			}
			return tempStr;
			
		}
		catch(e)
		{
			alert(e.description)
			return "";
			
		}
		return "";
	},
	ItemMouseEnter:function()
	{
		var el = GetSrcElement(this.m_ACFrame.event);
		if(el.tagName!="TD")return;
		var Value = el.value;
		if(this.m_AddrLineNo != Value)
		{
			if( this.m_AddrLineNo > -1)
			{
				this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd";
			}
			this.m_AddrLineNo = Value;
			this.m_ACTable.rows[this.m_AddrLineNo].cells[0].className = "frtd_on";
		}
	},
	ItemClick:function()
	{
		this.SelectAddr();
	},
	ClickEvent:function()
	{
		this.m_AddrTextCtrl.focus();
		if(!this.m_ACFrameElement.Loaded)
		{
			this.LoadIFrame();
		}
		if(!this.m_ACTable)
		{
			this.m_ACTable = this.m_ACFrame.document.getElementById("AutoCompleteTable");
			if(!this.m_ACTable){ return;};
		}
		this.GenACTable(" ");
		this.ShowAC();
	}
};

CCRelease.AutoCompleteAllAddr=CCRelease.Create();
CCRelease.AutoCompleteAllAddr.prototype=(new CCRelease.AutoComplete()).Extend(
{
	GetAddrList:function()
	{
		 
		var m_AddrList = [];
		var Item = null
		//[ id,pinyin,email,name]
		var dat;
		var idx=0;
		var g_addrs ;
		g_addrs = classList;
		for(var i=0,len=g_addrs.length-1;i<len;++i)
		{
			dat = g_addrs[i];
			 
			m_AddrList[idx]={Name:dat[3],EMail:dat[2],PinYin:dat[1].toLowerCase()};
			++idx;
		}

		return m_AddrList;
	}
});

CCRelease.AutoCompleteQQFriend=CCRelease.Create();
CCRelease.AutoCompleteQQFriend.prototype=(new CCRelease.AutoComplete()).Extend(
{
	GetAddrList:function()
	{
		 
		return null;
	}
});
