/**
 * 
 * Methods
 * - GET, POST, HEAD
 * 
 * References
 * - Prototype Framework
 * 
 * TODO
 * - Check ajax status and state in stop() and timeout()
 */

 if(window.jscore) (function() {
 	jscore.requireJS("json");
 
	var stateChange = function(request) {
		if(request) {
			request.readyState = this.events[request.transport.readyState];
			//request.status = (!jscore.isUndefined(request.transport.status) ? request.transport.status : 0);
			if (request.readyState == 'Complete') {
				
				if (jscore.isFunction(request.onComplete)) {
                    if(request.checkTransport) {
                    	
                        if(this.checkTransport(request,"200",false) || (request.transport.responseText && request.transport.responseText != "")) {
                            request.onComplete.call(request.scope, request);
                        }
                    } else {
                        request.onComplete.call(request.scope, request);
                    }
				}
				
				// avoid memory leak in MSIE: clean up
      			request.transport.onreadystatechange = function(){};
			} else {
				if (jscore.isFunction(request.onStateChange)) {
					request.onStateChange.call(request.scope, request);
				}
			}
		}
	}
	
	var stopTimeout = function(request) {
		
		if (request.readyState != 'Complete' && !request.timeout_stop) {
			request.timeout_stop = true;
			request.aborted = true;
			request.transport.abort();
			clearTimeout(request.timer);
			request.timer = null;
			/*if(jscore.isFunction(request.onTimeout)) {
				if(request.timeout_attempts >= request.timeout_retries) {
					if(confirm("Request timeout (ajax).\r\n\r\nDo you want to retry?")) {
						request.timeout_attempts=0;
						this.send(request);
					} else {
						if(request.timeout_auto_close_notify_dialog && jscore.namespaceExist("jscore.widget.dialog.notify") && jscore.isFunction(jscore.widget.dialog.notify)) {
							jscore.widget.dialog.notify("hide");
						}
					}
				} else {
					request.timeout_attempts++;
					request.onTimeout.call(request.scope,request);
				}
			}*/
			if(jscore.isFunction(request.onTimeout)) {
				request.timeout_attempts++;
				request.onTimeout.call(request.scope,request);
				if(request.timeout_auto_close_notify_dialog && jscore.namespaceExist("jscore.widget.dialog.notify") && jscore.isFunction(jscore.widget.dialog.notify)) {
					jscore.widget.dialog.notify("hide");
				}
			} else {
				//alert("Request timeout (ajax).");
				if(request.timeout_auto_close_notify_dialog && jscore.namespaceExist("jscore.widget.dialog.notify") && jscore.isFunction(jscore.widget.dialog.notify)) {
					jscore.widget.dialog.notify("hide");
				}
			}
			
		}
		
	}
	
	var queue = [];
	var file_uploads=[];

	jscore.extend("jscore.ajax",{
		events : ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'],
		
		transport : function() {
			var xmlHttp = null;
			try {
				xmlHttp = new XMLHttpRequest();
			} catch (e) {
				try {
					xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
				} catch (e) {
					try {
						xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
					} catch (e) {
						xmlHttp = null;
					}  
				}
			}
			
			return xmlHttp;
		},

		request : function(conf) {
			var _this=this;
			var req = {
				method : "get",
				asynchronous : true,
				cacheable : false,
				timeStampParameter : "ts", //Only used when cacheable is true. e.g. &ts=
				aborted: false,
				contentType:'application/x-www-form-urlencoded',
				encoding:'UTF-8',
				userHeaders: {},
				url:'',
                parameters:'',
				//evalJSON:true,
				//evalJS:true,
				readyState:"",
				//status:0,
				timer:null,
				timeout: 15,
				timeout_stop:false,
				timeout_retries:2,
				timeout_attempts:0,
				timeout_ask_retry:true,
				timeout_auto_close_notify_dialog:true,
                checkTransport:true, //checks code 200 and not aborted
				onStateChange : null,
				onComplete : null,
				onTimeout : null,
				onStop : null,
				transport : null,
				scope : this
			}

                        if(conf) {
                            if(jscore.isObject(conf)) {
                                for(var k in conf) {
                                    //if((k in this.config) && this.config[k]) {
                                        req[k] = conf[k];
                                    //}
                                }
                            }
                        }

                        return req;
		},
                sendRequest :function(conf) {
                    conf = conf || {};
                    var ajax = this.request(conf);
                    this.send(ajax);
                },
		
		setHeaders : function(request) {
			
			if(jscore.isUndefined(request)) {
				return false;
			}
			
			var transport = null,headers={};
			
			if(request.transport) {
				transport = request.transport;
			} else {
				return false;
			}
			
			if(request.asynchronous) {
								
				//Build Headers
				if(request.method.toLowerCase() == "post" && jscore.isString(request.contentType)) {
					headers['Content-Type'] = request.contentType + (request.encoding ? "; charset="+request.encoding : "");
					
					/* Force "Connection: close" for older Mozilla browsers to work
					* around a bug where XMLHttpRequest sends an incorrect
					* Content-length header. See Mozilla Bugzilla #246651.
					*/
					if (transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1] < 2005) {
						headers['Connection'] = 'close';
					}
				}
				
			}
			
			//Include user request headers
			if(jscore.isObject(request.userHeaders)) {
				for(p in request.userHeaders) {
					headers[p] = request.userHeaders[p];
				}
			}
				
			//Define headers to XMLHTTRequest
			for (p in headers) {
				transport.setRequestHeader(p, headers[p]);
			}	
		},
		
		send : function(request) {
			
			
			if(jscore.isObject(request)) {
				var url,invalid=false,headers={},p,body,_this=this;
				if(request.transport) request.transport = null;
				request.transport = this.transport();
				
				request.timeout_stop = false;
				
				//Build URL
				if(jscore.isString(request.url) && jscore.isString(request.parameters) && jscore.isString(request.method)) {

					url = request.url;
					url += (url.indexOf("?") < 0 ? "?" : "");
					if(request.method.toLowerCase() == "get") {
						url += request.parameters;
					}
					
					if(!request.cacheable && jscore.isString(request.timeStampParameter)) {
						url += "&"+request.timeStampParameter+"="+new Date().getTime();
					}
				} else {
					invalid = true;
				}
				
				if (request.transport) {
					request.transport.open(request.method, url, request.asynchronous);
					request.transport.onreadystatechange = function(){
						stateChange.call(_this, request);
					};
					this.setHeaders(request);
				} else {
					invalid = true;
				}
				
				if (!invalid) {
					body = (request.method.toLowerCase() == "get" ? null : request.parameters);

					request.transport.send(body);
					
					queue[request] = request;
					
					//Timeout timer
					if(jscore.isNumber(request.timeout)) {
						request.timer = window.setTimeout(function(){
							stopTimeout.call(_this,request)
						}, (request.timeout*1000));
					}
					
					return true;
				}
				
				/* Force Firefox to handle ready state 4 for synchronous requests */
				/*
  				if (!this.options.asynchronous && this.transport.overrideMimeType) {
					this.onStateChange();
				}
				//*/
				
			}
			return false;
		},
		
		/*
		 * Check if the transport status code and aborted status matches the data specified in the arguments
		 */
		checkTransport : function(request,statusCode,aborted) {
			try {
			if (jscore.isString(statusCode) && !jscore.isUndefined(aborted)) {
				if (request) {
					if (request.transport) {
						if (request.aborted == aborted) {
							if (request.transport.status == statusCode) {
								return true;
							}
						}
					}
				}
			}
			} catch(ex) {
				return false;
			}
			return false;
		},
		
		stop : function(request) {
			if (request) {
				request.aborted = true;
				request.transport.abort();
				
				if (request.timer) {
					clearTimeout(request.timer);
					request.timer = null;
				}
				
				if (jscore.isFunction(request.onStop)) {
					request.onStop.call(request.scope, request);
				}
			}
		},
		
		ajax_file_upload : function() {
			//Check if plupload is loaded
			if(plupload && plupload.Uploader) {
				console.log("plupload");
			}
		},
		
		ajax_form_data_sorter : function (data,format) {
			format = format || "STRING";
			var rtn=(format == "STRING" ? "" : (format == "OBJECT" ? {} : false)),element_type;
			var input_types = {"file":null,"text":null,"button":null,"checkbox":null,"hidden":null,"image":null,"password":null,"radio":null,"submit":null};
			var input_filter = {"radio":null,"file":null,"checkbox":null};
			if(jscore.isElement(data) && data.nodeName) {

				if(data.nodeName == "INPUT") {
					element_type = data.type.toLowerCase().trim();
					
					if((element_type in input_types) && data.name) {
						
						if(!(element_type in input_filter)) {
							if(format == "STRING") {
								rtn = "&"+data.name+"="+encodeURIComponent(data.value);
							} else if(format == "OBJECT") {
								rtn[data.name] = data.value;
							}
						} else if(element_type == "file") {
							this.ajax_file_upload();
						} else if(element_type == "radio") {
							if(data.checked) {
								if(format == "STRING") {
									rtn = "&"+data.name+"="+encodeURIComponent(data.value);
								} else if(format == "OBJECT") {
									rtn[data.name] = data.value;
								}
							}
						} else if(element_type == "checkbox") {
							if(data.checked) {
								if(format == "STRING") {
									rtn = "&"+data.name+"="+encodeURIComponent(data.value);
								} else if(format == "OBJECT") {
									rtn[data.name] = data.value;
								}
							}
						} else if(element_type == "hidden") {
							if(data.checked) {
								if(format == "STRING") {
									rtn = "&"+data.name+"="+encodeURIComponent(data.value);
								} else if(format == "OBJECT") {
									rtn[data.name] = data.value;
								}
							}
						}
					}
				} else if(data.nodeName == "SELECT") {
				
                    if(data.options && data.selectedIndex > -1 && data.options[data.selectedIndex] && data.options[data.selectedIndex] && data.options[data.selectedIndex].nodeName=="OPTION") {

                    	if(format == "STRING") {
							rtn = "&"+data.name+"="+encodeURIComponent(data.options[data.selectedIndex].value);
						} else if(format == "OBJECT") {
							rtn[data.name] = data.options[data.selectedIndex].value;
						}
						
					}
				} else if(data.nodeName == "TEXTAREA") {
					if(format == "STRING") {
						rtn = "&"+data.name+"="+encodeURIComponent(data.value);
					} else if(format == "OBJECT") {
						rtn[data.name] = data.value;
					}
					
				}
			} else if(typeof(data) == "function") {
				if(data) {
					rtn = data();
					
					if(jscore.isObject(rtn) || jscore.isArray(rtn)) {
						rtn = jscore.json.stringify(rtn);
					}
				}
			}else {
				rtn = data;
			}
			
			if(rtn===false || rtn===null) {
				rtn="";
			}
			
			return rtn;
		},
		
		parse_form : function(form,format,alter_list,exclude_list) {
			format = format || "STRING";
			if(jscore.isString(form)) {
                if(document.forms[form]) {
					form = document.forms[form];
                }
			}
			
			if(!(jscore.isObject(alter_list))) {
				alter_list = {};
			}
			
			if(!(jscore.isObject(exclude_list))) {
				exclude_list = {};
			}
			
			var ajax_post = (format == "STRING" ? "" : (format == "OBJECT" ? {} : false)),key,value;
			
			if(form && alter_list && exclude_list) {
			
				if(form['action']) {
					form_action = form['action'];
				}
				
				for(var e in form.elements) {
					if(form.elements[e] && jscore.isElement(form.elements[e]) && form.elements[e].name) {
						if(!(form.elements[e].name in exclude_list)) {
						
							if(!ajax_post[form.elements[e].name]) {
								ajax_post[form.elements[e].name] =null;
							}
						
							if((form.elements[e].name in alter_list)) {
								key = form.elements[e].name;
								value = this.ajax_form_data_sorter(alter_list[form.elements[e].name],format);
								if(format == 'STRING') {
									ajax_post += "&"+key+"="+value;
								} else if(format == 'OBJECT') {
									ajax_post[key] = value;
								}
							}  else {
								value = this.ajax_form_data_sorter(form.elements[e],format);
								if(format == 'STRING') {
									ajax_post += value;
								} else if(format == 'OBJECT') {
									if(form.elements[e].name && value[form.elements[e].name]) 
										ajax_post[form.elements[e].name] = value[form.elements[e].name];
								}
							}
						}
						
					}
					
				}
			}
			
			return ajax_post;
		},
		
		//Only POST allowed
		form : function(form,callback,alter_list,exclude_list,str_param_extra,send) {
			form = form || false;
                        send = send || true;
			var form_action = "";

                        if(!jscore.isString(str_param_extra)) {
                            str_param_extra = "";
                        }
			
			if(!jscore.isFunction(callback)) {
				callback = false;
			}
			
			if(!(jscore.isObject(alter_list))) {
				alter_list = {};
			}
			
			if(!(jscore.isObject(exclude_list))) {
				exclude_list = {};
			}
			
			var ajax_post = "";
			var keys=[];
			if(form && alter_list && exclude_list) {
			
				if(jscore.isString(form)) {
                                    if(document.forms[form]) {
					form = document.forms[form];
                                    }
				}
					
				if(form) {
					if(form['action']) {
						form_action = form['action'];
					}
					ajax_post = this.parse_form(form,'STRING',alter_list,exclude_list);
					
					
				}
				
				if(send && ajax_post != "") {
					var ajax = this.request();
					ajax.method = "post";
					ajax.url = form_action;
					ajax.parameters=ajax_post+str_param_extra;
					if(callback) {
						ajax.onComplete = function(r) {
							//if(jscore.ajax.checkTransport(r,"200",false)) {
								//if(callback) {
								callback(r);
								//}
							//}
						}
					}
					this.send(ajax);
					//console.log(ajax_post);
				}
			}

			return ajax_post;
		}
	
	 });
 
 })();

