function serialize(obj) {
	return Object.keys(obj).map(function(k) {return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);}).join('&');
}

function ajaxPost(url, data, headers) {
	var promise = {"success": function() {},
					"failure": function() {}};
	var xhttp = new XMLHttpRequest();
	xhttp.open("POST", url, true);
	if(typeof headers != typeof undefined) {
		for (var key in headers) {
			xhttp.setRequestHeader(key, headers[key]);
		}
	}
	xhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4) {
			if(this.status == 200) {
				promise.success(JSON.parse(this.responseText));
			} else {
				var errorData = {};
				errorData.message = this.status + " " + this.statusText;
				errorData.response = this.responseText;
				promise.failure(errorData);
			}
		}
	};

	var dataString = serialize(data);
	xhttp.send(dataString);
	return promise;
}

function ajaxPut(url, binaryData, headers) {
	var promise = {"success": function() {},
					"failure": function() {},
					"finally": function() {}};
	var xhttp = new XMLHttpRequest();
	xhttp.open("PUT", url, true);
	if(typeof headers != typeof undefined) {
		for (var key in headers) {
			xhttp.setRequestHeader(key, headers[key]);
		}
	}
	contentType = "text/plain";
	if('content-type' in headers) {
		contentType = headers['content-type'];
	}
	xhttp.overrideMimeType(contentType + '; charset=x-user-defined-binary');
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4) {
			if(this.status == 200) {
				var successData = {};
				successData.message = this.status + " " + this.statusText;
				successData.response = this.responseText;
				successData.url = this.responseURL;
				promise.success(successData);
			} else {
				var errorData = {};
				errorData.message = this.status + " " + this.statusText;
				errorData.response = this.responseText;
				promise.failure(errorData);
			}

			promise.finally();
		}
	};

	xhttp.send(binaryData);
	return promise;
}

function ajaxGet(url, headers) {
	var promise = {"success": function() {},
					"failure": function() {}};
	var xhttp = new XMLHttpRequest();
	xhttp.open("GET", url, true);
	if(typeof headers != typeof undefined) {
		for (var key in headers) {
			xhttp.setRequestHeader(key, headers[key]);
		}
	}
	//xhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4) {
			if(this.status == 200) {
				promise.success(this.responseText);
			} else {
				var errorData = {};
				errorData.message = this.status + " " + this.statusText;
				errorData.response = this.responseText;
				promise.failure(errorData);
			}
		}
	};

	xhttp.send();
	return promise;
}

function ajaxGetRaw(url, headers) {
	var promise = {"success": function() {},
					"failure": function() {}};
	var xhttp = new XMLHttpRequest();
	xhttp.open("GET", url, true);
	if(typeof headers != typeof undefined) {
		for (var key in headers) {
			xhttp.setRequestHeader(key, headers[key]);
		}
	}
	//xhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4) {
			if(this.status == 200) {
				promise.success(this.responseText);
			} else {
				var errorData = {};
				errorData.message = this.status + " " + this.statusText;
				errorData.response = this.responseText;
				promise.failure(errorData);
			}
		}
	};

	xhttp.send();
	return promise;
}