var marqueeId = '';

function wmxMarquee()
{
	//Private variables
	var _marquee = null;
	var _marqueeSlideContainer = null;
	var _initialized = false;
	var _transitionType = 
		{ 
			Fade: 				1, 
			SlideDown: 	2, 
			SlideUp: 			3, 
			SlideLeft: 		4, 
			SlideRight: 	5 
		};
	var _transition = 
		{ 
			time: 	1, 
			scale: 	0.25, 
			type: 	_transitionType.Fade, 
			mode: 	'relative',	
			func: 	function(){} 
		};
	var _marqueeSlideStaging = null;
	var _delay = 
		{ 
			executer: null, 
			counter: 	0, 
			paused: 	false 
		};
	var _currentIndex = 0;
	
	//Public properties
	this.marqueeSlides = new Array(); // marqueeSlides must be an Array containing only elements of type wmxMarqueeSlide
	this.delayTime = 8; // 1 (0.5s) --- 20 (10s) 
	this.delayTimeScale = 0.5;
	this.height = null;
	this.name = '';
	this.transitionTime = 1; // 1 (0.25s) --- 8 (2s)
	this.width = null;
	this.transitionTypeId = 1; // 1 - Fade, 2 - T->C, 3 - B->C, 4 - R->C, 5 - L->C

	this.initialize = function()
	{
		this.InitializeMarquee();
		
		_marqueeSlideContainer = $("MarqueeSlideContainer" + this.name);

		this.marqueeSlides[0].element.setStyle({top: (this.height - this.marqueeSlides[0].dimensions.height)/2 + 'px'});
		this.TransferToContainer(this.marqueeSlides[0].element);
		this.marqueeSlides[0].element.show();
		
		this.initializeTransition();
		
		this.InitializeEvents();
		
		_initialized = true;
	};
	
	this.InitializeMarquee = function()
	{
		if(!_marquee) _marquee = $("Marquee" + this.name);	
		
		if(!cmxbrowser.ie)
		{
			this.marqueeSlides.each(function(s)
			{
				if(s.hasImage)
				{
					
					if(!s.imagesPreloaded)
					{
						PreloadImages(this.InitializeMarquee.bind(this), s.element.select('img').pluck('src'));
						s.imagesPreloaded = true;
					}
					else
					{
						s.RecalculateDimensions();
					}
				}
			}, this);
		}
		
		var maxHeight = this.marqueeSlides.max(function(slide) { return slide.dimensions.height; });
		this.height = (maxHeight > this.height) ? maxHeight : this.height;
		this.width = _marquee.getWidth() || this.width;
		_marquee.setStyle({ height: this.height + 'px'});
		
		this.initializeTransition();
		this.marqueeSlides[0].element.setStyle({top: (this.height - this.marqueeSlides[0].dimensions.height)/2 + 'px'});
	
		if(marqueeId == '') marqueeId = _marquee.id;	
	};

	this.InitializeEvents = function()
	{
		if(Prototype.Browser.IE)
		{
			_marqueeSlideContainer.observe('mouseenter', function(e){this.pause();}.bind(this));
			_marqueeSlideContainer.observe('mouseleave', function(e){this.start();}.bind(this));
		}
		else
		{
			_marqueeSlideContainer.observe('mouseover', function(e){this.pause();}.bind(this));
			_marqueeSlideContainer.observe('mouseout', function(e){this.start();}.bind(this));
		}
	};
	
	this.normalizeMarqueeSlideDimensions = function()
	{
		this.marqueeSlides.each(function(slide)
			{
				slide.element.setStyle({ height: this.height + 'px' });
				slide.dimensions.height = this.height;
			}, this);
	};

	var _containerPosition = { Bottom: 0, Top: 1 };
	
	this.TransferToContainer = function(element, position)
	{
		if(position == _containerPosition.Top)
		{
			_marqueeSlideContainer.insert({top: element});
		}
		else
		{
			_marqueeSlideContainer.insert({bottom: element});
		}
	};

	this.initializeTransition = function()
	{
		_delay.counter = this.delayTime;
		_transition.time = this.transitionTime;
		
		switch (this.transitionTypeId)
		{
			case 2:	// Top to Center
				this.marqueeSlides.each(function(slide)
					{
						slide.startPos.y = -slide.dimensions.height;
						slide.offset.y = (this.height - slide.dimensions.height)/2;
					}, this);
				_transition.mode = 'absolute';
				_transition.type = _transitionType.SlideDown;
				_transition.func = this.moveToCenter.bind(this);
				break;
			case 3:	// Bottom to Center
				this.marqueeSlides.each(function(slide)
					{
						slide.startPos.y = this.height;
						slide.offset.y = (this.height - slide.dimensions.height)/2;
					}, this);
				_transition.mode = 'absolute';
				_transition.type = _transitionType.SlideUp;
				_transition.func = this.moveToCenter.bind(this);
				break;
			case 4:	// Right to Center
				this.marqueeSlides.each(function(slide)
					{
						slide.startPos.y = (this.height - slide.dimensions.height)/2;
						slide.startPos.x = this.width;
						slide.offset.x = -this.width;
					}, this);
				_transition.type = _transitionType.SlideLeft;
				_transition.func = this.moveToCenter.bind(this);
				break;
			case 5:	// Left to Center
				this.marqueeSlides.each(function(slide)
					{
						slide.startPos.y = (this.height - slide.dimensions.height)/2;
						slide.startPos.x = -this.width;
						slide.offset.x = this.width;
					}, this);
				_transition.type = _transitionType.SlideRight;
				_transition.func = this.moveToCenter.bind(this);
				break;
			case 1:	// Fade
			default:
				this.marqueeSlides.each(function(slide)
					{
						slide.startPos.y = (this.height - slide.dimensions.height)/2;
						slide.ResetPosition();
					}, this);
				_transition.type = _transitionType.Fade;
				_transition.func = this.Fade.bind(this);
				break;
		}
	};
	
	this.Fade = function(previousMarqueeSlide, marqueeSlide)
	{
		Effect.Fade(previousMarqueeSlide.id,
								{
									duration: this.getSeconds(_transition.time, _transition.scale) / 2,
									queue: { position: 'end', scope: this.name },
									afterFinish: function(effect) 
										{
											this.ReplaceContentWith(marqueeSlide.element.hide());
											Effect.Appear(marqueeSlide.id,
																			{
																				duration: this.getSeconds(_transition.time, _transition.scale) / 2,
																				queue: { position: 'end', scope: this.name }
																			})
										}.bind(this)
								});
};

	
	this.ReplaceContentWith = function(element)
	{
		_marqueeSlideContainer.childElements().invoke('remove');
		this.TransferToContainer(element);
	};
	
	this.moveToCenter = function(previousMarqueeSlide, marqueeSlide)
	{
		marqueeSlide.ResetPosition();
		if(this.marqueeSlides.size() > 1)
		{
			if(_transition.type == _transitionType.SlideDown)
			{
				this.TransferToContainer(marqueeSlide.element, _containerPosition.Top);
			}
			else
			{
				this.TransferToContainer(marqueeSlide.element);
			}
		
			new Effect.Move(marqueeSlide.id, 
				{ 	x: marqueeSlide.offset.x, y: marqueeSlide.offset.y, mode: _transition.mode,
					duration: this.getSeconds(_transition.time, _transition.scale),
					queue: {	position: 'end', scope: this.name },
					beforeStart: function(effect)
						{
							this.remove();
						}.bind(previousMarqueeSlide.element)
				} );
		}
		else
		{
			new Effect.Move(marqueeSlide.id, 
				{ 	x: marqueeSlide.offset.x, y: marqueeSlide.offset.y, mode: _transition.mode,
					duration: this.getSeconds(_transition.time, _transition.scale),
					queue: {	position: 'end', scope: this.name }
				} );		
		}

	};
	
	this.getSeconds = function(time, scale)
	{
		return (time * scale);
	};
	
	this.CurrentSlide = function()
	{
		return this.marqueeSlides[_currentIndex];
	}
	
	this.NextSlide = function()
	{
		_currentIndex++;
		_currentIndex = (_currentIndex < this.marqueeSlides.size()) ? _currentIndex : 0;
		return this.marqueeSlides[_currentIndex];
	};
	
	this.PreviousSlide = function()
	{
		var previousIndex = (_currentIndex - 1 >= 0) ? _currentIndex - 1 : this.marqueeSlides.size() - 1;
		return this.marqueeSlides[previousIndex];
	};

	this.start = function()
	{
	  if (cmxbrowser.supportsDOM)
		{
			if(_delay.executer == null)
			{
				if(!_initialized)
				{
					Event.observe(window, 'load', function(e)
						{
							_delay.executer = new PeriodicalExecuter(this.delayStep.bind(this), this.delayTimeScale);
						}.bind(this));
				}
				else
				{
					_delay.executer = new PeriodicalExecuter(this.delayStep.bind(this), this.delayTimeScale);
				}
			}
				
			if (!_initialized)
			{
				this.initialize();
			}	
		}
	};

	this.delayStep = function()
	{
		if (Effect.Queues.get(this.name).size() == 0)
		{
			_delay.counter--;
		}
		
		if(_delay.counter < 0)
		{
			_delay.counter = this.delayTime; 
			_transition.func(this.CurrentSlide(), this.NextSlide());
		}
	}

	this.pause = function()
	{
		if (_delay.executer != null)
		{
			_delay.executer.stop();
			_delay.executer = null;
		}
	};		
}

function wmxMarqueeSlide(slideId, slideBody)
{
	this.id = 'marqueeSlide_' + slideId;
	this.body = slideBody || '';
	this.element = new Element('div', { 'id': this.id, 'class': 'marqueeSlide', 'style': 'position:relative;' });
	this.element.innerHTML = this.body;
	this.hasImage = this.element.select('img').size() > 0;
	this.imagesPreloaded = false;
	this.startPos = { x: 0, y: 0 };
	this.offset = { x: 0, y: 0 };
	
	document.body.appendChild(this.element.hide());
	this.dimensions = { width: this.element.getWidth(), height: this.element.getHeight() };
	document.body.removeChild(this.element.show());		
	
	this.ResetPosition = function()
	{
		this.element.setStyle({left: this.startPos.x + 'px', top: this.startPos.y + 'px'});
	};
	
	this.RecalculateDimensions = function()
	{
		var onlyTemporary = false;
		if(!this.element.descendantOf(document.body))
		{
			document.body.appendChild(this.element.hide());
			onlyTemporary = true;
		}

		this.dimensions = { width: this.element.getWidth(), height: this.element.getHeight()};
		
		if(onlyTemporary)
		{
			document.body.removeChild(this.element.show());	
		}
	}
}

var preloadedImages = new Array();
function PreloadImages(onload, imageSrcArray)
{
	for(var i=0; i < imageSrcArray.length; i++)
	{
		if(!preloadedImages.pluck('src').include(imageSrcArray[i]))
		{
			var img = new Image();
			img.onload = onload;
			img.src = imageSrcArray[i];
			preloadedImages[i] = img;
		}
	};
};
	
function ImageLoaded(img)
{
	if(!img.complete)
	{
		return false;
	}
	
	if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) 
	{
		return false;
	}
	
	return true;
}
