function CarouselItemPosition()
{
	this.Set = function(l,t,w,h,z)
	{
		this.l = l;
		this.t = t;
		this.w = w;
		this.h = h;
		this.z = z;
	}
	
	this.Copy = function(pos)
	{
		this.l = pos.l;
		this.t = pos.t;
		this.w = pos.w;
		this.h = pos.h;
		this.z = pos.z;
	}
	
	this.Set(0,0,0,0,0);
	
}

function CarouselItem(i)
{	// i is CarouselDescription's item
	var img = document.createElement('img');
	img.src		= i[1];
	img.width	= 0; this.W = i[2];
	img.height	= 0; this.H = i[3];
	img.alt		= i[4];
	img.border = 0;
	this._img = img;

	var a = document.createElement('a');
	a.href = i[0];
	a.target = '_top';
	a.title = i[4];
	a.style.position = 'absolute';
	a.CarouselItem = this;
	a.onmouseover = function ()	{ window.status = this.title; this.CarouselItem.setTopMost(true); this.CarouselItem.Carousel.UpdateTime = false; return true; };
	a.onmouseout = function ()	{ window.status = ''; this.CarouselItem.setTopMost(false); this.CarouselItem.Carousel.UpdateTime = true; return true; };
	a.appendChild(img);
	this._a = a;
	
	this.Element = a;
	
	this.Pos0 = new CarouselItemPosition();
	this.Pos1 = new CarouselItemPosition();
	
	this.setWidth	= function(w)	{ this._img.width = w; }
	this.getWidth	= function()	{ return this._img.width; }
	this.setHeight	= function(h)	{ this._img.height = h; }
	this.getHeight	= function()	{ return this._img.height; }
	this.setTop		= function(t)	{ this._a.style.top = t + 'px'; }
	this.getTop		= function()	{ return this._a.style.top; }
	this.setLeft	= function(l)	{ this._a.style.left = l + 'px'; }
	this.getLeft	= function()	{ return this._a.style.left; }
	
	this._z = 0;
	this._topMost = false;
	this.setZIndex	= function(z)	{ this._z = Math.round(z); if( !this._topMost ) this._a.style.zIndex = this._z; }
	this.getZIndex	= function()	{ return this._a.style.zIndex; }
	this.setTopMost	= function(f)	{ this._topMost = f; this._a.style.zIndex = f ? 999000 : this._z; }
	
//	this.Bool0 = true;
	this.positionAt	= function(m0)
	{
		var m1 = 1 - m0;
		this.setWidth	(m0 * this.Pos0.w + m1 * this.Pos1.w);
		this.setHeight	(m0 * this.Pos0.h + m1 * this.Pos1.h);
		this.setTop		(m0 * this.Pos0.t + m1 * this.Pos1.t);
		this.setLeft	(m0 * this.Pos0.l + m1 * this.Pos1.l);
		this.setZIndex	(m0 * this.Pos0.z + m1 * this.Pos1.z);
	/* debugging stuff
		if( this.Bool0 )
		{
			//alert("w=" + this.getWidth() );
			//alert("top=" + this.getTop() );
			//alert("left=" + this.getLeft() );
			alert("Z=" + this.getZIndex() );
			this.Bool0 = confirm("continue?");
		}
		*/
	}
}

// Originally Carousel is the description array
// We attach other props and functions to it
function Carousel_Init(Carousel, ElementId)
{
	for(var length=0; Carousel[length] != null; length++)
		continue;
	if( length == 0 ) return;
	Carousel.length = length;
	Carousel.Length = length;
	
	Carousel.ElementId = ElementId;
	Carousel.Element = document.getElementById(ElementId);
	Carousel.Element.Carousel = Carousel;

	Carousel.Items = new Array(); 
	for(var idx=0; idx < length; idx++)
	{
		var ci = new CarouselItem( Carousel[idx] );
		Carousel.Element.appendChild( ci.Element );
		Carousel.Items[idx] = ci;
		ci.Carousel = Carousel;
	}

	//alert("Element.clientWidth=" + Carousel.Element.clientWidth);
	//alert("Carousel.Items[0].W=" + Carousel.Items[0].W);

	Carousel.calcPosition_AtCorners = function (Left, Top, Size)
	{
		var W  = this.Element.clientWidth;
		var H  = this.Element.clientHeight;

		for(idx = 0; idx < this.Length; idx++)
		{
			i = this.Items[idx];
			i.Pos1.Set( Left==0 ? W - i.W*Size : 0, Top==0 ? H - i.H*Size : 0, i.W*Size, i.H*Size, (this.Length-idx)*10);
		}
	}

	// make it to start from different corners
	Carousel.calcPosition_AtCorners(Math.round(Math.random()), Math.round(Math.random()), 0);
	
	Carousel.calcPosition_InLine = function ()
	{
		var i = this.Items[0];
		if( this.Length == 1 )
		{
			i.Pos1.Set( 
				(this.Element.clientWidth  - i.W)/2, 
				(this.Element.clientHeight - i.H)/2, i.W, i.H, 0);
			return;
		}
		
		var W  = this.Element.clientWidth - i.W/2 - this.Items[this.Length-1].W/2;
		var x0 = 0;
		var dx = W / (this.Length-1);

		var wmin = (this.Length - 1)* 5;
		if( W < wmin )
		{
			x0 = (W-wmin)/2;
			dx = 5;
		}
		
		var H  = this.Element.clientHeight - i.H/2 - this.Items[this.Length-1].H/2;
		var y0 = 0;
		var dy = H / (this.Length-1);

		var hmin = (this.Length - 1)* 5;
		if( H < hmin )
		{
			y0 = (H-hmin)/2;
			dy = 5;
		}
		
		for(idx = 0; idx < this.Length; idx++)
		{
			i = this.Items[idx];
			i.Pos1.Set( x0 + dx*idx, y0 + dy*idx, i.W, i.H, (this.Length-idx)*10);
		}
	}

	Carousel.calcPosition_Ellipse = function ()
	{
		var i = this.Items[0];
		
		var D = 5; // "depth" coefficient
		
		var W = (this.Element.clientWidth - i.W*D/(D+1))/2;
		var X = this.Element.clientWidth / 2;

		var H = (this.Element.clientHeight - i.H/2 - i.H/2*(D-1)/(D+1))/2;
		var Y = (this.Element.clientHeight - i.H/2 + i.H/2*(D-1)/(D+1))/2;
		
		var S = this.Speed*200/Math.sqrt(W*W+H*H);// -0.03; // speed
		var T = S * this.Time;
		for(idx = 0; idx < this.Length; idx++)
		{
			// angle 
			var a = Math.PI / 180 * (T + idx*360/this.Length);
			i = this.Items[idx];
			var w = i.W*(D+Math.cos(a))/(D+1);
			var h = i.H*(D+Math.cos(a))/(D+1);
			var z = (1+Math.cos(a))*100;
			i.Pos1.Set( X + W*Math.sin(this.Nx * a) - w/2, Y + H*Math.cos(this.Ny * a) - h/2, 
				w, h, z);
				//(this.Length-idx)*10);
		}
	}
	
	Carousel.positionItems = function ()
	{
		var m0;
		if( this.Time >= this.TransitionEnd )
			m0 = 0;
		else if( this.Time > this.TransitionStart && this.TransitionEnd > this.TransitionStart )
			m0 = (this.TransitionEnd - this.Time) / (this.TransitionEnd - this.TransitionStart);
		else
			m0 = 1;

		for(idx = 0; idx < this.Length; idx++)
		{
			this.Items[idx].positionAt(m0);
		}
	}
	
	Carousel.startTransition = function (start, end, calcPosition)
	{
		//var t = new Date().getTime();
		var t = this.Time;
		this.TransitionStart = t + start;
		this.TransitionEnd	 = t + end;
		this.CalcPosition	 = calcPosition;
		for(idx = 0; idx < this.Length; idx++)
		{
			i = this.Items[idx];
			i.Pos0.Copy( i.Pos1 );
		}
		Carousel.CalcPosition();
	}
	
	// initial
	Carousel.Time0 = new Date().getTime();
	Carousel.Time = 0;
	Carousel.startTransition(0, 2000, Carousel.calcPosition_InLine);
	Carousel.CalcPositionRequired = true;
	Carousel.UpdateTime = true;
	Carousel.Speed = -0.02; // speed
	Carousel.Nx = 1;
	Carousel.Ny = 1;
	
	//setTimeout("Carousel_Timeout('" + ElementId + "',50)" , 1000);
	Carousel_timeout(ElementId, 50);
}

	function Carousel_timeout(ElementId, dt)
	{
		var Element = document.getElementById(ElementId);
		var Carousel = Element.Carousel;
		if( Carousel.UpdateTime )
		{
			//Carousel.Time = new Date().getTime() - Carousel.Time0;
			Carousel.Time += dt; 
		}
		
		//document.getElementById('txt').value = Carousel.Time;

		if( Carousel.Time > 3000 )
		{
			if( Carousel.CalcPosition != Carousel.calcPosition_Ellipse )
			{
				Carousel.startTransition(0, 3000, Carousel.calcPosition_Ellipse);
				Carousel._mode = 0;
			}
			else
			{
				if( Carousel.Time >= Carousel.TransitionEnd + 6000 + Math.random()*4000 )
				{	// make more different knots
					var n = Math.random()*5;
					var e = 3000;
					if( n < 1 && Carousel._mode != 1 )
					{ Carousel.Nx = 1; Carousel.Ny = 2; Carousel._mode = 1; }
					else if( n < 2 && Carousel._mode != 2 )
					{ Carousel.Nx = 2; Carousel.Ny = 1; e = 5000; Carousel._mode = 2; }
					else if( n < 3 && Carousel._mode != 3 )
					{ Carousel.Nx = 3; Carousel.Ny = 2; Carousel._mode = 3; }
					else if( n < 4 && Carousel._mode != 4 )
					{ Carousel.Nx = 3; Carousel.Ny = 1; Carousel._mode = 4; }
					else if( Carousel._mode != 0 )
					{ Carousel.Nx = 1; Carousel.Nx = 1; e = 5000; Carousel._mode = 0; }
					else
					{ Carousel.Nx = 1.7; Carousel.Nx = 1.3; e = 2000; Carousel._mode = -1; }
					Carousel.startTransition(0, e, Carousel.calcPosition_Ellipse);
				}
			}
		}
		
		if( Carousel.CalcPositionRequired )
		{
			Carousel.CalcPosition();
		}
		Carousel.positionItems();

		t = setTimeout("Carousel_timeout('" + ElementId + "'," + dt + ")" , dt);
	}

function element_onload()
{
	Carousel_Init(CarouselObject, 'Carousel');
}