function isString(obj){
	return (typeof obj == "string" || obj instanceof String) ? true : false
}
function isNumber(obj){
	return (typeof obj == "number" || obj instanceof Number) ? true : false;
}
function isElement(obj){
	return obj.nodeType ? true : false;
}
function isFunction(obj){
	return typeof obj == "function";
}
function isArray(obj){
	return obj instanceof Array;
}
function isRegExp(obj){
	return obj instanceof RegExp
}
/*
formに値をうめる関数
*/
var Ecnavi = {};
Ecnavi.Form = {};
Ecnavi.Form.fill = function(form,json){
	form = $(form);
	var a = $A(form.elements);
	a.each( function(el){
		var name = el.name; 
		var v = json[name];
		var value = (isArray(v)) ? v.shift() : v;
		if(!name || value == null) return;
		(/text|hidden|submit/.test(el.type)) ? 
			(el.value = value) :
		(el.type == "checkbox") ? (el.value = value, el.checked = true) :
		(el.type == "radio") ?
			(value == el.value) ? (el.checked = true) : (el.checked = false) :
		null
	})
}
Ecnavi.Form.toJson = function(form){
	var json = {};
	var len = form.elements.length;
	var a = $A(form.elements);
	a.each( function(el){
		if(!el.name) return;
		var value = $F(el);
		if(value){
			var obj = json[el.name];
			(isString(obj)) ? json[el.name] = [obj,value] :
			(isArray(obj))  ? json[el.name].push(value) :
			json[el.name] = value;
		}
	});
	return json;
}
Ecnavi.Form.build = function(action, method, json){
	var form = document.createElement("form");
	form.action = action;
	form.method = method;
	for( var i in json ){
		var input = document.createElement("input");
		input.type = "hidden";
		input.name = i;
		input.value = json[i];
		form.appendChild(input);
	}
	return form;
}
Ecnavi.Object = {};
Ecnavi.Object.toQuery = function(obj){
	var buf = [];
	for(var key in obj){
		var value = obj[key];
		if(isFunction(value)) continue;
		var q = (isArray(value)) ? Ecnavi.Array.toQuery(key, value) :
			encodeURIComponent(key)+"="+encodeURIComponent(value);
		buf.push(q);
	}
	return buf.join("&");
}
Ecnavi.Array = {};
Ecnavi.Array.toQuery = function(key, array){
	var buf = [];
	for(var i=0; i<array.length; i++){
		var value = array[i];
		if(isFunction(value)) continue;
		buf.push(
			encodeURIComponent(key)+"="+
			encodeURIComponent(value)
		);
	}
	return buf.join("&");
}

/*
* APIを呼び出すためのXHRラッパ。
* LDRの同様なクラスの実装を参考にして
* yuiを使って実装した
*/
var API = Class.create();
Object.extend(API.prototype, {
initialize:function(api){
	this.api = api;
}
,get:function(param, callback){
	param.timestamp = (new Date - 0);
	var url = this.api + "?" + Ecnavi.Object.toQuery(param);
	this.on_request(this.argument);
	new Ajax.Request( url, { method:"get", onComplete: this.on_success(callback)} );
}
,post:function(param, callback){
	var post = Ecnavi.Object.toQuery(param);
	this.on_request(this.argument);
	new Ajax.Request( this.api, { method:"post", postBody: post, onComplete: this.on_success(callback) } );
}
,on_success:function(callback){
	var me = this;
	return function(req){
		eval("var json = "+req.responseText);
		remove_prefix(json);
		callback(json, me.argument);
	};
}
//ユーザ定義ハンドラ
//XHR呼び出し前に呼ばれるハンドラ
,on_request:function(arg){}
});

function remove_prefix(json){
	for( var i in json ){
		if( typeof json[i] == "object" ){
			remove_prefix(json[i]);
		}else if( typeof json[i] == "string" ){
			json[i] = json[i].replace(/^###string###_/, "").unescapeHTML();
		}
	}
}

Function.prototype.later = function(ms){
	var self = this;
	return function(){
		var args = arguments;
		var thisObject = this;
		var res = {
			complete: false,
			cancel: function(){clearTimeout(PID);},
			notify: function(){clearTimeout(PID);later_func()}
		};
		var later_func = function(){
			self.apply(thisObject,args);
			res.complete = true;
		};
		var PID = setTimeout(later_func,ms);
		return res;
	};
};

Function.prototype.interval = function(ms){
	var self = this;
	return function(){
		var args = arguments;
		var thisObject = this;
		var res = {
			cancel: function(){clearInterval(PID);},
			notify: function(){func()}
		};
		var func = function(){
			self.apply(thisObject,args);
		};
		var PID = setInterval(func,ms);
		return res;
	};
}
