/*
 * declare mdvLib namespace
 */

var mdvLib;

if (!mdvLib) {
	mdvLib = {};	
}

/*
 * PROTOTYPE dollar function
 * @param		one or many IDs and/or DOM elements (comma separated) 
 * @return		array of or single DOM element(s) 
 */	
 
mdvLib.$ = function() {
	var elements = [];
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element === 'string')
			element = document.getElementById(element);
		if (arguments.length === 1)
			return element;
		elements.push(element);
	}
	return elements;
};

/*
 * getElementPosition
 * @param		DOM element 
 * @return		object literal with properties left and top,
 * 				holding boundingbox top/left values in px
 * 				measured from the browser's top/left corner. 
 */

mdvLib.getElementPosition = function(el) {
	var leftPos = el.offsetLeft;
	var topPos = el.offsetTop;
	var parentEl = el.offsetParent;  
	
	while (parentEl !== null) {
		leftPos += parentEl.offsetLeft;
		topPos += parentEl.offsetTop;  
		parentEl = parentEl.offsetParent;
	}
	return { left: leftPos, top: topPos };
};

/*
 * getMousePosition
 * @param		mouse event 
 * @return		object literal with properties left and top,
 * 				holding values in px measured from the browser's
 * 				top/left corner. 
 */
	
mdvLib.getMousePosition = function(e) {
	var posx = 0;
	var posy = 0;
	var e = e || window.event;
	
	if (e.pageX || e.pageY) {
		posx = e.pageX;
		posy = e.pageY;
	} else if (e.clientX || e.clientY) {
		posx = e.clientX + (document.documentElement.scrollLeft? document.documentElement.scrollLeft : document.body.scrollLeft);
		posy = e.clientY + (document.documentElement.scrollTop? document.documentElement.scrollTop : document.body.scrollTop);
	}	
	return { left: posx, top: posy };  
};

/*
 * style
 * @param		array of IDs and/or DOM elements
 * @param		object literal of styles to be applied 
 * @return		true on success 
 * 				example: mdvLib.style([o1, el2], { color: 'yellow', display: 'block' });
 */	
 
mdvLib.style = function (a, o) {
	
	if(mdvLib.typeOf(a) !== 'array') {
		return false;
	}
	
	for(var i = 0; i < a.length; i++) {
		for (var s in o) {
			mdvLib.$(a[i]).style[s] = o[s];
		}
	}
	return true;	
};

/*
 * typeOf
 * type detection function from http://javascript.crockford.com/remedial.html
 * @param		value to check
 * @return		string with the type of value 
 */

mdvLib.typeOf = function(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
};

mdvLib.createImg = function(styleObj, propObj) {

	var img = document.createElement('img');

	if(mdvLib.typeOf(propObj) === 'object') {
		for(var prop in propObj) {
			img[prop] = propObj[prop];
		}
	}
	
	if(mdvLib.typeOf(styleObj) === 'object') {
		mdvLib.style([img], styleObj);
	}
	return img;
};

mdvLib.correctPNG = function(map, img) {
	
	if (!document.body.filters || !img || !map) {
		 return;
	}
	
	if (img.src == map.transparent.src) {
		return true;
	}
	
	if (mdvLib.typeOf(img) === 'array') {
		for(var i=0; i < img.length; i++ ) {
			addFilter(img[i]);
		}
	} else {
		addFilter(img);
	}

	function addFilter(image) {
		var src = image.src;
		var s = image.runtimeStyle;
		s.width = image.offsetWidth + "px";
		s.height = image.offsetHeight + "px";
		s.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\'), sizingMethod=\'crop\'';
		image.src = map.transparent.src;
	}
};
/*
 * @param {object}	use PROTOTYPE member names for options. Other libs are matched.
 * 					http://www.sergiopereira.com/articles/prototype.js.html#Ajax.options
 * @return {object}	the request object or null in case of failure.
 */
mdvLib.ajax = function(optionsObj) {
	
	var options, lib, method, params, sendRequest, appendToSendOptions, sendOptions = {};
	
	// define matching values for optionsObj 
	var jquery = {
		host: 'url',
		method: 'type',
		asynchronous: 'async',
		contentType: 'contentType',
		encoding: 'scriptCharset',
		parameters: 'data',
		onComplete: 'complete',
		onFailure: 'error',
		onSuccess: 'success'
	};
	
	// define matching MOOTOOLS values for optionsObj 
	var moo = {
		host: 'url',
		method: 'method',
		asynchronous: 'async',
		contentType: 'urlEncoded',
		encoding: 'encoding',
		parameters: 'data',
		onComplete: 'onComplete',
		onFailure: 'onFailure',
		onSuccess: 'onSuccess',
		request: null
	};
	
	options = optionsObj || null;
	
	// host is mandatory
	if (!options || options.host === undefined) {
		return null;	
	}
	
	lib = (typeof Prototype !== 'undefined' && Prototype.Version) ? 'PROTOTYPE' : 
			  (typeof jQuery !== 'undefined' && jQuery.fn) ? 'JQUERY' : 
			    (typeof MooTools !== 'undefined' && MooTools.version) ? 'MOOTOOLS' : 
			    	null;
	
	method = options.method || 'post';
	method = method.toLowerCase();
	params = options.parameters || '';
	
	appendToSendOptions = function(obj, exclude) {
		
		var p, q;
		
		for (p in obj) {
			if (obj.hasOwnProperty(p) && (!exclude || exclude[p] !== true)) {
				q = lib === 'PROTOTYPE' ? p : 
					lib === 'JQUERY' ? jquery[p] || p : 
					lib === 'MOOTOOLS' ? moo[p] : p;
				sendOptions[q] = obj[p];
			}
		} 
	};
	
	sendRequest = function() {
		
		switch(lib) {
			
			case 'PROTOTYPE':	// parameters need special treatment
								params = $H(params);
		 						params = params.toQueryString();
		 						sendOptions.parameters = params;
		 						
		 						// method also goes separately
		 						// as it is not mandatory in the options argument 
		 						sendOptions.method = method;
		 						
		 						//append all other options members
		 						appendToSendOptions(options, { host: true, parameters: true }); 
		 						// fire request and return an object reference
		 						return new Ajax.Request(options.host, sendOptions);
		 						
								
			case 'JQUERY':		// jquery handles params format by itself, so append the whole lot
								appendToSendOptions(options);
								if (sendOptions.method === undefined) {
									// jquery defaults to GET. switch it to POST if no method is specified.
									sendOptions.type = method;
								}
								return $.ajax(sendOptions);

			case 'MOOTOOLS':	appendToSendOptions(options, { parameters: true });
								// parameters need special treatment
								if (params !== '') {
									params = new Hash(params);
									params = params.toQueryString();
								}
								moo.request = new Request(sendOptions);
								return moo.request.send(params);
								
			default: 			// own implementation of AJAX goes here
								return null;
		}
	};
	
	return sendRequest();
	
};

function attachEventListener(target, eventType, functionRef, capture) {
			
	var oldListener;
	
	if (typeof target.addEventListener != "undefined") {
		target.addEventListener(eventType, functionRef, capture);
	} else if (typeof target.attachEvent != "undefined") {
		target.attachEvent("on" + eventType, functionRef);
	} else {
		eventType = "on" + eventType;
		if (typeof target[eventType] == "function")	{
			oldListener = target[eventType];
			target[eventType] = function() {
									oldListener();
									return  functionRef();
								};
		} else {
			target[eventType] = functionRef;
		}
	}
	return true; 
}

/*
 * 
 * PREDEFINED OBJECTS
 * extend only if method is not defined elsewhere.
*/
if (typeof Function.prototype.bind !== 'function') {
 	Function.prototype.bind = function(obj) {
	  var method = this, temp = function() {
	    return method.apply(obj, arguments);
	   };
	  return temp;
	 }; 
}

if (typeof String.prototype.trim !== 'function') {
	String.prototype.trim = function () {
	    return this.replace(/^\s+|\s+$/g, "");
	}; 
}
