//全局提示信息id和classname的计数器
var AJAX_MSG_ID = 1;

/**
 * 用闭包的方法生成消息提示类，然后在针对不同的类运行方法。
 * @param (String) msgGlobal 消息提示的内容。 
 * @param (String) boxNameGlobal 消息提示容器的名称，做为是否重复显示的标志。
 * @param (String) boxClassGlobal 消息提示容器的样式名称，可以控制消息容器的样式。
 * @param {Object} optionsGlobal 消息提示用到的参数。
 * options参数说明
 * @param (String) timeout 提示信息显示时间，如果为整数，则显示多少秒后自动消失，如果为-999，则一直保留，默认值为5000（即5秒钟）
 * @param (String) viewStyle ( repeat | single ) 显示形式，是一个消息类只存在一个，还是可以存在多个，默认为single
 * @param (String) place ( top | bottom | middle | custom ) 提示信息显示的位置，top 为页面右上角 bottom为页面右下角 middle为页面中间，custom为自定义位置，此时参数为页面上要放置提示信息的参照元素的id，默认值为top
 * @param (String) insertby ( after | before | append | prepend | html ) 如果place为custom自定义位置，则该参数将被用到，用来定义提示信息和参照元素之间的位置关系。具体参照jquery的api 
 * @param (String) modality ( html | script ) 显示内容的形式 html代表用html代码显示，script代表用script代码显示
 * @param (String) templete 显示提示信息的模板，用字符串来表示，内部的标记了两个正则替换标签：$msgboxid$用来替换boxName，定义提示信息的id，$msgboxContent$用来替换msg，置入提示信息。
 */
function Magic_AjaxMsg(msgGlobal,boxNameGlobal,optionsGlobal,boxClassGlobal){
	this.msgGlobal = msgGlobal || "";
	this.boxNameGlobal = boxNameGlobal || this._generateIt("msgBoxName_");
	this.boxClassGlobal = boxClassGlobal || this._generateIt("msgBoxClass_");
	this.optionsGlobal = jQuery.extend({
		timeout: "5000",
		viewStyle: "single",
		place: "top",
		insertby: "append",
		modality : "html",
		begin_item:"",
		templete : '<div id="#msgboxid#" name="#msgboxname#" class="#msgboxclass# msg_normal">#msgboxContent#</div>'
	}, optionsGlobal || {});
	var _this = this;

	return function(msg,boxName,options,boxClass){
		msg = msg || _this.msgGlobal;
		boxName = boxName || _this.boxNameGlobal;
		boxClass = boxClass || _this.boxClassGlobal ;
		options = _this.dealOptions(options);
		var boxId = _this._generateIt("msgBoxId_");
		var templete = _this.dealTemplete(msg,boxName,boxId,options,boxClass);
		var $place;

		switch(options.modality){
			case "html" :
					jQuery("[@name='"+ boxName+ "'] div").html(msg);
					$place = _this.dealPlace(options);
					_this.dealViewStyle(boxName,options);
					_this.insertMsgBox($place,templete,boxId,options); 
					_this.placeExend(boxId,options);
					_this.dealTimeout(boxId,options);
				break;
			case "script" :
				eval(templete);
				break;
			default:
				return false;
		}
		return boxId;
	};
}

Magic_AjaxMsg.prototype = {
	
	/**
	 * 建立一个不重复的名字。用一个外部传入的字符串和后面的数字链接生成一个在此页面内不会重复的名字定义。
	 * @param {String} headString 定义名字前面的字符串
	 * 在此应用中主要用于生成消息容器的id和classname。
	 */
	_generateIt : function(headString){
		var id = headString || "ajaxmsg_";
		AJAX_MSG_ID = AJAX_MSG_ID + 1;
		return id + AJAX_MSG_ID;
	},
	
	/**
	 * 对由包含函数传入的options参数进行处理。
	 * @param {Object} options 生成函数的options定义
	 */
	dealOptions : function(options){
		/*
		 * 不能直接使用jQuery.extend，此方法会对_this.optionsGlobal进行重写，导致在修改了其包含函数的对象，这是我们不希望出现的。
		 * var options = jQuery.extend(_this.optionsGlobal,options || {});
		 * 解决方法是，先建立一个新的对象，将其包含函数的对象的复制过来。
		 * 不能直接进行对象赋值，这样变量指向的还是同一个对象，这个是要特别注意的。
		 * 可以用一个技巧来简化这里
		var optionsTemp = new Object;
		for(var i in this.optionsGlobal){
			optionsTemp[i] = this.optionsGlobal[i];
		}
		return jQuery.extend(optionsTemp,options || {});
		*/
		//jQuery.extend 支持多个对象的添加。
		return jQuery.extend({},this.optionsGlobal,options || {});
	},
	
	/**
	 * 对模板进行处理。将其中定义的 #msgboxid# #msgboxclass# #msgboxContent# 进行正则替换。
	 * @param {String} msg 提示信息
	 * @param {String} boxName 提示信息容器的name
	 * @param (String) boxClass 消息提示容器的样式名称，可以控制消息容器的样式。
	 * @param {String} boxId 提示信息容器的id
	 * @param {Object} options 扩展options
	 */
	dealTemplete: function(msg,boxName,boxId,options,boxClass){
		var templete = options.templete;
		var reId = /#msgboxid#/;
		var reName = /#msgboxname#/;
		var reClass = /#msgboxclass#/;
		var reMsg = /#msgboxContent#/;
		//正则替换
		switch(options.modality){
			case "html" :
				templete = templete.replace(reId,boxId);
				templete = templete.replace(reName,boxName);
				templete = templete.replace(reClass,boxClass);
			case "script" :
				templete = templete.replace(reMsg,msg);
		}
		return templete;
	},
	
	/**
	 * 对提示信息插入的位置进行处理，对top,bottom,middle等三个定义类型，将其参照元素设置为body。
	 * @param {Object} options
	 */
	dealPlace: function(options){
		var $place;
		switch(options.place){
			case "top":
				$place = jQuery("body");
				break;
			case "bottom":
				$place = jQuery("body");
				break;
			case "middle":
				$place = jQuery("body");
				break;
			case "pop":
				$place = jQuery("body");
				break;
			case "pop_right":
				$place = jQuery("body");
				break;
			default:
				$place = jQuery("#" + options.place);
				break;
		}
		return $place;		
	},
	
	/**
	 * 对于显示形式进行处理（单一显示，重复显示）
	 * @param {String} boxClass 
	 * @param {Object} options
	 */
	dealViewStyle: function(boxName,options){
		switch(options.viewStyle){
			case "single":
				jQuery("[@name='"+ boxName+ "']").remove();
				break;
			case "repeat":
				break;
		}
	},
	
	/**
	 * 将提示信息插入文件。
	 * @param {jquery Object} $place
	 * @param {String} templete
	 * @param {String} boxId
	 * @param {Object} options
	 */
	insertMsgBox : function($place,templete,boxId,options){
		$place[options.insertby](templete);
/*投放效果暂时不做
			jQuery("#" + options.begin_item).TransferTo(
				{
					to:boxId,
					className:'transferer2', 
					duration: 50,
					complete: function()
					{
						$('#'+ boxId).show();
					}
				}
			);			
*/
		jQuery("#" + boxId).css("display","none").fadeIn();
	},
	
	/**
	 * 根据置入提示信息的类型进行必要的扩展。
	 * @param {String} boxId
	 * @param {Object} options
	 * 主要是针对top,bottom,middle三种位置添加了提示信息的初始位置和当页面onscroll和onresize的时候的方法。
	 */
	placeExend : function(boxId,options){
		var _this = this;
		switch(options.place){
			case "top":
				jQuery("#" + boxId).css({position:"absolute",right:"0px"});
				_this._initPosition(boxId,options);
				jQuery(window).scroll(function(){ _this._initPosition(boxId,options);});
				jQuery(window).resize(function(){ _this._initPosition(boxId,options);});
				break;
			case "bottom":
				jQuery("#" + boxId).css({position:"absolute",right:"0px"});
				_this._initPosition(boxId,options);
				jQuery(window).scroll(function(){ _this._initPosition(boxId,options);});
				jQuery(window).resize(function(){ _this._initPosition(boxId,options);});
				break;
			case "middle":
				jQuery("#" + boxId).css({position:"absolute"});
				_this._initPosition(boxId,options);
				jQuery(window).scroll(function(){ _this._initPosition(boxId,options);});
				jQuery(window).resize(function(){ _this._initPosition(boxId,options);});
				break;
			case "pop":
				jQuery("#"+boxId).css("right",(jQuery(window).width() - jQuery("#"+options.begin_item).offset().left - Math.floor(jQuery("#"+options.begin_item).width()/2) )+ "px");
				jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + jQuery("#"+options.begin_item).height() + 3) + "px");
				jQuery(window).resize(function(){ _this._initPosition(boxId,options);});
				break;
			case "pop_right":
				jQuery("#"+boxId).css("left",(jQuery("#"+options.begin_item).offset().left + jQuery("#"+options.begin_item).width() + 10 )+ "px");
				jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + Math.floor((jQuery("#"+options.begin_item).height()-26)/2)+3) + "px");
				jQuery(window).resize(function(){ _this._initPosition(boxId,options);});
				break;
			default:
				break;
		}		
	},
	
	/**
	 * 设置提示信息的位置。top:右上角，bottom:右下角，middle:页面中间。
	 * @param {String} boxId
	 * @param {Object} options
	 */
	_initPosition: function(boxId,options){
		switch(options.place){
			case "top":
				if(document.all){	
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",(document.documentElement.scrollTop || document.body.scrollTop) + "px");//ie
					}
				}else{
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",(pageYOffset)+"px");//firefox
					}
				}
				break;
			case "bottom":
				if(document.all){	
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",((document.documentElement.scrollTop || document.body.scrollTop) + document.documentElement.clientHeight - jQuery("#" + boxId)[0].offsetHeight)+"px" );//ie
					}
				}else{
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",(pageYOffset + document.documentElement.clientHeight - jQuery("#" + boxId)[0].offsetHeight)+"px");//firefox
					}
				}			
				break;
			case "middle":
				if(document.all){	
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",((document.documentElement.scrollTop || document.body.scrollTop) + parseInt((document.documentElement.clientHeight - jQuery("#" + boxId)[0].offsetHeight)/2))+"px" );//ie
						jQuery("#" + boxId).css("left",((document.documentElement.scrollLeft || document.body.scrollLeft) + parseInt((document.documentElement.clientWidth - jQuery("#" + boxId)[0].offsetWidth)/2))+"px" );//ie
					}
				}else{
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#" + boxId).css("top",(pageYOffset + parseInt((document.documentElement.clientHeight - jQuery("#" + boxId)[0].offsetHeight))/2)+"px");//firefox
						jQuery("#" + boxId).css("left",(pageXOffset + parseInt((document.documentElement.clientWidth - jQuery("#" + boxId)[0].offsetWidth))/2)+"px");//firefox
					}
					
				}			
				break;
			case "pop":
				if(document.all){	
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#"+boxId).css("right",(jQuery(window).width() - jQuery("#"+options.begin_item).offset().left - Math.floor(jQuery("#"+options.begin_item).width()/2) )+ "px");
						jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + jQuery("#"+options.begin_item).height() + 3) + "px");
					}
				}else{
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#"+boxId).css("right",(jQuery(window).width() - jQuery("#"+options.begin_item).offset().left - Math.floor(jQuery("#"+options.begin_item).width()/2) )+ "px");
						jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + jQuery("#"+options.begin_item).height() + 3) + "px");
					}
					
				}
				break;
			case "pop_right":
				if(document.all){	
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#"+boxId).css("left",(jQuery("#"+options.begin_item).offset().left + jQuery("#"+options.begin_item).width() + 10 )+ "px");
						jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + Math.floor((jQuery("#"+options.begin_item).height()-26)/2)) + "px");
					}
				}else{
					if(jQuery("#" + boxId).size()>0)
					{
						jQuery("#"+boxId).css("left",(jQuery("#"+options.begin_item).offset().left + jQuery("#"+options.begin_item).width() + 10 )+ "px");
						jQuery("#"+boxId).css("top",( jQuery("#"+options.begin_item).offset().top + Math.floor((jQuery("#"+options.begin_item).height()-26)/2)) + "px");
					}
					
				}			
				break;
			default:
				break;
		}		
	},
	
	/**
	 * 对超时的处理。
	 * @param {String} boxId
	 * @param {Object} options
	 */
	dealTimeout: function(boxId,options){
		var time;
		if( options.timeout != "-999" ){
			time = parseInt(options.timeout);
			setTimeout(function(){jQuery("#"+boxId).fadeOut(function(){jQuery(this).remove();});},time);
		}
	}
};

/*使用例子
$(function(){
	
	//生成一个消息实例，
	var box1 = new Magic_AjaxMsg("","boxClass1");
	//调用提示信息，所有参数默认
	$("#aClick1").click(function(){
		box1("头部信息");
		return false;
	});
	//调用提示信息，显示位置在页面右下角
	$("#aClick2").click(function(){
		box1("底部消息","",{place:"bottom"});
		return false;
	});
  //调用提示信息，显示位置在页面中间
	$("#aClick3").click(function(){
		box1("中部信息","",{place:"middle"});
		return false;
	});
  
  //生成另外一个消息实例，改变option参数，修改了显示行为和置入位置
	var box2 = new Magic_AjaxMsg("","boxClass2",{viewStyle: "repeat",place: "place1"});
  
  //调用提示信息
	$("#aClick4").click(function(){
		box2("我是消息一，我可以重复，拉拉拉");
		return false;
	});
	
	//调用提示信息
	$("#aClick5").click(function(){
		box2("我是消息二，我可以重复，拉拉拉");
		return false;
	});
	
	//调用提示信息
	$("#aClick6").click(function(){
		box2("我是消息三，我可以重复，拉拉拉");
		return false;
	});
	
	//改变消息实例的参数，弹出脚本提示
	$("#aClick1").click(function(){
		box1("底部消息","boxClass2",{modality:"script",templete:"alert('#msgboxContent#')",place: "bottom"});
		return false;
	});
});
*/