var Slider = new Class({
	options: {
		onChange: Class.empty,
		onComplete: Class.empty,
		onMove: Class.empty,
		onTick: function(pos){
			this.moveKnob.setStyle(this.p, pos);
		},
		start: 0,
		end: 100,
		offset: 0,
		knobheight: 20,
		knobwidth: 14,
		mode: 'horizontal',
		clip_w:0, 
		clip_l:0,
		isinit:true,
		snap: false,
		range: false,
		numsteps:null,
		gutters:false
	},
    initialize: function(el, knob, bkg, options, maxknob) {
		this.setOptions(options);
		this.element = $(el);
		this.knob = $(knob);
		this.previousChange = this.previousEnd = this.step = -1;
		this.bkg = $(bkg);
		if(this.options.steps==null){
			this.options.steps = this.options.end - this.options.start;
		}
		this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
		if(this.options.gutters){
			this.element.getPrevious().addEvent('mousedown', this.down.bindWithEvent(this));
			this.element.getNext().addEvent('mousedown', this.up.bindWithEvent(this));
		}
		if(maxknob!=null)
			this.maxknob = $(maxknob);

		var mod, offset;
		switch(this.options.mode){
			case 'horizontal':
				this.z = 'x';
				this.p = 'left';
				mod = {'x': 'left', 'y': false};
				offset = 'offsetWidth';
				break;
			case 'vertical':
				this.z = 'y';
				this.p = 'top';
				mod = {'x': false, 'y': 'top'};
				offset = 'offsetHeight';
		}
		this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
		this.half = this.knob[offset]/2;
		this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
		this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
		this.getPos = this.element['get' + this.p.capitalize()].bind(this.element);
		this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset);
		this.range = this.max - this.min;
		this.steps = this.options.steps || this.full;
		this.stepSize = Math.abs(this.range) / this.steps;
		this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
		if(maxknob != null) {
			this.maxPreviousChange = -1;
			this.maxPreviousEnd = -1;
			this.maxstep = this.options.end;
			this.maxknob.setStyle('position', 'relative').setStyle(this.p, + this.max - this.options.offset).setStyle('bottom', this.options.knobheight);
		}
		var lim = {};
		//status = this.z
		lim[this.z] = [- this.options.offset, this.max - this.options.offset];
		//lim[this.z] = [100, this.max - this.options.offset];

		this.drag = new Drag(this.knob, {
			limit: lim,
			modifiers: mod,
			snap: 0,
			onStart: function(){
				this.draggedKnob();
			}.bind(this),
			onDrag: function(){
				this.draggedKnob();
			}.bind(this),
			onComplete: function(){
				this.draggedKnob();
				this.end();
			}.bind(this)
		});

		if (this.options.snap) {
			//this.drag.options.grid = Math.ceil(this.stepWidth);
			this.drag.options.grid = (this.full)/this.options.numsteps ;
			this.drag.options.limit[this.z][1] = this.full;
			//this.drag.options.grid = this.drag.options.grid - (this.knob[offset]/this.options.numsteps);
			status = "GRID - " + this.drag.options.grid  + "  , full = " + this.full// DEBUG

		}
		if (this.options.initialize) this.options.initialize.call(this);
    },
	set:function(val){
		this.step=val!=undefined?val:Math.round(this.options.end/2);
		this.checkStep(1);
		this.moveKnob = this.knob;
		var position=this.toPosition(this.step);
		this.setKnobPos(position);
		this.fireEvent('onMove', position);
		return this;
	},
	setMin: function(stepMin){
		this.step = stepMin.limit(this.options.start, this.options.end);
		this.checkStep();
		this.end();
		this.moveKnob = this.knob;

		this.fireEvent('onTick', this.toPosition(this.step));
		return this;
	},
	setMax: function(stepMax){
		this.maxstep = stepMax.limit(this.options.start, this.options.end);
		this.checkStep(1);
		this.end();
		this.moveKnob = this.maxknob;
		var w= Math.abs(this.toPosition(this.step)- this.toPosition(this.maxstep)) + 3 ;
		var r = parseInt(this.clip_l + w); 

		this.fireEvent('onTick', this.toPosition(this.maxstep));
		// For Init Only 
		if(this.options.isinit){
			var lim = {}; var mi,mx;
			mi = - this.options.offset; 
			mx= parseInt(this.maxknob.getStyle('left')) - this.options.offset-4 ;
			lim[this.z] = [mi, mx];
			this.drag.options.limit = lim;
			this.options.isinit = false;
		}
		return this; 
	},
	clickedElement: function(event){
		var position = event.page[this.z] - this.getPos() - this.half;
		position = position.limit(-this.options.offset, this.max -this.options.offset);

		this.step = this.toStep(position);
		this.checkStep();
		this.end();
		this.fireEvent('onTick', position);
		this.fireEvent('onMove', position);
		if(this.bkg){
			this.clip_l = parseInt(this.knob.getStyle('left')) + 10;
			this.bkg.style.width = this.clip_l+"px";
		}
	},

	draggedKnob: function(mx){
		var lim = {}; var mi,mx;
		if(mx==null) {
			var position=this.drag.value.now[this.z];
			this.step = this.toStep(position);
			this.fireEvent('onMove', position);
			this.checkStep();
		}else{
			this.maxstep = this.toStep(this.maxdrag.value.now[this.z]); 
			this.checkStep(1);
		}
//		this.fireEvent('onTick', this.toPosition(this.step));
	},
	checkStep: function(mx){
		var lim = {};
		var mi,mx;
		var limm = {};
		if(mx==null) {if (this.previousChange != this.step){this.previousChange = this.step;}}
		else {if (this.maxPreviousChange != this.maxstep){this.maxPreviousChange = this.maxstep;}}
		this.fireEvent('onChange', this.step);

		if(this.bkg){
			this.clip_l = parseInt(this.knob.getStyle('left')) + 10;
			this.bkg.style.width = this.clip_l+"px";
		}
	},
	end: function(){
		if (this.previousEnd !== this.step || (this.maxknob != null && this.maxPreviousEnd != this.maxstep)) {
			this.previousEnd = this.step;
			if(this.maxknob != null) {
				this.maxPreviousEnd = this.maxstep;
				if(this.step < this.maxstep)
					this.fireEvent('onComplete', { minpos: this.step + '', maxpos: this.maxstep + '' });
				else    
					this.fireEvent('onComplete', { minpos: this.maxstep + '', maxpos: this.step + '' });
			}else{  
				this.fireEvent('onComplete', this.step + '');
			}
		}
	},
	
	toStep: function(position){
		return Math.round((position + this.options.offset) / this.max * this.options.steps) + this.options.start;
	},
	toPosition: function(step){
		return (this.max * step / this.options.steps) - (this.max * this.options.start / this.options.steps) - this.options.offset;
	},
	up:function(){
		if(this.step!=this.steps){
			this.step++;
			this.checkStep(1);
		}
		var position=this.toPosition(this.step);
		this.setKnobPos(position);
		this.fireEvent('onMove', position);
	},
	down:function(){
		if(this.step!=0){
			this.step--;
			this.checkStep(1);
		}
		var position=this.toPosition(this.step);
		this.setKnobPos(position);
		this.fireEvent('onMove', position);
	},
	setKnobPos:function(pos){
		var o={};
		o[this.p]=[this.moveKnob.getStyle(this.p),pos]
		new Fx.Morph(this.moveKnob).start(o);
		if(this.bkg){
			new Fx.Morph(this.bkg).start({width:[this.moveKnob.getStyle(this.p)+10,pos+10]});
		}
	}
});

Slider.implement(new Events);
Slider.implement(new Options);

function formatNumber(num,dec,thou,pnt){ 
  var x=Math.round(num * Math.pow(10,dec)); 
  var y=(""+Math.abs(x)).split(""); 
  var z=y.length - dec; 
  if (z<0)z--; 
  for(var i=z; i<0; i++)y.unshift("0"); 
  y.splice(z,0,pnt); 
  if(y[0]==pnt) y.unshift("0"); 
  while(z>3){ 
	z-=3; 
	y.splice(z,0,thou); 
  }  
  var r=y.join(""); 
  return r; 
}
