var DualSlider = new Class
({
 options:
 {
 onChange: Class.empty,
 onComplete: Class.empty,
 steps: 100,
 step: 1,
 stepper: 1,
 min: 1
 },

 initialize:function(el, knobs, options)
 {
 this.element = el;
 this.knobs = knobs;
 this.setOptions(options);
 this.options.min = this.options.min.toInt();

 this.limits = [];
 this.min = [];
 this.max = [];
 this.half = [];
 this.drag = [];
 this.step = [-1, -1];
 this.prev = [-1, -1];
 this.ends = [-1, -1];
 this.steps = [];
 this.offsets = [];

 this.element.setStyle('position', 'relative');

 this.single();
 if (this.knobs.length == 2) this.dual();

 this.element.addEvent('mousedown', this.clicked.bindWithEvent(this));
 },

 single: function()
 {
 this.setDrag(0);
 this.drag[0].value.now['x'] = 0;
 },

 dual: function()
 {
 this.setDrag(1);

 this.drag[1].value.now['x'] = this.limits[1]['x'];
 this.set(1, this.options.steps);

 this.max[0] -= this.half[1] * 2;
 this.min[1] += this.half[0] * 2;

 this.limit(0);
 this.limit(1);
 },

 setDrag: function(i)
 {
 this.knobs[i].setStyles
 ({
 'position': 'absolute',
 'top': '0px',
 'left': '0px'
 });

 this.min[i] = 0;
 this.max[i] = this.element['offsetWidth'] - this.knobs[i]['offsetWidth'];
 this.half[i] = this.knobs[i]['offsetWidth'] / 2;
 this.limits[i] = {};
 this.limits[i]['x'] = [this.min[i], this.max[i]];
 this.steps[i] = this.options.steps;
 this.offsets[i] = 0;

 this.drag[i] = new Drag.Base
 (
 this.knobs[i],
 {
 limit: this.limits[i],
 modifiers: {'x': 'left', 'y': false},
 snap: 0,
 onStart: this.dragged.pass(i, this),
 onDrag: this.dragged.pass(i, this),
 onComplete: this.end.pass(i, this)
 }
 );
 },

 set: function(i, step)
 {
 if (i == 1 && step < this.options.min) step = this.options.steps;
 this.step[i] = new Number(step).limit(this.offsets[i], this.steps[i].toInt() + this.offsets[i].toInt());
 this.toPos(i);
 return this;
 },

 clicked: function(event)
 {
 var pos = event.page['x'];
 var i = 0;

 this.knobs.each
 (
 function(el, j)
 {
 var diff = Math.abs(event.page['x'] - el.getLeft());
 if (diff >= pos) return;
 pos = diff;
 i = j;
 }
 );

 pos = event.page['x'] - this.element.getLeft() - this.half[i];
 pos = pos.limit(this.min[i], this.max[i]);
 if (!$defined(pos)) pos = 0;
 this.set(i, this.toStep(i, pos));

 this.end(i);
 },

 toStep: function(i, pos)
 {
 if (pos == 0) return 0;
 var step = (pos - this.min[i]) / (this.max[i] - this.min[i]);
 if (this.offsets[i] > 0) step = Math.floor(step * this.steps[i]);
 else step = Math.floor(step * (this.steps[i] - this.options.min)) + this.options.min;
 step += this.offsets[i];

 if (((step % this.options.stepper) * 2) > this.options.stepper) return step - (step % this.options.stepper) + this.options.stepper.toInt();
 else return step - (step % this.options.stepper);
 },

 toPos: function(i)
 {
 var pos = this.step[i] - this.offsets[i];

 if (this.step[i] <= this.options.min) pos = 0;
 else if (this.offsets[i] > 0) pos = pos / this.steps[i];
 else pos = (pos - this.options.min) / (this.steps[i] - this.options.min);

 pos = Math.round(pos * (this.max[i] - this.min[i])) + this.min[i];

 this.knobs[i].setStyle('left', pos);
 },

 checkStep: function(i)
 {
 if (this.prev[i] != this.step[i])
 {
 this.prev[i] = this.step[i];
 this.fireEvent('onChange', [i, this.step[i]]);
 }
 },

 dragged: function(i)
 {
 this.step[i] = this.toStep(i, this.drag[i].value.now['x']);
 this.checkStep(i);
 },

 limit: function(i)
 {
 var pos = this.knobs[i].getLeft() - this.element.getLeft() - this.half[i];

 this.limits.each
 (
 function(limit, j)
 {
 if (j == i) return;

 if (j > i)
 {
 this.min[j] = pos + this.half[i] + this.half[j] * 2;
 this.drag[j].options.limit['x'][0] = this.min[j];
 this.steps[j] = this.options.steps - this.step[i];
 this.offsets[j] = this.step[i];
 }
 else
 {
 this.max[j] = pos - this.half[i];
 this.drag[j].options.limit['x'][1] = this.max[j];
 this.steps[j] = this.step[i];
 }

 }.bind(this)
 );
 },

 end: function(i)
 {
 this.checkStep(i);

 if (this.ends[i] != this.step[i])
 {
 this.ends[i] = this.step[i];
 this.fireEvent('onComplete', [i, this.step[i]]);
 }
 if (this.knobs.length > 1) this.limit(i);
 }
});

DualSlider.implement(new Events, new Options);