/**
 * Dynamize object.
 * Add new features to object, dependend on loaded nLibraries.
 * @author : Nickesh (nickesh.pl[at]gmail.com).
 * @copyright : 2007 Nickesh
 */
function nDynamic(obj) {
	obj.nName = 'nDynamic';

	if (window.nAction) {
		obj.motion = function(options) {
			var motionAction = new nAction({
				obj: obj,
				beforeActivate:function(end) {
					if (end != undefined) {
						this.end = end;
					}
					this.start = this.n;
					this.detectDirection();
				},
				onLoop:function() {
					this.decelerate();
				},
				onEndDetection:function() {
					if (this.isEnd()) {
						this.n = this.end;
						this.deactivate();
					}
				},
				onInitialize: ((options.onInitialize)? options.onInitialize : null)
				//onActivate
				//onUpdate
				//onDeactivate
			});
			
			motionAction.setOptions(options);
			return motionAction;
		}
	}
	
	if (window.nListener) {
		obj.point = function(options) {
			var newListener = new nListener({
				obj: obj,
				start: {x: 0, y: 0},
				n: {x: 0, y: 0},
				startScreen: null,
				
				// onInitialize
				beforeActivate:function() {
					this.startScreen = {x: this.event.screenX, y: this.event.screenY};
					this.preventTextSelection();
				},
				// onActivate
				onLoop:function() {
					this.captureRelativeXY();
				},
				captureRelativeXY:function() {
					this.n.x = this.relativeX();
					this.n.y = this.relativeY();
				},
				relativeX:function() {
					return this.start.x + this.distanceX();
				},
				relativeY:function() {
					return this.start.y + this.distanceY();
				},
				distanceX:function() {
					return this.event.screenX - this.startScreen.x;
				},
				distanceY:function() {
					return this.event.screenY - this.startScreen.y;
				},
				limit:function(n, min, max) {
					if (n < min) return min;
					if (n > max) return max;
					return n;
				},
				// onUpdate
				// onDeactivate
				afterDeactivate:function() {
					this.start = {x: this.n.x, y: this.n.y};
					this.startScreen = null;
				}
			});
			newListener.setOptions(options);
			return newListener;
		}
	}
	
	
	obj.css = function(styles) {
		if (styles) {
			for (var i in styles) {
				if (i == 'opacity') {
					// @todo: ujednolicic metode definiowania opacity w IE (0% - 100%) i pozostalych przegladarkach (0 - 1) - najlepiej sprawdzac przegladarke przy instancjalizacji, niz przy kazdym wywolaniu metody css()
//					this.style[i] = styles[i];
					this.cssOpacity(styles[i]);
				} else {
					this.style[i] = styles[i];
				}
			}
		}
	}
	
	
	obj.addClass = function(className) {
		this.className += ' ' + className;
	}
	
	
	obj.dropClass = function(className) {
		this.className = this.className.replace(new RegExp('\\b' + className + '\\b'), '');
	}
	
	
	if (nConfig.isIE) {
		obj.cssOpacity = function(value) {
			this.style.filter = 'alpha(opacity=' + value + ')';
		}
	} else {
		obj.cssOpacity = function(value) {
			this.style.opacity = value / 100;
		}
	}
	
	obj.config = {};
	
	obj.configure = function(config) {
		for (var i in config) {
			this.config[i] = config[i];
		}
	}
}


function nConfig() {
	this.isOpera = (navigator.userAgent.indexOf('Opera') != -1);
	this.isIE = (!this.isOpera && navigator.userAgent.indexOf('MSIE') != -1);

// @todo ...
//	this.init = function() {}
//	this.init();
	this.include = function(file) {
		var script  = document.createElement('script');
		script.src  = file;
		script.type = 'text/javascript';
		script.defer = true;

		document.getElementsByTagName('head').item(0).appendChild(script);
	}
}

var nConfig = new nConfig();



// ========= "Dolar functions": ============

if (!window.$) {
	function $(id) {
		return document.getElementById(id);
	}
}


/**
 * Wyszukuje elementy o podanej klasie.
 * Jesli podano tag, wyszuka tylko elementy tych tagow.
 * Jesli podano node, bedzie szukac tylko wewnatrz tego obiektu.
 */
if (!window.$$) {
	function $$(className, tag, node) {
		if (!node) {
			node = document;
		} else if (typeof(node) != 'object') {
			node = $(node);
		}
		
		if (tag == null)
			tag = '*';
		
		var i, j = 0;
		var classElements = new Array;
		var allElements = node.getElementsByTagName(tag);
		
		for (i = 0; i < allElements.length; i++) {
			if (!className || allElements[i].className.match(new RegExp('\\b' + className + '\\b'))) {
				classElements[j] = allElements[i];
				j++;
			}
		}
		
		return classElements;
	}
}


/**
 * Wyszukuje bezposrednie elementy o podanej klasie.
 * Jesli podano tag, wyszuka tylko elementy tych tagow.
 * Jesli podano node, bedzie szukac tylko wewnatrz tego obiektu.
 * @todo : naprawic ta funkcje - teraz cos jest nie tak z rozpoznawaniem bezposrednich potomkow node'a. Interpretacja childNodes zalezy od przegladarki.
 */
if (!window.$$$) {
	function $$$(className, tag, node) {
		if (!node) {
			node = document;
		} else if (typeof(node) != 'object') {
			node = $(node);
		}
		
		if (!tag || tag == '*')
			tag = '';
			
		tag = tag.toLowerCase();
		
		var nodes = new Array;
		
		for (var i in node.childNodes) {
			if (nConfig.isOpera && node.childNodes[i].parentNode != node) {
				break;
			}
			
			if (node.childNodes[i].nodeType == 1) {
				if (!className || (node.childNodes[i].className && node.childNodes[i].className.match(new RegExp('\\b' + className + '\\b')))) {
					if (!tag || node.childNodes[i].tagName.toLowerCase() == tag) {
						nodes.push(node.childNodes[i]);
					}
				}
			}
		}

		return nodes;
	}
}

/**
 * nic nie robi
 */
function nev2006() {

}