// core.js: Core library

var Core = function() {
	// configuration

	// private variables & initialization
	var AJAXThreads = 0;
	var lock = new Array();
	var logContainer = document.createElement('div');
	var debugLevel = 0;

	// private methods
	function getAJAX() {
		var request = null;
		try {
			request = new XMLHttpRequest();
		} catch(trymicrosoft) {
			try {
				request = new ActiveXObject('Msxml2.XMLHTTP');
			} catch(othermicrosoft) {
				try {
					request = new ActiveXObject('Microsoft.XMLHTTP');
				} catch(failed) {
					request = null;
				}
			}
		}
		return request;
	}

	function _encodeJSON(object, prefix) {
		var string = '';
		var newPrefix = '';
		if(prefix !== null) {
			newPrefix = prefix + '.';
		}
		if(typeof object == 'object' || typeof object == 'array') {
			for(var i in object) {
				string += _encodeJSON(object[i], newPrefix + i);
			}
		} else {
			if(prefix !== null) {
				string = prefix + '=' + encodeURIComponent(object.toString()) + '&';
			}
		}
		if(string.length <= 1) return null;
		if(prefix === null) {
			string = string.substr(0, string.length - 1);
		}
		return string;
	}
	
	function _writeLog(src, msg, level) {
		var numericLevel = 0;
		switch(level) {
			case 'error': numericLevel = 1; break;
			case 'warning': numericLevel = 2; break;
			case 'info': numericLevel = 3; break;
			default: numericLevel = 3; level = 'info'; break;
		}
		if(numericLevel <= debugLevel) {
			var dateObject = new Date();
			var ts = dateObject.toLocaleTimeString();
			delete dateObject;
			logContainer.innerHTML += '<div class="' + level + '"><span class="timestamp">' + ts + '</span>&nbsp;<span class="source">' + src + '</span>:&nbsp;' + msg + '</div>' + "\n";
		}
	}

	function _hasClass(object, classname) {
		var classes = object.className.split(' ');
		return (_findInArray(classes, classname) >= 0);
	}

	function _findInArray(array, element) {
		if(typeof array.indexOf == 'undefined') {
			for(var i = 0; i < array.length; i++)
				if(array[i] == element) return i;
			return -1;
		} else return array.indexOf(element);
	}
	
	// public methods
	return {
		getUID : function() {
			var s = '';
			for(var i = 1; i <= 4; i++) {
				s += Math.floor(Math.random() * 65536).toString(16);
				while(s.length < (4 * i)) s = '0' + s;
			}
			return s;
		},

		loadLibrary : function(url) {
			var head = document.getElementsByTagName('head')[0];
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = url;
			head.appendChild(script);
		},

		loadStyle : function(url) {
			var head = document.getElementsByTagName('head')[0];
			var link = document.createElement('link');
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = url;
			head.appendChild(link);
		},

		writeCookie : function(name, value, days, path) {
			var valueString = encodeURIComponent(JSON.stringify(value));
			var expires = '';
			if(typeof days != 'undefined' && !isNaN(days)) {
				var date = new Date();
				date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
				expires = '; expires=' + date.toGMTString();
			}
			if(typeof path == 'undefined') path = '/';
			document.cookie = name + '=' + valueString + expires + '; path=' + path;
			_writeLog('Core::writeCookie', 'Cookie ' + name + ' written', 'info');
		},

		readCookie : function(name) {
			var resultString = null;
			var cookiesArray = document.cookie.split(';');
			for(var i = 0; i < cookiesArray.length; i++) {
				var cookieString = cookiesArray[i].replace(/^\s+|\s+$/g, '');
				if(cookieString.indexOf(name + '=') == 0) {
					result = cookieString.substr(name.length + 1);
					break;
				}
			}
			if(resultString === null) return;
			return JSON.parse(decodeURIComponent(resultString));
		},

		lock : function (resource, callback) {
			if(typeof lock[resource] == 'undefined') {
				lock[resource] = new Array();
			}
			lock[resource][lock[resource].length] = callback;
			if(lock[resource].length == 1) {
				setTimeout(callback, 0);
			}
		},

		release : function (resource) {
			lock[resource].splice(0, 1);
			if(lock[resource].length > 0) {
				setTimeout(lock[resource][0], 0);
			} else delete lock[resource];
		},

		loadContent : function (url, post, object, callback) {
			var data = null;
			var method = 'GET';
			var request = getAJAX();
			if(request !== null) {
				if(typeof post != 'undefined' && post !== null) {
					data = post;
					method = 'POST';
//					request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//					request.setRequestHeader("Content-length", data.length);
//					request.setRequestHeader("Connection", "close");
				}
				request.open(method, url, true);
				request.onreadystatechange = function() {
					if(this.readyState == 4) {
						AJAXThreads--;
						if(typeof object != 'undefined' && object !== null)
							object.innerHTML += this.responseText;
						if(typeof callback != 'undefined' && callback !== null) callback(this);
						_writeLog('Core::loadContent', 'Request for ' + this.url + 'completed with status ' + this.status, 'info');
					}
				}
				AJAXThreads++;
				_writeLog('Core::loadContent', 'Requesting ' + this.url + 'with method ' + method, 'info');
				request.send(data);
			} else {
				_writeLog('Core::loadContent', 'Unable to create HTTP request object', 'error');
			}
		},

		encodeJSON : function (object) {
			return _encodeJSON(object, null);
		},

		checkAJAX : function () {
			return (getAJAX() !== null);
		},

		addEvent : function (object, eventName, callbackFunction, bubblePropagation) {
			if(typeof bubblePropagation == 'undefined')
				var bubblePropagation = true;
			if(window.addEventListener) {
				object.addEventListener(eventName, callbackFunction, bubblePropagation);
			} else {
				object.attachEvent('on' + eventName, callbackFunction);
			}
			_writeLog('Core::removeEvent', 'Event ' + eventName + ' added', 'info');
		},

		removeEvent : function (object, eventName, callbackFunction, bubblePropagation) {
			if(typeof bubblePropagation == 'undefined')
				var bubblePropagation = true;
			if(window.removeEventListener) {
				object.removeEventListener(eventName, callbackFunction, bubblePropagation);
			} else {
				object.detachEvent('on' + eventName, callbackFunction);
			}
			_writeLog('Core::removeEvent', 'Event ' + eventName + ' removed', 'info');
		},

		getEventTarget : function (event) {
			var object = null;
			if(typeof event.target != 'undefined') {
				object = event.target;
			} else if(typeof event.srcElement != 'undefined') {
				object = event.srcElement;
			}
			return object;
		},
		
		writeLog : function (src, msg, level) {
			_writeLog(src, msg, level);
		},

		createLog : function (container) {
			container.appendChild(logContainer);
		},
		
		deleteLog : function (container) {
			container.removeChild(logContainer);
		},
		
		setDebugLevel : function(level) {
			switch(level) {
				case 'error': debugLevel = 1; break;
				case 'warning': debugLevel = 2; break;
				case 'info': debugLevel = 3; break;
				default: debugLevel = 0; break;
			}
		},
		
		findInArray : function(array, element) {
			_findInArray(array, element);
		},

		hasClass : function(object, classname) { return _hasClass(object, classname); },

		addClass : function(object, classname) {
			if(!_hasClass(object, classname))
				if(object.className === '') object.className = classname;
				else object.className += ' ' + classname;
		},

		removeClass : function(object, classname) {
			if(_hasClass(object, classname)) {
				var classes = object.className.split(' ');
				var i = 0;
				while(i < classes.length) {
					if(classes[i] == '' || classes[i] == classname)
						classes.splice(i, 1);
					else i++;
				}
				object.className = classes.join(' ');
			}
		},
		
		sendRequest : function(url, object) {
			var method = 'GET';
			var data = null;
			if(typeof object != 'undefined' && object !== null) {
				method = 'POST';
				data = encodeURIComponent(JSON.stringify(object));
			}
			var request = getAJAX();
			if(request === null) return;
			request.open(method, url, false);
			request.send(data);
			if(request.status == '200') return JSON.parse(request.responseText);
			else return { 'ok': false, 'error': 'http_error' };
		},
		
		initLibrary : function(library) {
			if(typeof library.init != 'undefined') {
				if(document.readyState != 'complete') {
					if(window.addEventListener) {
						window.addEventListener('load', library.init, false);
					} else {
						window.attachEvent('onload', library.init);
					}
				} else {
					library.init();
				}
			}
		}
	};
} ();

