/*
Copyright (c) 2007 John Dyer (http://johndyer.name)
MIT style license
*/

if (!window.Refresh) Refresh = {};
if (!Refresh.Web) Refresh.Web = {};

Refresh.Web.SlidersList = [];

Refresh.Web.Slider = new Class({
	_bar: null,
	_arrow: null,

    Implements: [Options],

    options: {
        xMinValue: 0,
        xMaxValue: 100,
        yMinValue: 0,
        yMaxValue: 100,
        arrowImage: 'refresh_web/colorpicker/images/rangearrows.gif'
    },

	initialize: function(id, options) {
	
		this.id = id;
        this.setOptions(options);

		this.xValue = 0;
		this.yValue = 0;

		// hook up controls
		this._bar = $(this.id);

		// build controls
		this._arrow = new Element('img');
		this._arrow.border = 0;
		this._arrow.src = this.options.arrowImage;
		this._arrow.margin = 0;
		this._arrow.padding = 0;
		this._arrow.style.position = 'absolute';
		this._arrow.style.top = '0px';
		this._arrow.style.left = '0px';
        this._arrow.injectInside(document.body);
        this.Arrow = this._arrow;

		// attach 'this' to html objects
		var slider = this;
		
		this.setPositioningVariables();
		
		this._event_docMouseMove = this._docMouseMove.bindWithEvent(this);
		this._event_docMouseUp = this._docMouseUp.bindWithEvent(this);

		this._bar.addEvent('mousedown', this._bar_mouseDown.bindWithEvent(this));
		this._arrow.addEvent('mousedown', this._arrow_mouseDown.bindWithEvent(this));

		// set initial position
		this.setArrowPositionFromValues();

		// fire events
		if(this.onValuesChanged)
			this.onValuesChanged(this);

		// final setup
		Refresh.Web.SlidersList.push(this);
	},
	
	
	setPositioningVariables: function() {
		// calculate sizes and ranges
		// BAR

		this._barWidth = this._bar.getWidth();
		this._barHeight = this._bar.getHeight();
		
		var pos = this._bar.getPosition(); // FIXME: May not be the right kind of position...
		this._barTop = pos.y;
		this._barLeft = pos.x;
		
		this._barBottom = this._barTop + this._barHeight;
		this._barRight = this._barLeft + this._barWidth;

		// ARROW
		this._arrow = $(this._arrow);
		this._arrowWidth = this._arrow.getWidth();
		this._arrowHeight = this._arrow.getHeight();

		// MIN & MAX
		this.MinX = this._barLeft;
		this.MinY = this._barTop;

		this.MaxX = this._barRight;
		this.MinY = this._barBottom;
	},
	
	setArrowPositionFromValues: function(e) {
		this.setPositioningVariables();
		
		// sets the arrow position from XValue and YValue properties

		var arrowOffsetX = 0;
		var arrowOffsetY = 0;
		
		// X Value/Position
		if (this.options.xMinValue != this.options.xMaxValue) {

			if (this.xValue == this.options.xMinValue) {
				arrowOffsetX = 0;
			} else if (this.xValue == this.options.xMaxValue) {
				arrowOffsetX = this._barWidth-1;
			} else {

				var xMax = this.options.xMaxValue;
				if (this.options.xMinValue < 1)  {
					xMax = xMax + Math.abs(this.options.xMinValue) + 1;
				}
				var xValue = this.xValue;

				if (this.xValue < 1) xValue = xValue + 1;

				arrowOffsetX = xValue / xMax * this._barWidth;

				if (parseInt(arrowOffsetX) == (xMax-1)) 
					arrowOffsetX=xMax;
				else 
					arrowOffsetX=parseInt(arrowOffsetX);

				// shift back to normal values
				if (this.options.xMinValue < 1)  {
					arrowOffsetX = arrowOffsetX - Math.abs(this.options.xMinValue) - 1;
				}
			}
		}
		
		// X Value/Position
		if (this.options.yMinValue != this.options.yMaxValue) {	
			
			if (this.yValue == this.options.yMinValue) {
				arrowOffsetY = 0;
			} else if (this.yValue == this.options.yMaxValue) {
				arrowOffsetY = this._barHeight-1;
			} else {
			
				var yMax = this.options.yMaxValue;
				if (this.options.yMinValue < 1)  {
					yMax = yMax + Math.abs(this.options.yMinValue) + 1;
				}

				var yValue = this.yValue;

				if (this.yValue < 1) yValue = yValue + 1;

				var arrowOffsetY = yValue / yMax * this._barHeight;

				if (parseInt(arrowOffsetY) == (yMax-1)) 
					arrowOffsetY=yMax;
				else
					arrowOffsetY=parseInt(arrowOffsetY);

				if (this.options.yMinValue < 1)  {
					arrowOffsetY = arrowOffsetY - Math.abs(this.options.yMinValue) - 1;
				}
			}
		}

		this._setArrowPosition(arrowOffsetX, arrowOffsetY);

	},
	_setArrowPosition: function(offsetX, offsetY) {
		
		
		// validate
		if (offsetX < 0) offsetX = 0
		if (offsetX > this._barWidth) offsetX = this._barWidth;
		if (offsetY < 0) offsetY = 0
		if (offsetY > this._barHeight) offsetY = this._barHeight;	

		var posX = this._barLeft + offsetX;
		var posY = this._barTop + offsetY;

		// check if the arrow is bigger than the bar area
		if (this._arrowWidth > this._barWidth) {
			posX = posX - (this._arrowWidth/2 - this._barWidth/2);
		} else {
			posX = posX - parseInt(this._arrowWidth/2);
		}
		if (this._arrowHeight > this._barHeight) {
			posY = posY - (this._arrowHeight/2 - this._barHeight/2);
		} else {
			posY = posY - parseInt(this._arrowHeight/2);
		}
		this._arrow.style.left = posX + 'px';
		this._arrow.style.top = posY + 'px';	
	},
	_bar_mouseDown: function(e) {
		this._mouseDown(e);
	},
	
	_arrow_mouseDown: function(e) {
		this._mouseDown(e);
	},
	
	_mouseDown: function(e) {
		Refresh.Web.ActiveSlider = this;
		
		this.setValuesFromMousePosition(e);
		
		document.addEvent('mousemove', this._event_docMouseMove);
		document.addEvent('mouseup', this._event_docMouseUp);		

		e.stop();
	},
	
	_docMouseMove: function(e) {
		this.setValuesFromMousePosition(e);
		
		e.stop();
	},
	
	_docMouseUp: function(e) {
		document.removeEvent('mouseup', this._event_docMouseUp);
		document.removeEvent('mousemove', this._event_docMouseMove);
		e.stop();
	},	
	
	setValuesFromMousePosition: function(e) {
		//this.setPositioningVariables();
		
		var mouse = e.page;
		
		var relativeX = 0;
		var relativeY = 0;

		// mouse relative to object's top left
		if (mouse.x < this._barLeft)
			relativeX = 0;
		else if (mouse.x > this._barRight)
			relativeX = this._barWidth;
		else
			relativeX = mouse.x - this._barLeft + 1;

		if (mouse.y < this._barTop)
			relativeY = 0;
		else if (mouse.y > this._barBottom)
			relativeY = this._barHeight;
		else
			relativeY = mouse.y - this._barTop + 1;
			

		var newXValue = parseInt(relativeX / this._barWidth * this.options.xMaxValue);
		var newYValue = parseInt(relativeY / this._barHeight * this.options.yMaxValue);
		
		// set values
		this.xValue = newXValue;
		this.yValue = newYValue;	

		// position arrow
		if (this.options.xMaxValue == this.options.xMinValue)
			relativeX = 0;
		if (this.options.yMaxValue == this.options.yMinValue)
			relativeY = 0;		
		this._setArrowPosition(relativeX, relativeY);

		// fire events
		if(this.onValuesChanged)
			this.onValuesChanged(this);
	}	

});
