//全局ajax请求开关对象
var AJAX_REQUEST = {};
//全局ajax请求计数器
var AJAX_APP_ID = 0;
//全局变量，设置通用option
var AJAX_APP_OPTION = {};
//全局变量，设置提示消息对象
var oMsg = new Object();

/**
 * 根据我们应用的特定xml，从而编写了下面的函数构造体。
 * 1.模式化整个应用过程，对其中每个进程调用的方法填空式的填写。
 * 2.对ajax请求进行了控制，可以实现一个具体ajax请求在只能请求一次(once)，
 *   在请求发送到服务器处理后没有返回消息前不能重复请求(single)，不加限制(repeat)
 * 3.对于ajax请求的success根据特定的xml分成请求成功和失败两种状态，分别进行处理。
 * 4.通过构造函数这种方法可以对于应用相似的ajax应用构造出相似的应用反复调用。
 * 5.需要用到的扩展参数（如消息提示的显示位置，类名称，生成的消息容器的id）都可以通过在options里面添加对象属性来传递。
 *   有一点要注意，$.ajax用到的那几个属性(type,url,data,datatype)的处理必须在进入$.ajax以前的
 *   方法中完成（也就是说是在beforeAjax中完成）
 * @param {Object} options 参数对象，可以将ajax请求的参数，需要传递的参数，预定义的方法都从这里进行定义，并且可以继承来自全局OPTION进行统一定义。
 * 预定义方法说明：下面对于ajax请求各个阶段需要设置的外部方法进行说明
 * beforeAjax 参数 options 默认返回true
 *   beforeAjax主要是在建立ajax请求前调用的方法：
 *   可以决定对options参数进行处理（主要是$.ajax用到的参数，比如对data进行拼合），
 *   并且判断ajax请求是否需要建立（比如form提交前的校验，判断数据是否加载）
 * ajaxBeforeSend 参数 xmlHttp,options 默认返回true
 *   在ajax请求建立后，发送前调用的方法：
 *   建立提示消息。
 *   修改options
 *   取消ajax请求（xmlHttp.abort()）如果需要取消ajax请求，则将返回值设为false，来控制改变锁定状态。
 * successPass 参数 msg,options
 *   在ajax请求返回成功后，返回信息断定为正确后调用的方法
 *   处理返回数据
 *   建立提示消息（如有需要控制ajaxBeforeSend生成的提示消息）
 * successFailed 参数 msg,options
 *   在ajax请求返回成功后，返回信息断定为错误后调用的方法
 *   处理返回数据
 *   建立提示消息（如有需要控制ajaxBeforeSend生成的提示消息）
 * ajaxError 参数 options
 * 	 在ajax请求失败后，需要调用的方法
 *   定义处理方式
 *   建立提示消息（如有需要控制ajaxBeforeSend生成的提示消息）
 * ajaxLock 参数 options
 *   在ajax请求被锁定后，需要调用的方法
 * @param {String} appName 应用名称，如果为空会调用_generateIt方法对其生成一个唯一的名称号。
 * @param {String} appStyle 应用请求类型（once 单一请求 single 单进程 repeat 多进程）
 */
function Magic_AjaxApp(options,appName,appStyle)
{
	this.options = jQuery.extend(
		{
			type: "POST",
			dataType: "xml",
			formData:"",
			base64: true,
			beforeAjax: function(options){return true;},
			ajaxBeforeSend: function(xmlHttp,options){return true;},
			successPass: function(msg,options){},
			successFailed : function(msg,options){},
			ajaxError: function(options){},
			ajaxLock: function(options){},
			msgName:"",
			loadingwords:"请求处理中...",
			errorwords:"服务器出错，请稍后再试",
			boxs:"",
			begin_item:""
		}, AJAX_APP_OPTION || {}, options || {} );
	this.appStyle = appStyle || "single";
	this.appName = appName || this._generateIt();
	
}

Magic_AjaxApp.prototype = {
	
	/**
	 * 复制一个对象，暂时没用
	 * @param {Object} object 原对象
	 */
	_clone : function(object){
		var tempObject = new Object;
		for ( var i in object){
			tempObject[i] = object[i];
		}
		return tempObject;
	},
	
	/**
	 * 生成一个名字
	 * @param {Object} headString 名字的起始字符串
	 */
	_generateIt : function(headString){
		var id = headString || "ajaxapp_";
		AJAX_APP_ID = AJAX_APP_ID + 1;
		return id + AJAX_APP_ID;
	},
	
	/**
	 * ajax整个过程的模式化
	 * @param {Object} options 继承自构造体，并可以添加与覆盖其中的属性
	 * @param {Object} appName 继承自构造体，并可以覆盖
	 * @param {Object} appStyle 继承自构造体，并可以覆盖
	 */
	app: function(options,appName,appStyle)
	{
		//用个空对象即可避免this.options被修改
		options = jQuery.extend({},this.options || {},options || {});
		appName = appName || this.appName;
		appStyle = appStyle || this.appStyle;
		
		//将beforeAjax的结果返回，如果函数未返回值，则会造成ajax请求被中断。
		var beforeAjax = options.beforeAjax.call(this,options);
		
		//判断beforeAjax的值来决定此次ajax请求是否建立
		if(!beforeAjax)
		{
			return;
		}

		if(options.base64)
		{
			var sFilter = "&actiontype&classname&rtype&xsl&goto_page&count_of_page&total_count&action&";
			if(options.type == "POST")
			{
				
				var aData = options.data.split("&");
				for(var i = 0; i<aData.length; i++)
				{
					if(aData[i])
					{
						var aUnits = aData[i].split("=");
						var re = new RegExp("&"+ aUnits[0] +"&","i");
						if(re.test(sFilter) || /^[0-9]+$/.test(aUnits[1]))
						{
							aData[i] = aUnits[0] + "=" + aUnits[1];
						}
						else
						{
							aData[i] = aUnits[0] + "=" + htmlEncode1(base64encode(utf16to8(htmlEncode(aUnits[1]))));
						}
					}
				}
				options.data = aData.join("&");
				//alert(options.data);
				
			}
			if(options.type == "GET")
			{
				var aUrl = options.url.split("?");
				var aData = aUrl[1].split("&");
				for(var i = 0; i<aData.length; i++)
				{
					if(aData[i])
					{
						var aUnits = aData[i].split("=");
						var re = new RegExp("&"+ aUnits[0] +"&","i");
						if(re.test(sFilter) || /^[0-9]+$/.test(aUnits[1]))
						{
							aData[i] = aUnits[0] + "=" + aUnits[1];
						}
						else
						{
							aData[i] = aUnits[0] + "=" + htmlEncode1(base64encode(utf16to8(htmlEncode(aUnits[1]))));
						}
					}
				}
				var data = aData.join("&");
				options.url= aUrl[0] + "?" + data;
				//alert(options.url);
			}
		}
			if(options.formData)
			{
/**
				if(options.base64)
				{
					var aData = options.formData.split("&");
					for(var i = 0; i<aData.length; i++)
					{
						var aUnits = aData[i].split("=");
						aData[i] = aUnits[0] + "=" + htmlEncode1(base64encode(utf16to8(htmlEncode(aUnits[1]))));
					}
					options.formData = aData.join("&");
				}
**/
				options.data = options.data + "&" + options.formData;
			}
			//alert(options.data);
		
		//看此ajax请求是否建立或者锁定，如果未建立或者未锁定，则继续
		if(!AJAX_REQUEST[appName])
		{
			//如果appStyle不为repeat，则对此ajax应用锁定
			if(appStyle != "repeat")
			{
				AJAX_REQUEST[appName] = true;
			}
			
			//建立ajax请求并将options参数加入
			jQuery.ajax(jQuery.extend(
			{
				beforeSend: function(xmlHttp)
				{
					//20080702将提示信息固化进来
					if(options.msgName)
					{
						oMsg[options.msgName](options.loadingwords, "", {place: options.boxs,begin_item:options.begin_item}, "msg_loading");
					}
					//根据ajaxBeforeSend方法的返回值判断锁定状态
					var ajaxBeforeSend = options.ajaxBeforeSend.call(this,xmlHttp,options);
					if(!ajaxBeforeSend){
						//如果请求被取消，则解锁
						AJAX_REQUEST[appName] = false;
					}
				},
				success: function(msg)
				{
					//alert(msg);
					if(options.msgName)
					{
						oMsg[options.msgName]($("message", msg).text(), "", {place: options.boxs,begin_item:options.begin_item,timeout : 1500}, "msg_ok");
					}
					//根据特定的xml进行返回数据正确与否的判断，根据结果分别调用不同的方法和改变当前ajax应用的锁定状态。
					if(jQuery("return_msg error_flag",msg).text() == "ok")
					{
						options.successPass.call(this,msg,options);
						if(appStyle != "once")
						{
							//如果请求不是单一请求，则解锁
							AJAX_REQUEST[appName] = false;
						}
					}
					else
					{
						if(options.msgName)
						{
							if($("return_type",msg).text() != "system")
							{
								oMsg[options.msgName]($("message", msg).text(), "", {place: options.boxs,begin_item:options.begin_item,timeout : 5000}, "msg_error");
								//topic_reply_msg($("message", msg).text(), "", {timeout : 5000}, "msg_error");
							}
							else
							{
								oMsg[options.msgName](options.errorwords, "", {place: options.boxs,begin_item:options.begin_item,timeout : 5000}, "msg_error");
							}
						}
						options.successFailed.call(this,msg,options);
						//结果错误，需要重新请求，解锁
						AJAX_REQUEST[appName] = false;
					}
				},
				error: function(xmlHttp)
				{
					if(options.msgName)
					{
						oMsg[options.msgName](options.errorwords, "", {place: options.boxs,begin_item:options.begin_item,timeout : 5000}, "msg_error");
					}
					options.ajaxError.call(this,options,xmlHttp);
					//请求错误，需要重新请求，解锁
					AJAX_REQUEST[appName] = false;
				}
			},options ||{}));
		}
		else
		{
			//请求锁定的处理方法
			options.ajaxLock.call(this,options);
		}
	}
}

function htmlEncode1(txt)
{
	var f = /=/g;
	txt = txt.replace(f,"@"); 
	return txt; 
}
function htmlEncode(txt)
{
	var a = /&/g;
	var b = /\"/g;
	var c = /</g;
	var d = />/g;
	var e = / /g;
	txt = txt.replace(a,"&amp;"); 
	txt = txt.replace(b,"&quot;"); 
	txt = txt.replace(c,"&lt;"); 
	txt = txt.replace(d,"&gt;");
	txt = txt.replace(e,"&nbsp;"); 
	return txt; 
}

/*
//定义全局的options参数
var AJAX_APP_OPTION = {
	type: "GET",
	url: "/hibj/process.do",
	data: "classname=article&action=getbyid&rtype=xml&article_id=",
	dataType: "xml"
};

$(function(){
	
	//生成一个ajax请求实例，对预定义方法进行编写。
	var ajax1 = new Magic_AjaxApp(
	{
		beforeAjax: function(options){
			options.data = options.data + options.article_id;
			//alert(options.data);
			return true;
		},
		ajaxBeforeSend: function(xmlHttp,options){
			var a = xmlHttp;
			var b = options;
			var d = 1;
			options.id = "999";
			return true;
		},
		successPass: function(msg,options){
			var author_id = msg;
			var b = options;
			var c = 1;
			//alert(options.data);
			//alert(msg);
		}
		
	},"a","single");
	
	ajax1.app({article_id:159,divBox: "2"});
	ajax1.app({article_id:195},"dddd");
});

*/