
var Slider = new Class({

	Implements: [Options, Events],
	
	options: {
		onChange: Class.empty,
		onComplete: Class.empty,
		onTick: function(pos){
			this.moveKnob.setStyle(this.coordinate, pos);
		},
		start: 0,
		end: 0,
		offset: 0,
		mode: 'horizontal',
		snap: false,
		steps:null
	},
    initialize: function(el, knob,background, options, maxknob) {
		this.setOptions(options);
		this.element = $(el);
		this.knob = $(knob);
		this.background = $(background);
		var mod, offset;
		switch(this.options.mode){
			case 'horizontal':
				this.axis = 'x';
				this.coordinate = 'left';
				mod = {'x': 'left', 'y': false};
				offset = 'offsetWidth';
				break;
			case 'vertical':
				this.axis = 'y';
				this.coordinate = 'top';
				mod = {'x': false, 'y': 'top'};
				offset = 'offsetHeight';
		}
		this.max = this.element[offset];
		this.min = 0;
		this.range = this.max - this.min;
		//this.getPos = this.element['get' + this.coordinate.capitalize()].bind(this.element);
		this.step = this.options.start;
		this.steps = this.options.steps || this.range;
		this.stepWidth = Math.round(this.range/this.steps);
		this.stepValue = Math.abs(this.options.end-this.options.start)/this.options.steps;
		this.previousStep = this.step = 0;
		var lim = {};
		lim[this.axis] = [0, this.max-this.stepWidth];
		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 = this.stepWidth;
		
		if(maxknob != null) {
			this.maxknob = $(maxknob)
			var limm = {};
			limm[this.axis] = [this.stepWidth, this.max];
			this.previousMaxStep = this.maxstep = this.options.end;
			this.maxdrag = new Drag(this.maxknob, {
				limit: limm,
				modifiers: mod,
				snap: 0, 
				onStart: function(){
					this.draggedKnob(1);
				}.bind(this),
				onDrag: function(){
					this.draggedKnob(1);
				}.bind(this),
				onComplete: function(){
					this.draggedKnob(1);
					//this.end();
				}.bind(this)
			});
			//if(this.options.snap) this.maxdrag.options.grid = this.stepWidth;
		}
		this.display();
		if (this.options.initialize) this.options.initialize.call(this);
    },
	
	setMin: function(stepMin) {
		this.step = stepMin.limit(this.options.start, this.options.end);
		this.checkStep();
		this.end();
		this.moveKnob = this.knob;
		this.display();
		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;
		this.display();
		this.fireEvent('onTick', this.toPosition(this.maxstep));
		return this; 
	},
	
	display: function() {
		this.knob.setStyle(this.coordinate, this.toPosition(this.step));
		if(this.maxknob) {
			this.maxknob.setStyle(this.coordinate, this.toPosition(this.maxstep));
			this.background.style.clip = "rect(0px "+(parseInt(this.toPosition(this.maxstep)))+ "px "+this.background.getHeight()+"px "+(parseInt(this.toPosition(this.step)))+"px)";
		} else {
			this.background.style.clip = "rect(0px "+(parseInt(this.toPosition(this.step)))+ "px "+this.background.getHeight()+"px 0px)";
		}
	},
	
	setValue: function(stepMin, stepMax){
		this.step = stepMin.limit(this.options.start, this.options.end);
		this.maxstep = stepMax.limit(this.options.start, this.options.end);
		this.display();
	},
	
	draggedKnob: function(mx) {
		if(mx==null) {
			this.step = this.toStep(this.drag.value.now[this.axis]);
			this.checkStep();
		}else {
			this.maxstep = this.toStep(this.maxdrag.value.now[this.axis]);
			this.checkStep(1);
		}
	},
	
	checkStep: function(mx) {
		var lim = {}; var mi,mx;
		var limm = {};
		if(this.maxknob!=null) {
			lim[this.axis] = [0, this.toPosition(this.maxstep)-this.stepWidth];
			this.drag.options.limit = lim;
			limm[this.axis] = [this.toPosition(this.step)+this.stepWidth, this.max];
			this.maxdrag.options.limit = limm;
			this.fireEvent('onChange', { minpos: this.step, maxpos: this.maxstep });
		} else {  
			this.fireEvent('onChange', this.step);
		}
		if(mx==null) {
			if (this.previousStep != this.step) {
				this.previousStep = this.step;
			}
		} else {
			if (this.previousMaxStep != this.maxstep){
				this.previousMaxStep = this.maxstep;
			}
		}
		this.display();
	},
	
	end: function(){
		if(this.maxknob != null) {
			this.fireEvent('onComplete', { minpos: this.step + '', maxpos: this.maxstep + '' });
		} else {
			this.fireEvent('onComplete', this.step + '');
		}
	},
	
	toStep: function(position) {
		var step = this.options.start + Math.round(position*(this.options.end - this.options.start)/this.max);
		step = Math.max(this.options.start, Math.min(step, this.options.end));
		step = (this.options.snap) ?  this.options.start+Math.round((step-this.options.start)/this.stepValue)*this.stepValue : step;
		return step;
	},

	toPosition: function(step) {
		return Math.round(step*this.max/(this.options.end-this.options.start));
	}

});
