//------------------------------------------------
// 汎用Ajaxライブラリ Ver2.0.1
// LunarNight Lab.
// http://www.ln-lab.net/
//------------------------------------------------

var DataArray = Class.createEx('Array',{
	toDataPack : function(){
		var out = '';
		var max = this.length;
		for(var i=0;i<max;i++){
			var type = typeof(this[i]);
			if (type == 'object'){
				out += this[i].getDataPack(i);
			}else if(type != 'function'){
				out += '<string name="'+Escape.ucs(i)+'">'+Escape.ucs(this[i])+'</string>';
			}
		}
		return(out);
	},
	getDataPack: function(name){
		var data = this.toDataPack();
		
		var label = '';
		if (name != null){ label = ' name="'+Escape.ucs(name)+'"';}
		
		var out = '<list'+label+'>'+data+'</list>';
		return(out);
	}
});
var DataHash = Class.createEx('Object',{
	init : function(data){
		if (data){
			for(var i in data){
				this[i] = data[i];
			}
		}
	},
	toDataPack : function(){
		var out = '';
		for(var i in this){
			var type = typeof(this[i]);
			if (type == 'object'){
				out += this[i].getDataPack(i);
			}else if(type != 'function'){
				out += '<string name="'+Escape.ucs(i)+'">'+Escape.ucs(this[i])+'</string>';
			}
		}
		return(out);
	},
	getDataPack: function(name){
		var data = this.toDataPack();
		var label= '';
		if (name != null){ label = ' name="'+Escape.ucs(name)+'"';}
		
		var out = '<hash'+label+'>'+data+'</hash>';
		return(out);
	}
});

function ajaxDspError(errObj){
	var title = errObj['title'];
	var msg   = errObj['msg'  ];
	var opt   = errObj['opt'  ];
	if (opt == null){ opt = '';              }
	if (msg == null){ msg = 'メッセージなし';}
	
	dspError(title,msg,opt);
}
function ajaxDspMsg(msgObj){
	var title = msgObj['title'];
	var msg   = msgObj['msg'  ];
	var opt   = msgObj['opt'  ];
	
	dspMsg(title,msg,opt);
}

var AjaxBuildData = {
	StrList : Class.create({
		strList : null,
		init : function(strList){
			this.strList = strList;
		},
		pick : function(){
			var str = this.strList.shift();
			str.match(/<string[^>]*>([^>]*)<\/string>/);
			return(unescape(RegExp.$1));
		},
		isExist : function(){
			return(this.strList.length > 0);
		}
	}),
	TagList : Class.create({
		tagList : null,
		tag     : new Object(),
		
		init : function(tagList){
			this.tagList = tagList;
		},
		pick : function(onlyPick){
			var buf = this.tagList.shift();
			if (onlyPick || !buf){ return(null);}
			
			buf.match(/^<([^ >]+)/);
			this.tag.name = unescape(RegExp.$1);
			
			buf.match(/name=\"([^\"]+)"/);
			this.tag.key  = unescape(RegExp.$1);
			
			return(this.tag);
		},
		isExist : function(){
			return(this.tagList.length > 0);
		}
	}),
	build : function(responseText){
		
		var tagList = responseText.match(/<[^>]+>/g);
		var strList = responseText.match(/<string[^>]*>[^>]*<\/string>/g);
		if (!strList || !tagList){
			throw 'XML解析エラー:システム内部エラーを検出しました'+"\n"+responseText;
		}
		if (tagList[0] && tagList[0].indexOf('?') != -1){ tagList.shift();}

		strList = new this.StrList(strList);
		tagList = new this.TagList(tagList);
		
		var st    = null;
		var stack = new Array();
		var tag   = null;
		
		while(tag = tagList.pick()){
			if (tag.name == 'hash' || tag.name == 'list'){
				var buf;
				if (tag.name == 'hash'){
					buf = {
						key : tag.key,
						obj : new DataHash(),
						type: 'hash'
					};
				}else{
					buf = {
						key : tag.key,
						obj : new DataArray(),
						type: 'list'
					};
				}
				
				if (st){
					if (st.type == 'hash'){
						st.obj[buf.key] = buf.obj;
					}else{
						st.obj.push(buf.obj);
					}
					stack.push(st);
				}
				st = buf;
			}else if(tag.name == 'string'){
				var str = strList.pick();
				if (st.type == 'hash'){
					st.obj[tag.key] = str;
				}else{
					st.obj.push(str);
				}
				tagList.pick(true);
			}else if(tag.name == '/hash' || tag.name == '/list'){
				var t = stack.pop();
				if (t){ st = t; }else{ break;}
			}else{
				break;
			}
		}
		
		if (strList.isExist() || tagList.isExist()){
			throw 'XML解析エラー:XMLパーサがXML構造エラーを検出しました';
		}
		if (!st){
			throw 'XMLデータエラー';
		}
		return(st.obj);
	}
}


var HTTPRequest = Class.create({
	url : null,
	
	init : function(url){
		this.url = url;
	},
	execPOST : function(sendQuery,sendData,callbackSet){
		var self    = this;
		var httpObj = this.createHTTPRequest();
		if (httpObj == null){
			return('XMLHttpRequestオブジェクトの取得に失敗しました');
		}
		if (this.url == '' || this.url == null){
			return('送信先URLが不明です');
		}
		
		httpObj.open('POST',this.url,true);
		httpObj.onreadystatechange = function(){ self.onReadyStateChange(httpObj,callbackSet);}
		
		var data = "";
		if (sendData){
			data = "&dataPack="+Escape.uri(sendData.getDataPack());
		}
		httpObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		httpObj.send(sendQuery+data);
		return(null);
	},
	onReadyStateChange : function(httpObj,callbackSet){
		if (httpObj.readyState != 4){ return;}
		var rcCommand;
		var rcData;

		try{
			if (httpObj.status == 200){
				var xml = httpObj.responseText;
				var obj= null;
				
				if (xml == null){
					throw 'レスポンスがありません';
				}else{
					obj = AjaxBuildData.build(xml);
					if (obj == null){
						throw 'XML構造エラー:'+xml;
					}
				}
				if (obj['rcCode'] == 'error'){
					ajaxDspError(obj['rcData']);
				}else if (obj['rcCode'] == 'msg'){
					ajaxDspMsg(obj['rcData']);
				}else{
					rcCommand= obj['rcCommand'];
					rcData   = obj['rcData'   ];
					
					if (!callbackSet){ throw '不正なコールバックです';  }
					if (!rcData     ){ throw 'rcDataが存在しません';    }
					if (!rcCommand  ){ throw 'rcCommandが存在しません'; }
				}
			}else{
				throw 'BadResponse:'+httpObj.status;
			}
		}catch(msg){
			var err = new DataHash();
			err['title'] = 'ASyncHTTPTransactionError at execHttpPost->onReadyStateChange';
			err['msg'  ] = ""+msg;
			ajaxDspError(err);
			return;
		}
		if (callbackSet && rcCommand && rcData){
			callbackSet.callback.apply(callbackSet.baseObj,[rcCommand,rcData]);
		}
	},
	
	createHTTPRequest : function(){
		if(window.XMLHttpRequest){
			return(new XMLHttpRequest());
		}else if(window.ActiveXObject){
			try{
				return(new ActiveXObject("Msxml2.XMLHTTP"));
			}catch(e){
				try{
					return(new ActiveXObject("Microsoft.XMLHTTP"));
				}catch(e2){
					return(null);
				}
			}
		}else{
			return(null);
		}
	}
	
});

var AjaxCallbackObj = Class.create({
	httpRequest  : null,
	sessionID    : null,
	callbackSet : null,
	
	init : function(sessionID,httpRequest,callback,baseObj){
		
		this.callbackSet = {
			callback : callback,
			baseObj  : baseObj
		};
		this.sessionID  = sessionID;
		this.httpRequest=httpRequest;
	},
	sendQuery : function(query){
		return(this.httpRequest.execPOST(query,null,this.callbackSet));
	},
	
	sendCommand : function(command,ajaxDataObj){
		var obj = new DataHash();
		obj['command'] = command;
		if (ajaxDataObj){
			obj['data'] = ajaxDataObj;
		}
		
		var sid = this.sessionID ? '&sessionID='+this.sessionID : '';
		return(this.httpRequest.execPOST('ajaxGateway=1'+sid,obj,this.callbackSet));
	}
	
});


var AjaxConnection = Class.create({
	sessionID: null,
	httpRequest : null,
	
	init : function(gateURL,sessionID){
		this.httpRequest = new HTTPRequest(gateURL);
		this.sessionID= sessionID;
	},
	createCallback : function(callback,baseObj){
		var obj = new AjaxCallbackObj(this.sessionID,this.httpRequest,callback,baseObj);
		return(obj);
	},
	getFileDirect : function(targetURL){
		var request = this.httpRequest.createHTTPRequest();
		request.open('GET',targetURL,false);
		request.send('');
		
		return(request.responseText);
	}
});


