//=== GLOBAL SETTINGS ===
dt_min = 2;	 //
dt_max = 4;	// bounds on the random duration of player re-alignment 
dt_quick = .5; // average duration of quick re-alignment
T_link = 5;	// duration link overlay is active at end of videos
DX = -30;	 //
DY = 10;	// global offset of the cluster
pct_zoom = 150; //percentage of zoom effect
dt_zoom = 3;	// zoom duration in seconds 
hover_color = '#F9F9F9';
link_color = '#E8B7D0';
//= END GLOBAL SETTINGS =				

//=== GLOBAL VARS ===
playerInfos = new Array();
highest_zidx = 0;

xt = 0;	 //
yt = 0;	// Mouse position at respectively previous update step

T = -1; 		// Remaining time in seconds until end of active video
TRefIdx = -1; 	// index corresponding to player upon which T is being calculated

stillUnaligned = 0; // How many players are not back in the cluster yet?

dragging = false;	// Is anything being dragged?
//== END GLOBAL VARS =

PlayerInfo = Class.create(
{
	initialize:	function(videoname, w,h, dx,dy)
				{
					this.videoname = videoname;
					this.playerID = 'player_' + videoname;
					this.containerID = 'container_' + videoname;
					this.dragAreaID = 'drag_area_' + videoname;
					this.dx = dx;
					this.dy = dy;
					this.w = w;
					this.h = h;
					this.containerDiv = $(this.containerID);
					this.dragAreaDiv = $(this.dragAreaID);	
				},
			
	disableDragging: function()
					{
						this.screenDiv.show();
					},
					
	enableDragging: function()
					{
						this.screenDiv.hide();
					},
					
	videoname:	'',		// key property relating container, player and drag area
	playerID:	'',		// an alternative key property
	containerID:'',		// ...yet another one
	dragAreaID:	'',		// *dito*
	w:			0,		 //
	h:			0,		// video dimensions in pixels
	dx:			0, 		 // 
	dy:			0,		// offset from cluster origin in pixels
	duration:	-1,		// video length in seconds
	playerDiv:	null,	// HTML div element containing JW player object 
	dragAreaDiv:null,	// HTML div element containing drag area
	containerDiv:null,	// HTML div element containing the above two divs
	dragObj:	null,
	
	hasLink:	false,
	linkDiv:	null,
	linkVisited:false,
	
	mouseOverDiv:null,
	
	screenDiv:	null,
	
	playing:	false	// is the video running?
} );


function getInfoByKey(key)
{
	for( var i=0; i<playerInfos.length; i++ )
		if( playerInfos[i].videoname==key
			|| playerInfos[i].playerID==key
			|| playerInfos[i].containerID==key )
			return playerInfos[i];	
	return null;
}


function getIdxByKey(key)
{
	for( var i=0; i<playerInfos.length; i++ )
		if( playerInfos[i].videoname==key
			|| playerInfos[i].playerID==key
			|| playerInfos[i].containerID==key )
			return i;	
	return null;
}


function wait(millis) 
{
var date = new Date();
var curDate = null;

do { curDate = new Date(); } 
while(curDate-date < millis);
} 


function addPlayer(videoname, w,h, dx,dy, link)
{	
	dx += DX;
	dy += DY;
	
	var container = $(videoname).parentNode;
	if( container.id != 'container_'+videoname )
		container.setAttribute('id','container_'+videoname);
	$(container).setStyle({	left: dx+'px', 
							top: dy+'px', 
							width: w+'px', 
							height: h+'px', 
							zIndex: highest_zidx++,
							borderColor: hover_color,
							borderWidth: '1px'
							});
		
	var dragArea = container.select('div.dragArea')[0];
	if( dragArea.id != 'drag_area_'+videoname )
		dragArea.setAttribute('id','drag_area_'+videoname);
	dragArea.setStyle({width: w+'px', height: h+'px'});
		
	
	var flashvars = 
	{
		file:		'media/'+ videoname +'.flv',
		image:		'mediaplayer_v5_1/media/'+ videoname +'.png',
		config:		'mediaplayer_v5_1/config.xml',
		playerready:'onPlayerReady',
		stretching:	'exactfit',
		provider:	'http'
	};
	var params = 
	{
		allowfullscreen:	'false',
		allowscriptaccess:	'always',
		wmode:				'opaque'
	};
	var attributes = 
	{
		id:		'player_'+videoname,	
		name:	'player_'+videoname,
		style:	'position:absolute;z-index:10;cursor:move'
	};
	swfobject.embedSWF(	"mediaplayer_v5_1/player-licensed.swf", 
						videoname, 
						w, h, 
						"9.0.0", "expressInstall.swf", 
						flashvars, params, attributes );
	
	container.observe( 'click', 
						function(ev){
							var info = getInfoByKey(videoname);
							
							if(!dragging)
							{
								if( info.playing )
								{
									if( info.hasLink && info.linkDiv.visible() )
									{
										info.linkDiv.hide();
										container.style.borderColor = hover_color;
									}
									else
										info.playerDiv.sendEvent('STOP');
								}
								else
								{
									info.playerDiv.sendEvent('PLAY',true);
									scheduleContainerAlignment( container.id );	
								}
							}
						} );	
						
	container.observe( 'mouseover', 
						function(ev){
							var info = getInfoByKey(videoname);
							container.style.zIndex = (++highest_zidx);
							container.style.borderStyle = 'solid';
							if( !info.playing )
								info.mouseOverDiv.show();
							playerInfos[TRefIdx].containerDiv.style.zIndex = (++highest_zidx);
						} );
											
	container.observe( 'mouseout', 
						function(ev){
							var info = getInfoByKey(videoname);
							info.mouseOverDiv.hide();
							container.style.borderStyle = 'none';
						} );
	
	options =
	{
		zindex:		20,
		scroll:		window,
		onStart:	function(dragObj,ev)
					{
						dragging = true;
						xt = ev.pointerX(); 
						yt = ev.pointerY();
					},
		onDrag:		moveContainer,		
		onEnd:		function(dragObj,ev){
						getInfoByKey(videoname).playerDiv.sendEvent('PLAY',true);
						scheduleContainerAlignment( getInfoByKey(videoname).containerID );	
						setDragging.delay(.1, false);
					}
	};					
	
	var dragObj = new Draggable('drag_area_'+videoname, options);
			
	var info = new PlayerInfo( videoname, w,h, dx,dy );
	info.dragObj = dragObj;
	
	var screenDiv = new Element( 'div', {id:'screen_'+videoname, 'class':'screen'} );
	screenDiv.setStyle({width: w+'px', height: h+'px'});
	container.insert( {top: screenDiv} );
	screenDiv.hide();
	info.screenDiv = screenDiv;
	
	var mouseOverImg = new Element( 'img', {src:'mediaplayer_v5_1/media/'+ videoname +'_title.png'} );
	var mouseOverDiv = new Element( 'div', {id:'MOimg_'+videoname, 'class':'mouseOverImg'} );
	mouseOverDiv.update(mouseOverImg);
	container.insert( {top: mouseOverDiv} );
	mouseOverDiv.hide();
	info.mouseOverDiv = mouseOverDiv;
	
	if( !Object.isUndefined(arguments[5]) )
	{
		info.hasLink = true;
		var linkImg = new Element('img', {src:'mediaplayer_v5_1/media/dummy.png'});
		linkImg.setStyle({width: w*pct_zoom/100+'px', height: h*pct_zoom/100+'px'});
		var linkDiv = new Element( 'div', {id:'link_'+videoname, 'class':'link'} );
		linkDiv.insert( new Element('a',{href: link}).update(linkImg) );
		container.insert( {top: linkDiv} );
		linkDiv.hide();
		
		info.linkDiv = linkDiv;
	}
	
	playerInfos.push(info);
}


function setDragging(state)
{
	dragging = state;
}


function onPlayerReady(playerObj) 
{
	var player = $(playerObj.id);
	
	player.addModelListener('STATE','onPlayerStateChange');
	player.addModelListener('TIME','updateTime');
	
	getInfoByKey(playerObj.id).playerDiv = player;
}


function updateTime(playerObj)
{
	T = playerObj.duration - playerObj.position;
	//$('t').innerHTML = T;
	TRefIdx = getIdxByKey(playerObj.id);
	// Store the video length for once:
	if( playerInfos[TRefIdx].duration < 0 )
		playerInfos[TRefIdx].duration = playerObj.duration;
}


function onPlayerStateChange(playerObj)
{
	var info = getInfoByKey(playerObj.id);
	
	switch( playerObj.newstate )
	{
		case 'PLAYING':
			info.playing = true;						 			
			info.mouseOverDiv.hide();
			zoomIn( info, dt_zoom, 0 );
			info.containerDiv.style.zIndex = (highest_zidx++);
//			scheduleContainerAlignment( info.containerID );	
			if( info.hasLink )
			{
				info.linkDiv.show();
				info.containerDiv.style.borderColor = link_color;
			}
			// Stop inactive players:
			for( var i=0; i<playerInfos.length; i++ )
				if( playerInfos[i].playerID != playerObj.id )
					playerInfos[i].playerDiv.sendEvent('STOP');
			break;
			
		case 'IDLE':
			TRefIdx = -1;
			info.playing = false;
			enforceContainerAlignment( info.containerID );		
			if( info.hasLink )
			{
				info.linkDiv.hide();
				info.containerDiv.style.borderColor = hover_color;
			}
			
			break;
			
		default:
			// Nothing to do here.
	}
}


function zoomIn(playerInfo, duration)
{			
	Effect.Queues.get('zoom_scope_'+playerInfo.videoname).invoke('cancel');
	
	
	new Effect.Morph( playerInfo.containerID, 
							 {
							 style:{
							 	width:playerInfo.w*pct_zoom/100+'px', 
							 	height:playerInfo.h*pct_zoom/100+'px'
							 	},
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );
	new Effect.Morph( playerInfo.dragAreaID, 
							 {
							 style:{
							 	width:playerInfo.w*pct_zoom/100+'px', 
							 	height:playerInfo.h*pct_zoom/100+'px'
							 	},
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );	
	new Effect.Morph( playerInfo.playerID, 
							 {
							 style:{
							 	width:playerInfo.w*pct_zoom/100+'px', 
							 	height:playerInfo.h*pct_zoom/100+'px'
							 	},
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );
}


function zoomOut(playerInfo, duration, delay)
{		
	//Effect.Queues.get('zoom_scope').invoke('cancel');
	
	new Effect.Morph( playerInfo.containerID, 
							 {
							 style:{
							 	width:playerInfo.w+'px', 
							 	height:playerInfo.h+'px'
							 	},
						 	 delay: delay,
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );
	new Effect.Morph( playerInfo.dragAreaID, 
							 {
							 style:{
							 	width:playerInfo.w+'px', 
							 	height:playerInfo.h+'px'
							 	},
						 	 delay: delay,
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );	
	new Effect.Morph( playerInfo.playerID, 
							 {
							 style:{
							 	width:playerInfo.w+'px', 
							 	height:playerInfo.h+'px'
							 	},
						 	 delay: delay,
				 			 duration: duration,
				 			 queue:{scope:'zoom_scope_'+playerInfo.videoname}
				 			 } );

}	


function moveContainer(dragObj,ev)
{
	var container = dragObj.element.parentNode;
	var dx = ev.pointerX() - xt;
	var dy = ev.pointerY() - yt;
	xt = ev.pointerX();
	yt = ev.pointerY();
	container.style.left = parseInt( container.style.left ) + dx +'px';
	container.style.top = parseInt( container.style.top ) + dy +'px';
}


function scheduleLinkOverlay(playerInfo)
{
	if( !playerInfo.hasLink )
		return;
	// Safeguard against non-initialization of video duration:
	if( playerInfo.duration < 0 ) 
		scheduleLinkOverlay.delay(0.1, playerInfo);
	else
	{
		new Effect.Appear( playerInfo.linkDiv, 
					{delay:playerInfo.duration-T_link, duration:1, queue:{scope:'link_scope'}} );
		playerInfo.linkDiv.hide.delay(playerInfo.duration-0.1);
	}
}
function disruptLinkOverlay(playerInfo)
{	
	if( !playerInfo.hasLink )
		return;	
	playerInfo.linkDiv.hide();
	Effect.Queues.get('link_scope').invoke('cancel');
}


function scheduleContainerAlignment(staticContainerID)
{
	var staticIdx = getIdxByKey(staticContainerID);
	
	// Safeguard against case where remaining playing time T is not (yet) determined by video corresponding to staticIdx:
	if( TRefIdx != staticIdx ) 
		scheduleContainerAlignment.delay(0.1, staticContainerID);
	else
	{
		Effect.Queues.get('alignment_scope').invoke('cancel');
		
		var staticX = parseInt( playerInfos[staticIdx].containerDiv.style.left );
		var staticY = parseInt( playerInfos[staticIdx].containerDiv.style.top );			
		
		
		for( var i=0; i<playerInfos.length; i++ )
		{
			if( i == staticIdx )
				zoomOut( playerInfos[i], dt_zoom, T-dt_zoom );
			else
			{
			var otherContainer = playerInfos[i].containerDiv;
	
			var dx = playerInfos[i].dx - playerInfos[staticIdx].dx;
			var dy = playerInfos[i].dy - playerInfos[staticIdx].dy;
			var dt = dt_min + Math.random() * (dt_max-dt_min); // temporal offset in seconds
			new Effect.Move( otherContainer, {	my_i: i, // sucks, I know!
												x: staticX + dx,
												y: staticY + dy, 
												mode: 'absolute',
												delay: T-dt,
												duration: dt,
//												beforeStart: function(){
//													stillUnaligned++;
//													},
												afterSetup: function(effObj){
													var i = effObj.options.my_i;
													playerInfos[i].disableDragging();
													},
//												afterFinish: function(effObj){
//													stillUnaligned--;			
//													var i = effObj.options.my_i;
//													playerInfos[i].enableDragging();
//													},
												queue: {scope: 'alignment_scope'}
											   } );
			}
		}
	}
}


function enforceContainerAlignment(staticContainerID)
{
	var staticIdx = getIdxByKey( staticContainerID );
	
	var staticX = parseInt( playerInfos[staticIdx].containerDiv.style.left );
	var staticY = parseInt( playerInfos[staticIdx].containerDiv.style.top );
	
	Effect.Queues.get('alignment_scope').invoke('cancel');
	Effect.Queues.get('zoom_scope_'+playerInfos[staticIdx].videoname).invoke('cancel');
	
	for( var i=0; i<playerInfos.length; i++ )
	{
		zoomOut( playerInfos[i], dt_quick, 0 );
		
		if( i != staticIdx )
		{
			var dx = playerInfos[i].dx - playerInfos[staticIdx].dx;
			var dy = playerInfos[i].dy - playerInfos[staticIdx].dy;
			var dt = dt_quick * ( 0.5 + Math.random() ); // +-50%
			new Effect.Move( playerInfos[i].containerDiv, 	
															{	x: staticX + dx,
				 												y: staticY + dy, 
				 												mode: 'absolute',
				 												duration: dt,
				 												afterSetup: function(effObj){
																var i = effObj.options.my_i;
																playerInfos[i].disableDragging();
																},
																queue: {scope: 'alignment_scope'}	
															} ); 
			
		}
			
		playerInfos[i].enableDragging();
	}
	
	stillUnaligned = 0;
}

