/*
 * Written by A.McBain
 *
 * License: Public Domain
 */

function Slider(window) {
	var $this = this;

	var borderColor = "#204a87";
	var innerColor = "#729fcf";
	var highlightColor = "#3465a4";

	var trackBorderColor = "#2e3436";
	var trackInnerColor = "#d3d7cf";
	var trackHighlightColor = "#eeeeec";

	var frame = new Frame();
	if(window) window.appendChild(frame);

	var canvas = new Canvas();
	var scanvas = new Canvas();
	scanvas.onMouseEnter = function() {
		hover = true;
		repaintSlider = true;
		$this.repaint();
	};
	scanvas.onMouseExit = function() {
		hover = false;
		repaintSlider = true;
		$this.repaint();
	};
	scanvas.onMouseDown = function() {
		down = true;
		repaintSlider = true;
		$this.repaint();
	};
	scanvas.onMouseUp = function() {
		down = false;
		repaintSlider = true;
		$this.repaint();
	};
	scanvas.onMouseDrag = function(e) {
		var event = e || system.event;
		$this.value = Math.min(max, Math.max(min, event.x * (max - min) / canvas.width + min));
	};
	this.__defineGetter__("width", function() { return canvas.width; });
	this.__defineSetter__("width", function(v) {
		if(!isNaN(Number(v))) {
			scanvas.width = canvas.width = Number(v);
			repaintBase = true;
			repaintSlider = true;
			this.repaint();
			return Number(v);
		}
		return o;
	});
	
	frame.appendChild(canvas);
	frame.appendChild(scanvas);
	var ctx = canvas.getContext("2d");
	var stx = scanvas.getContext("2d");

	this.__defineGetter__("hOffset", function() { return frame.hOffset; });
	this.__defineSetter__("hOffset", function(v) {
		if(!isNaN(Number(v))) {
			frame.hOffset = Number(v);
			return Number(v);
		}
		return o;
	});
	this.__defineGetter__("vOffset", function() { return frame.vOffset; });
	this.__defineSetter__("vOffset", function(v) {
		if(!isNaN(Number(v))) {
			frame.vOffset = Number(v);
			return Number(v);
		}
		return o;
	});

	var repaintBase = false;
	var repaintSlider = true;

	var value = 0;
	this.__defineGetter__("value", function() { return value; });
	this.__defineSetter__("value", function(v) {
		if(!isNaN(Number(v))) {
			value = Math.min(max, Math.max(min, Number(v)));
			if(snap) {
				var tickInt = (max - min) / (ticks + 1);
				var tickNum = (value - min) / tickInt;
				value = Math.ceil((Math.floor(tickNum) + Math.round(tickNum - Math.floor(tickNum))) * tickInt);
			}
			repaintSlider = true;
			this.repaint();
		}
		return v;
	});

	var min = 0;
	this.__defineGetter__("min", function() { return min; });
	this.__defineSetter__("min", function(v) {
		var number = Number(v);
		if(!isNaN(number) && number < max) {
			min = number;
			value = Math.max(min, value);
			this.value = value;
		}
		return v;
	});

	var max = 100;
	this.__defineGetter__("max", function() { return max; });
	this.__defineSetter__("max", function(v) {
		var number = Number(v);
		if(!isNaN(number) && number > min) {
			max = number;
			value = Math.min(max, value);
			this.value = value;
		}
		return v;
	});

	var ticks = 2;
	this.__defineGetter__("ticks", function() { return ticks; });
	this.__defineSetter__("ticks", function(v) {
		var number = Number(v);
		if(!isNaN(number) && number >= 0) {
			ticks = Math.max(number - 2, 0);
			repaintBase = true;
			if(snap) {
				this.value = value;
			} else {
				this.repaint();
			}
		}
		return v;
	});

	var snap = false;
	this.__defineGetter__("snap", function() { return snap; });
	this.__defineSetter__("snap", function(v) {
		if(v instanceof Boolean || typeof v === "boolean") {
			snap = v;
			this.value = value;
		}
		return v;
	});

	var track = 10;
	var fifth = track / 5;
	var fourth = track / 4;

	scanvas.height = canvas.height = 2 * track;

	var down = false;
	var hover = false;

	this.repaint = function() {
		var width = canvas.width - 2 * fourth;
		var height = canvas.height;
		var half = height / 2;

		if(repaintBase) {
			ctx.clearRect(0, 0, width + 2 * fourth, height);

			ctx.save();
			ctx.strokeStyle = trackBorderColor;
			ctx.translate(fourth, half - Math.floor(track / 2));
			ctx.beginPath();
			ctx.rect(0, 0, width, track);
			ctx.closePath();
			ctx.clip();
			ctx.fillStyle = trackInnerColor;
			ctx.fillRect(0, 0, width, track);
			for(var i = 0; i < 3; i++)
				ctx.strokeRect(0, 0, width, track);
			ctx.translate(-fourth, -(half - Math.floor(track / 2)));
			ctx.restore();

			ctx.save();
			var ticksPer = width / (ticks + 1);
			ctx.translate(ticksPer + fourth, half - Math.floor(track / 2));
			ctx.strokeStyle = trackBorderColor;
			for(var i = 0; i < ticks; i++) {
				var pos = Math.round(ticksPer * i);
				ctx.save();
				ctx.rect(pos, fifth, 1, track - 2 * fifth);
				ctx.clip();
				ctx.beginPath();
				ctx.moveTo(pos, fifth);
				ctx.lineTo(pos, track - fifth);
				ctx.closePath();
				for(var j = 0; j < 3; j++)
					ctx.stroke();
				ctx.restore();
			}
			ctx.restore();

			repaintBase = false;
		}

		var _value = Math.floor(value * width / (max - min));
		_value -= Math.floor(min * width / (max - min));
		if(repaintSlider) {
			stx.clearRect(0, 0, width + 2 * fourth, height);

			stx.save();
			stx.translate(_value, half - track);
			stx.beginPath();
			stx.rect(0, 0, 2 * fourth, 2 * track);
			stx.closePath();
			stx.clip();
			stx.fillStyle = (down || hover)? innerColor : highlightColor;
			stx.globalAlpha = .7;
			stx.fill();
			stx.globalAlpha = 1;
			stx.strokeStyle = borderColor;
			for(var i = 0; i < 3; i++)
				stx.stroke();
			stx.beginPath();
			stx.rect(fourth, 0, 1, 2 * track);
			stx.closePath();
			stx.clip();
			stx.beginPath();
			stx.moveTo(fourth, fifth);
			stx.lineTo(fourth, track - fourth);
			stx.moveTo(fourth, track + fourth);
			stx.lineTo(fourth, height - fifth);
			stx.closePath();
			for(var i = 0; i < 3; i++)
				stx.stroke();
			stx.restore();

			repaintSlider = false;
		}
	};
}
