/*
 *	Scroller
 *
 *	@version	0.1.2 - 2008.04.18
 *	@package	jsx.Scroller
 */

jsx.Scroller = JSX.Class.create('jsx.Scroller');
jsx.Scroller.prototype =
{
	// target div
	__target: null,
	
	// scroller div
	__scroller: null,
	
	// array met ScrollerContent objecten
	__contents: [],
	
	// array met berichten (zonder seperator)
	__messages: [],
	
	// het totale bericht dat moet worden gescrollt
	__message: '',
	
	__seperator: '&nbsp;&nbsp;-&nbsp;&nbsp;',
	
	__direction: 'rtl',
	
	__speed: 2,
	
	__position: 0,
	
	__posLeft: 0,
	
	__posRight: 0,
	
	__timer: null,
	
	__created: false,
	
	__running: false,
	
	/**
	 *	Het onStart event wordt uitgevoerd zodra het Scroller object wordt gestart door
	 *	middel van de start() function.
	 *
	 *	@event
	 */
	onStart: null,
	
	/**
	 *	Het onStop event wordt uitgevoerd zodra het Scroller object wordt gestopt door
	 *	middel van de stop() function.
	 *
	 *	@event
	 */
	onStop: null,
	
	/**
	 *	Het onScroll event wordt uitgevoerd wanneer de positie van de ScrollerContent
	 *	objecten worden gewijzigd, dus wanneer er een scroll actie wordt uitgevoerd.
	 *
	 *	@event
	 */
	onScroll: null,
	
	/*************************************************************************************
	 *	Constructor
	 *
	 *	@access public
	 *	@param object	target		Het element waarin de scroller wordt gemaakt.
	 *	@param string	direction	De richting waarin de scroll content beweegt.
	 *	@param int		width		De breedte van de scroller.
	 *	@param int		height		De hoogte van de scroller.
	 */
	__construct: function(target, direction, width, height)
	{
		JSX.Event.makeBroadcaster(this);
		
		var $this = this;
		var $target = $(target);
		
		var $width = (!JSX.isNumber(width)) ? $target.offsetWidth : parseInt(width);
		var $height = (!JSX.isNumber(width)) ? $target.offsetHeight : parseInt(height);
		
		this.__target = $target;
		this.__position = $width;
		this.__posRight = $width;
		
		this.__timer = new jsx.Timer(300);
		this.__timer.onTime = function($c)
		{
			$this.scroll();
		};
		
		this.setDirection(direction);
		
		// div waar de content in scrollt
		this.__scroller = document.createElement('div');
		this.__scroller.setAttribute('class', 'scroller');
		
		this.__scroller.style.position = 'relative';
		this.__scroller.style.overflow = 'hidden';
		this.__scroller.style.width = $width + 'px';
		this.__scroller.style.height = $height + 'px';
		
		// content toevoegen aan scroller
		this.__createContent();
		
		// scroller toevoegen aan target
		this.__target.insertBefore(this.__scroller, this.__target.firstChild);
	},
	
	__createContent: function()
	{
		var $content = new jsx.Scroller.Content(this.__posLeft, this.__posRight);
			$content.setPosition(this.__position);
		
		this.__contents.push($content);
		this.__scroller.appendChild($content.getContainer());
	},
	
	__createContents: function()
	{
		var $width = this.__contents[0].getWidth();
		var $count = Math.ceil(this.__posRight / $width);
		
		if(this.__direction == 'ltr') this.__position = -$width;
		
		for(var $i=0; $i<$count; $i++) this.__createContent();
		this.__created = true;
	},
	
	// update de content in alle ScrollerContent objecten
	__updateContent: function()
	{
		var $iL = this.__contents.length;
		for(var $i=0; $i<$iL; $i++)
		{
			this.__contents[$i].setContent(this.__message);
		}
	},
	
	// update de positie van alle ScrollerContent objecten
	__updatePosition: function()
	{
		var $position = this.__position;
		var $contents = this.__contents;
		var $reload = false;
		
		var $iL = this.__contents.length;
		for(var $i=0; $i<$iL; $i++)
		{
			var $content = this.__contents[$i];
			var $width = $content.getWidth();
			
			$content.setPosition($position);
			
			if(this.__direction == 'ltr')
			{
				$position -= $width;
				
				// content is voorbij links
				// aan het einde toevoegen
				if($position > (this.__posRight + $width))
				{
					$contents.shift();
					$contents.push($content);
					
					this.__position = -$width;
					$reload = true;
				}
			}
			else
			{
				$position += $width;
				
				// content is voorbij links
				// aan het einde toevoegen
				if($position < this.__posLeft)
				{
					$contents.shift();
					$contents.push($content);
					
					this.__position = $position;
					$reload = true;
				}
			}
		}
		this.__contents = $contents;
		if($reload) this.__updatePosition();
	},
	
	setSeperator: function(seperator)
	{
		if(JSX.isString(seperator)) this.__seperator = seperator;
	},
	
	setDirection: function(direction)
	{
		var $direction;
		if(JSX.isString(direction)) $direction = direction.toLowerCase();
		if($direction != 'ltr') $direction = 'rtl';
		
		this.__direction = $direction;
		
		if(!this.__created)
		{
			this.__position = ($direction == 'ltr') ? 0 : this.__posRight;
		}
	},
	
	setSpeed: function(speed, interval)
	{
		if(JSX.isInt(speed))	this.__speed = speed;
		if(JSX.isInt(interval))	this.__timer.setDelay(interval);
	},
	
	addMessage: function(message)
	{
		this.__messages.push(message);		
		this.__message += message + this.__seperator;
	},
	
	remember: function(cookieName)
	{
		var $data = {};
		alert('save koekje');
	},
	
	scroll: function()
	{
		if(this.__direction == 'ltr')
		{
			this.__position += this.__speed;
		}
		else
		{
			this.__position -= this.__speed;
		}
		
		this.__updatePosition();
		this.dispatchEvent('onScroll');
	},
	
	start: function()
	{
		if(!this.__running)
		{
			if(!this.__created)
			{
				this.__updateContent();
				this.__createContents();
				this.__updateContent();
			}
			
			this.__running = true;
			this.__timer.start();
			this.dispatchEvent('onStart');
		}
	},
	
	stop: function()
	{
		if(this.__running)
		{
			this.__running = false;
			this.__timer.stop();
			this.dispatchEvent('onStop');
		}
	}
};

/*****************************************************************************************
 *	ScrollerContent
 */

jsx.Scroller.Content = JSX.Class.create('jsx.Scroller.Content');
jsx.Scroller.Content.prototype =
{
	/**
	 *	...
	 *
	 *	@access private
	 *	@var int
	 */
	__container: null,
	
	__visible: false,
	
	__position: null,
	
	__posLeft: 0,
	
	__posRight: 0,
	
	/**
	 *	Het onShow event wordt uitgevoerd zodra het object wordt getoond in de Scroller.
	 *
	 *	@event
	 */
	onShow: null,
	
	/**
	 *	Het onHide event wordt uitgevoerd zodra het object uit het scroll gebied vandaan
	 *	scrollt.
	 *
	 *	@event
	 */
	onHide: null,
	
	/*************************************************************************************
	 *	Constructor
	 *
	 *	@access private
	 *	@param int	posLeft
	 *	@param int	posRight
	 */
	__construct: function(posLeft, posRight)
	{
		JSX.Event.makeBroadcaster(this);
		
		this.__posLeft = posLeft;
		this.__posRight = posRight;
		
		this.__container = document.createElement('div');
		this.__container.style.position = 'absolute';
		this.__container.style.whiteSpace = 'nowrap';
	},
	
	setContent: function(content)
	{
		if(this.isVisible())
		{
			var $this = this;
			var $events =
			{
				onShow: function()
				{
					$this.__container.innerHTML = content;
					$this.removeEventListener(this);
				}
			};
			this.addEventListener($events);
		}
		else
		{
			this.__container.innerHTML = content;
		}
	},
	
	setPosition: function(position)
	{
		this.__position = position;
		this.__container.style.left = position +'px';
		
		var $visible = this.isVisible();
		if($visible !== this.__visible)
		{
			if($visible)	this.dispatchEvent('onShow');
			else			this.dispatchEvent('onHide');
			
			this.__visible = $visible;
		}
	},
	
	getContainer: function()
	{
		return this.__container;
	},
	
	getWidth: function()
	{
		return this.__container.offsetWidth;
	},
	
	isVisible: function()
	{
		var $return = false;
		if(!isNaN(this.__position))
		{
			$return = (this.__position < this.__posRight && (this.__position + this.getWidth()) > this.__posLeft);
		}
		return $return;
	},
	
	hide: function()
	{
		this.__container.style.display = 'none';
	},
	
	show: function()
	{
		this.__container.style.display = '';
	}
};
