/**
 * simple "slider" widget
 * 
 * @version 0.2.1 2010-07-24
 * @author Gregor Kofler
 * 
 * @param {Object} configuration (all properties are optional)
 *	min:		{Number} lower bound
 *	max:		{Number} upper bound
 *  dir:		{String} direction "x" or "y"
 *	steps:		{Number} allow only a defined number of steps between min and max
 *	value:		{Number} initial value
 *
 * @return {Object} slider object
 * 
 * served events: "valueChange", "grab", "release"
 * 
 */
/*global vxJS*/

if(!this.vxJS) { throw Error("widget.slider: vxJS core missing."); }

vxJS.widget.slider = function(config) {
	var element, handle, theLeft, dir, eSize, eOffs, steps, dStep, lastPos, min, max, value,
		s = {}, mmListenerId, muListenerId;

	var setHandlePos = function(pos) {
		if(steps) {
			pos = (pos/100*(steps - 1)).toFixed() * 100/(steps - 1);
		}
		if(pos < 0) {
			pos = 0;
		}
		else if(pos > 100) {
			pos = 100;
		}
		if(lastPos === pos) {
			return false;
		}
		lastPos = pos;

		handle.style[dir === "y" ? "top" : "left"]		= pos + "%";
		theLeft.style[dir === "y" ? "height" : "width"]	= pos + "%";

		value = pos/100 * (max-min) + min;
		return true;
	};

	var setValue = function(v) {
		if(isNaN(+v)) {
			return;
		}
		eSize = vxJS.dom.getElementSize(element);
		setHandlePos((v-min)/(max-min) * 100);
	};

	var mouseMove = function(e) {
		if(setHandlePos((vxJS.event.getAbsMousePos(e)[dir] - eOffs[dir])/eSize[dir] * 100)) {
			vxJS.event.serve(s, "valueChange");
		}
		vxJS.event.preventDefault(e);
	};

	var mouseUp = function(e) {
		vxJS.event.removeListener(mmListenerId);
		vxJS.event.removeListener(muListenerId);
		vxJS.event.serve(s, "release");
		handle.className = "handle";
	};

	var mouseDown = function(e) {
		eSize = vxJS.dom.getElementSize(element);
		eOffs = vxJS.dom.getElementOffset(element);

		if(setHandlePos((vxJS.event.getAbsMousePos(e)[dir] - eOffs[dir])/eSize[dir] * 100)) {
			vxJS.event.serve(s, "valueChange");
		}
		handle.className = "handle active";
		vxJS.event.serve(s, "grab");

		mmListenerId = vxJS.event.addListener(document, "mousemove", mouseMove);
		muListenerId = vxJS.event.addListener(document, "mouseup", mouseUp);

		vxJS.event.preventDefault(e);
	};
	
	if(!config) {
		config = {};
	}
	min		= config.min && +config.min || 0;
	max		= config.max && +config.max || 1;
	steps	= config.steps && parseInt(config.steps, 10);
	dir		= /^[xy]$/i.test(config.dir) ? config.dir.toLowerCase() : "x";

	handle = "div".setProp("class", "handle").create();
	handle.style.position = "absolute";
	handle.style[dir === "y" ? "top" : "left"] = "0px";

	theLeft = "div".setProp("class", "theLeft").create();
	theLeft.style.position = "absolute";
	theLeft.style[dir === "y" ? "height" : "width"] = "0px";

	element = "div".setProp("class", "vxJS_slider").create([theLeft, handle]);
	element.style.position = "relative";
	setValue(config.value && +config.value ? config.value : min);

	vxJS.event.addListener(element, "mousedown", mouseDown);

	s.element = element;
	s.setValue = setValue;
	s.getValue = function() { return value; };
	
	return s;
};