/**
 * simple "slider" widget
 * 
 * @version 0.0.5 2009-06-22
 * @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, only used when container provided
 *	container:	{Object} DOM element which return
 *
 * @return {Object} slider object
 * 
 * served events: "change"
 * 
 */
/*global vxJS*/

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

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

	var setHandlePos = function(pos) {
		if(dStep) {
			pos = Math.round(pos/dStep) * dStep;
		}
		if(lastPos === pos) {
			return false;
		}
		if(pos < 0) {
			pos = 0;
		}
		else if(pos > eSize[dir]) {
			pos = eSize[dir];
		}
		lastPos = pos;
		handle.style[dir === "y" ? "top" : "left"]		= pos + "px";
		theLeft.style[dir === "y" ? "height" : "width"]	= pos + "px";

		value = pos/eSize[dir] * (max-min) + min;
		return true;
	};

	var setValue = function(v) {
		if(!parseFloat(v)) {
			return;
		}
		eSize = vxJS.dom.getElementSize(element);
		setHandlePos(eSize[dir]/(max-min) * (v-min));
	};

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

		if(steps) {
			dStep = eSize[dir]/steps;
		}

		if(setHandlePos(vxJS.event.getAbsMousePos(e)[dir] - eOffs[dir])) {
			vxJS.event.serve(that, "change");
		}
		drag = true;
		vxJS.event.preventDefault(e);
	};
	
	var mouseMove = function(e) {
		if(!drag) {
			return;
		}
		if(setHandlePos(vxJS.event.getAbsMousePos(e)[dir] - eOffs[dir])) {
			vxJS.event.serve(that, "change");
		}
		vxJS.event.preventDefault(e);
	};

	var mouseUp = function(e) {
		drag = false;
	};
	
	if(!config) {
		config = {};
	}
	min		= config.min && parseFloat(config.min) || 0;
	max		= config.max && parseFloat(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";

	vxJS.event.addListener(element, "mousedown", mouseDown);
	vxJS.event.addListener(document, "mousemove", mouseMove);
	vxJS.event.addListener(document, "mouseup", mouseUp);

	if(config.container) {
		config.container.appendChild(element);
		setValue(config.value && parseFloat(config.value) ? config.value : min);
	}

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