/*      .             .               .                   .   
 *  ,-. |-. ,-. . ,-. |-. ,-. ,-. ,-. |-.   ,-. ,-.   . . | , 
 *  |   | | |   | `-. | | |-' ,-| |   | |   |   | |   | | |<  
 *  `-' ' ' '   ' `-' ^-' `-' `-^ `-' ' ' : `-' `-' : `-^ ' ` 
 * ,---.,---.,---.,---.    ,---.|    ,---.,---.,---.,---.,---.
 * |    |   ||    |---'    |    |    ,---|`---.`---.|---'`---.
 * `---'`---'`    `---'    `---'`---'`---^`---'`---'`---'`---'
 *
 * 2003-2005
 *
 */
var UF_REQUEST_URL = domain + "/core/actioners/UserFeaturingActioner.php";
var USER_VIEWER_URL = domain + "/core/scripts/userViewer.php?userID=";
var ARROW_OFFSET = new Coords( 18, 65 );
var INITIAL_DISPLAY_TIME = 2000;
var FADE_BUFFER = 1000;
var FADE_INCREMENT = 0.2;
var FADE_INCREMENT_TIME = 40;
var SAVE_TIMEOUT = 500;

var entryID;
var mousePos = new Coords( 0, 0 );
var objPhoto = null;
var draggedArrow = null;
var browser = "IE";
var arrowAlpha = 0.8;
var arrowArray = Array();
var browserSupportsFilters;
var saveTimer = null;
var fadeTimer = null;
var fadeBufferTimer = null;
var godMode = false;
var photoFeaturingUserInitialised = false;

function initFeaturing( objPhotoID, argEntryID )
{
	entryID = argEntryID;
	var photoElement = document.getElementById( objPhotoID )
	objPhoto = new Photo( document.getElementById( objPhotoID ) );
	
	browserSupportsFilters = ( photoElement.style.filter != null );
	
	document.onmousemove = docMouseMove;
	document.onmouseup = function( e )
	{
		if ( draggedArrow == null ) return false;
		initSavePosition( draggedArrow );
		godMode = false;
		draggedArrow = null;
	};
	photoFeaturingUserInitialised = true;
}

function setArrowFadeDirection( visible )
{
	// Keep opaque if being dragged
	if ( draggedArrow != null && visible == false ) return;
	
	// godMode protects arrows from fading
	if ( godMode && visible == false ) return;

	if ( fadeTimer ) clearTimeout( fadeTimer );
	
	var arrowFadeIncrement = visible ? FADE_INCREMENT : -FADE_INCREMENT;
	//alert( "visible=" + visible + " arrowAlpha=" + arrowAlpha + " arrowFadeIncrement=" + arrowFadeIncrement );
	
	if ( ( arrowAlpha + arrowFadeIncrement ) > 1 )
	{
		arrowAlpha = 1.0;
	}	
	else if ( ( arrowAlpha + arrowFadeIncrement ) < 0 ) 
	{
		arrowAlpha = 0.0;
	}
	else
	{
		arrowAlpha += arrowFadeIncrement;
		fadeTimer = setTimeout( 
			"setArrowFadeDirection( " + visible + " )", 
			FADE_INCREMENT_TIME );
	}	
	for ( i = 0; i < arrowArray.length; i++ )
	{
		arrowArray[i].setOpacity( arrowAlpha );
	}
}

function Photo( obj )
{
	this.obj = obj;
	var objOffset = obj;
	this.coords = new Coords( 0, 0 );

	do
	{
		this.coords.y += objOffset.offsetTop;
		this.coords.x += objOffset.offsetLeft;
		if ( objOffset.offsetParent == document.body ) 
		{ 
			/* safari returns margins on body which is incorrect if the child is absolutely positioned */
			if ( document.defaultView && document.defaultView.getComputedStyle( objOffset, null ).position=='absolute' ) break;
		}
		objOffset = objOffset.offsetParent;
	} while ( objOffset );
	
	this.height = obj.height;
	this.width = obj.width;
	this.obj.onmouseout = function()
	{ 
		if ( fadeBufferTimer != null ) clearTimeout( fadeBufferTimer ); 
		clearTimeout( fadeTimer ); 		
		fadeBufferTimer = setTimeout( "setArrowFadeDirection( false );", FADE_BUFFER );
	};
	this.obj.onmouseover = function()
	{ 
		if ( fadeBufferTimer != null ) clearTimeout( fadeBufferTimer );
		clearTimeout( fadeTimer ); 
		setArrowFadeDirection( true );
	};
}

function Coords( x, y )
{
	this.x = x;
	this.y = y;
	this.toString = function(){ return "x=" + this.x + ", y=" + this.y; }
}

function Arrow( user, coords, isMovable )
{
	this.user = user;
	this.coords = coords;
	this.isMovable = isMovable;
	this.clickOffset = new Coords( 0, 0 );

	var objTable = document.createElement( 'TABLE' );
	objTable.className = 'arrowContainer';
	if ( this.isMovable ) objTable.style.cursor = 'move';
	objTable.id = this.user.userID;
	
	var objTableBody = document.createElement( 'TBODY' );
	var objArrowRow = document.createElement( 'TR' );
	
	this.objArrowIcon = document.createElement( 'TD' );
	this.objArrowName = document.createElement( 'TD' );
	this.objArrowRight = document.createElement( 'TD' ); 
	
	this.objArrowIcon.className = 'arrowIcon';
	this.objArrowRight.className = 'arrowRight';

	if ( this.user.imageURL )
	{
		var objIcon = document.createElement( 'IMG' ); 
		objIcon.src = ( this.user.imageURL.substring( 0, 7 ) == 'http://' ) ? 
			this.user.imageURL : domain + this.user.imageURL;

		if ( !this.isMovable )
		{
			objIconLink = document.createElement( 'A' );
			objIconLink.href = USER_VIEWER_URL + this.user.userID;
			objIconLink.appendChild( objIcon );
			this.objArrowIcon.appendChild( objIconLink );
		}
		else 
		{
			this.objArrowIcon.appendChild( objIcon );
		}
	}

	var objWaitingIcon = document.createElement( 'IMG' ); 
	objWaitingIcon.src = domain + "/core/images/spinner.gif";
	objWaitingIcon.style.marginLeft = "2px";
	objWaitingIcon.style.marginRight = "0";
	objWaitingIcon.style.visibility = "hidden";

	objPara = document.createElement( 'P' );
	objPara.style.padding = "0";
	objPara.style.margin = "0";
	if ( !this.isMovable )
	{
		objLink = document.createElement( 'A' );
		objLink.href = USER_VIEWER_URL + this.user.userID;
		objLink.appendChild( document.createTextNode( this.user.forename ) );
		objPara.appendChild( objLink );
	}
	else 
		objPara.appendChild( document.createTextNode( this.user.forename ) );
	objPara.appendChild( document.createElement( 'BR' ) );
	objPara.appendChild( objWaitingIcon );
	this.objArrowName.appendChild( objPara );
	
	this.objArrowRight.appendChild( document.createTextNode( " " ) );
	objArrowRow.appendChild( this.objArrowIcon );
	objArrowRow.appendChild( this.objArrowName );
	objArrowRow.appendChild( this.objArrowRight );
	objTableBody.appendChild( objArrowRow );
	objTable.appendChild( objTableBody );
	
	this.getImageRelativeCoords = function()
	{
		return new Coords( 
			parseInt( objTable.style.left ) + ARROW_OFFSET.x - objPhoto.coords.x, 
			parseInt( objTable.style.top ) + ARROW_OFFSET.y - objPhoto.coords.y );
	};
	
	this.moveToCoords = function( coords )
	{	
		objTable.style.left = coords.x - ARROW_OFFSET.x - this.clickOffset.x + "px"; 
		objTable.style.top = coords.y - ARROW_OFFSET.y - this.clickOffset.y + "px";
	};
	
	this.setWaiting = function( isWaiting )
	{
		objWaitingIcon.style.visibility = isWaiting ? "visible" : "hidden";	
	};
	
	this.pngLoaders = function()
	{
		this.objArrowIcon.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/core/images/arrow.png', sizingMethod='crop')";
		this.objArrowName.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/core/images/arrowMid.png', sizingMethod='crop')";
		this.objArrowRight.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/core/images/arrowRight.png', sizingMethod='crop')";
	};
	
	this.refreshContent = function()
	{
		this.objArrowIcon.style.zIndex = 10;
		this.objArrowRight.style.zIndex = 10;
	};

	this.setOpacity = function( opacity )
	{ 
		if ( objTable.style.MozOpacity != null)
		{
			objTable.style.MozOpacity = Math.round( opacity * 100 ) / 100;
		}
		else if ( objTable.style.opacity != null)
		{
			objTable.style.opacity = Math.round( opacity * 100 ) / 100;
		}
		else if ( browserSupportsFilters )
		{
			if ( opacity > 0 )
				objTable.style.visibility = "visible";
			else
				objTable.style.visibility = "hidden";
		}
		else
		{
			if ( opacity > 0 )
				objTable.style.visibility = "visible";
			else
				objTable.style.visibility = "hidden";	
		}
	};
	
	objTable.onmouseover = function()
	{ 
		if ( fadeBufferTimer != null ) clearTimeout( fadeBufferTimer );
		if ( fadeTimer != null ) clearTimeout( fadeTimer ); 
		setArrowFadeDirection( true ); 
	};
	
	objTable.onmouseout = function()
	{ 
		if ( fadeBufferTimer != null ) clearTimeout( fadeBufferTimer ); 
		if ( fadeTimer != null ) clearTimeout( fadeTimer ); 		
		fadeBufferTimer = setTimeout( "setArrowFadeDirection( false );", FADE_BUFFER );
	};
	
	var objArrow = this;
	
	if ( this.isMovable ) 
	{
		objTable.onmousedown = function( e )
		{ 
			draggedArrow = objArrow;
			draggedArrow.clickOffset = new Coords( 
				mousePos.x - parseInt( objTable.style.left ), 
				mousePos.y - parseInt( objTable.style.top ) );
			//alert( "offset: " + draggedArrow.clickOffset );
			docMouseMove( e ); 
			return false; 
		}; 
	}
	else
	{
		objTable.style.cursor = 'hand';
		objTable.onmousedown = function( e )
		{ 
			window.location.href = USER_VIEWER_URL + user.userID;
			return false; 
		}
	}; 
	
	if ( browserSupportsFilters ) 
	{
		this.pngLoaders();
	}
	else
	{	
		this.objArrowIcon.style.backgroundImage = "url( '/core/images/arrow.png' )";
		this.objArrowName.style.backgroundImage = "url( '/core/images/arrowMid.png' )";
		this.objArrowName.style.backgroundRepeat = "repeat-x";
		this.objArrowRight.style.backgroundImage = "url( '/core/images/arrowRight.png' )";
	} 
	this.moveToCoords( this.coords );
	this.setOpacity( arrowAlpha );
	document.body.appendChild( objTable );
	arrowArray[ arrowArray.length ] = this;
	
	this.remove = function()
	{
		objTable.parentNode.removeChild( objTable );
		arrowArray.splice( arrowArray.length - 1, 1 );
		var objAddUserArrow = document.getElementById( "addUserArrow" );
		objAddUserArrow.style.display = "inline";
	}
}

function User( userID, forename, imageURL )
{
	this.userID = userID;
	this.forename = forename;
	this.imageURL = imageURL;
}

function initUnfeatures( arrow )
{
	// Clear the timer to avoid unnecessary repeat calls to this function
	if ( saveTimer ) clearTimeout( saveTimer );
	arrow.setWaiting( true );
	var reqSave = getXMLHTTPObject();
	reqSave.onreadystatechange = function() 
	{
		if ( reqSave.readyState == 4 )
		{
			if ( !reqSave.responseText )
				alert( "Your position could not be deleted" );
			else
			{
				//alert( "[" + reqSave.responseText + "]" );
				arrow.remove();
			}
		}
	}
	reqSave.open( "POST", UF_REQUEST_URL, true )
	reqSave.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
	reqSave.send( "action=unfeatures&entryID=" + entryID + 
		"&userID=" + arrow.user.userID );
}

function initSavePosition( arrow )
{
	// Clear the timer to avoid unnecessary repeat calls to this function
	if ( saveTimer ) clearTimeout( saveTimer );
	arrow.setWaiting( true );
	var coords = arrow.getImageRelativeCoords();
	var reqSave = getXMLHTTPObject();
	reqSave.onreadystatechange = function() 
	{
		if ( reqSave.readyState == 4 )
		{
			if ( !reqSave.responseText )
				alert( "Your position could not be saved - please try again later" );
			else
			{
				arrow.setWaiting( false ); 
				//alert( "Position saved (" + coords + ") [" + reqSave.responseText + "]" );
			}
		}
	}
	reqSave.open( "POST", UF_REQUEST_URL, true )
	reqSave.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
	reqSave.send( "action=features&entryID=" + entryID + 
		"&userID=" + arrow.user.userID + 
		"&x=" + coords.x + "&y=" + coords.y );
}

function docMouseMove( e )
{
	if ( document.all )
	{
	    mousePos.x = window.event.x; 
	    mousePos.y = window.event.y;
	    if ( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) 
	    {
	     	mousePos.x += document.body.scrollLeft;
	     	mousePos.y += document.body.scrollTop;
	    }
	    else if ( document.documentElement &&
				( 	document.documentElement.scrollLeft || 
					document.documentElement.scrollTop ) )
	    {
	     	mousePos.x += document.documentElement.scrollLeft;
	     	mousePos.y += document.documentElement.scrollTop;
	    }
	}
	else if ( document.getElementById || document.layers )
	{
     	mousePos.x = e.pageX;
     	mousePos.y = e.pageY;
	}
	if ( draggedArrow != null ) 
	{
		if ( saveTimer ) clearTimeout( saveTimer );
		
		arrowheadX = ARROW_OFFSET.x - draggedArrow.clickOffset.x + mousePos.x;
		arrowheadY = ARROW_OFFSET.y - draggedArrow.clickOffset.y + mousePos.y;

		var atBoundary = false; 

		if ( arrowheadX < objPhoto.coords.x ) 
		{
			arrowheadX = objPhoto.coords.x; 
			atBoundary = true;
		}
		else if ( arrowheadX >= objPhoto.width + objPhoto.coords.x )
		{ 
			arrowheadX = objPhoto.width + objPhoto.coords.x; 
			atBoundary = true; 
		}
		// Note that logic of y coords is independent to logic of x coords
		if ( arrowheadY < ( objPhoto.coords.y ) ) 
		{
			arrowheadY = objPhoto.coords.y; 
			atBoundary = true; 
		}
		else if ( arrowheadY >= objPhoto.coords.y + objPhoto.height ) 
		{
			arrowheadY = objPhoto.height + objPhoto.coords.y; 
			atBoundary = true; 
		}
		draggedArrow.moveToCoords( 
			new Coords( 
				arrowheadX + draggedArrow.clickOffset.x, 
				arrowheadY + draggedArrow.clickOffset.y ) );
				
		// If at a boundary, set a timeout to cancel the drag operation
		if ( atBoundary ) saveTimer = setTimeout( "document.onmouseup()", SAVE_TIMEOUT );
	}
	return false;
}
