if (!window.nDynamic) alert('Require nDynamic library.');

/**
 * Interactive animation loop.
 *
 * Callbacks order:
 * 		public		onInitialize
 * 		protected	onAddEvent
 * 		protected	beforeActivate
 * 		public		onActivate
 * 		public	{	onLoop
 * 		public		onUpdate	}
 * 		public 		onDeactivate
 * 		protected	onDropEvent
 * 		protected	afterDeactivate
 */
function nListener(options) {
	this.nName = 'nListener';
	
	this.setOptions = function(options) {
		if (options) {
			// Ustawianie konfiguracji:
			for (option in options) {
				this[option] = options[option];
			}
		}
	}
	
	this.activate = function(options) {
		activateOptions = options;
		active = false;

		this.onAddEvent();
	}
	
	this.onAddEvent = function() {
		nConfig.addEvent(this.activator, this.eventType, this.run);
	}
	
	this.deactivate = function() {
		if (this.onDeactivate) {
			this.onDeactivate();
		}
		
		this.onDropEvent();
		active = false;
		activateOptions = null;
		
		if (this.afterDeactivate) {
			this.afterDeactivate();
		}
		
		return this; // @todo : czy to potrzebne?
	}
	
	this.onDropEvent = function() {
		nConfig.dropEvent(this.activator, this.eventType, this.run);
	}
	
	this.run = function(e) {
		listener.event = e || window.event;
		
		if (active == false) {
			active = true;
			if (listener.beforeActivate) {
				listener.beforeActivate();
			}
			if (listener.onActivate) {
				listener.onActivate(activateOptions);
			}
		}
		
		if (active == true) {
			if (listener.onLoop) {
				listener.onLoop();
			}
			
			if (listener.onUpdate) {
				listener.onUpdate();
			}
		}
	}
	
	// konstruktor {
		var listener = this;
		var active = false;
		var activateOptions = null;
		
		this.eventType = 'mousemove';
		this.activator = document;

		this.event = null;
		this.setOptions(options);
		
		if (this.onInitialize) {
			this.onInitialize();
		}
	// }
	
	
	// For use in onLoop:
	this.offset = function() {
		if (this.event.offsetX != undefined) {
			return {x: this.event.offsetX, y: this.event.offsetY};
		} else {
			return {x: this.event.layerX, y: this.event.layerY};
		}
	}
	
	// For use in onActivate:
	this.preventTextSelection = function() {
		document.body.focus();
		document.onselectstart = function() { return false; }
	}
	
	return this;
}

nConfig.addEvent = function(node, type, callback) {
	if (node.addEventListener) {
		node.addEventListener(type, callback, false);
	} else {
		node.attachEvent('on' + type, callback);
	}
}

nConfig.dropEvent = function(node, type, callback) {
	if (node.removeEventListener) {
		node.removeEventListener(type, callback, false);
	} else {
		node.detachEvent('on' + type, callback);
	}
}


function nDragNDrop(obj, autoInit, options) {
	nDynamic(obj);
	obj.nName = 'nDragNDrop';
	
	obj.dragging = obj.point({
		onUpdate:function() {
			this.obj.style.marginLeft = this.n.x + 'px';
			this.obj.style.marginTop = this.n.y + 'px';
		}
	});
	
	obj.drag = function() {
		this.dragging.activate();
		nConfig.addEvent(document, 'mouseup', obj.drop);
	}
	
	obj.drop = function() {
		obj.dragging.deactivate();
	}
	
	if (options) {
		obj.dragging.setOptions(options);
	}
	
	if (autoInit) {
		obj.onmousedown = obj.drag;
	}
}