var previewTime     = 5;
var previewSteps    = 15;
var includeFade     = 1;
var minBorder       = 90;   // Amount of padding between large, scaled down images, and the window edges

var ImagesURI   = 'youthbuild/'; // Location of the preview images

var windowWidth = 0, windowHeight = 0, windowScroll = 0; windowScrollWidth = 0; windowScrollHeight = 0;
var previewOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image();
var preloadAnimTimer = 0;

var previewActive = new Array(); 
var previewTimer  = new Array(); 
var previewOrigW  = new Array(); 
var previewOrigH  = new Array();
var previewOrigX  = new Array(); 
var previewOrigY  = new Array();

var previewID         = "PreviewBox";
var previewImageID    = "PreviewImage";
var waitAnimID        = "WaitAnimBox";
var waitAnimImageID   = "WaitAnimImage";

// <body onload="initPreview()">
function initPreview() 
{
	updateHrefObjectPreviewEvents();
	insertPreviewHTML();
	previewdiv = document.getElementById(previewID);  
	previewimg = document.getElementById(previewImageID);
}

// preview
function updateHrefObjectPreviewEvents() 
{
	if (!document.getElementsByTagName)
		return;

	var links = document.getElementsByTagName("a");
	for (i = 0; i < links.length; i++) 
	{
		if ((links[i].getAttribute("href")) && (links[i].getAttribute("rel") == "preview"))
		{
			links[i].onclick = function (event) { return previewClick(this, event); };
			links[i].onmouseover = function () { previewPreload(this); };
		}
	}
}

// Preview: Load an image into an image object. When done loading, function sets preloadActive to false,
// so other bits know that they can proceed with the preview.
// Preloaded image is stored in imgPreload and swapped out in the preview function.
function previewPreload(from) 
{
    var theimage = from.getAttribute("href");
    // Only preload if we have to, i.e. the image isn't this image already
    if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) 
    {
        preloadActive = true;
        imgPreload = new Image();
        // Set a function to fire when the preload is complete, setting flags along the way.
        imgPreload.onload = function(){preloadActive = false;}
        imgPreload.src = theimage;
    }
}

function preloadAnimStart() 
{
	preloadTime = new Date();
	document.getElementById(waitAnimID).style.left = (windowWidth / 2) + 'px';
	document.getElementById(waitAnimID).style.top = ((windowHeight / 2) + windowScroll) + 'px';
	document.getElementById(waitAnimID).style.visibility = "visible";	
	preloadFrame = 1;
	document.getElementById(waitAnimImageID).src = ImagesURI+'wait_anim_'+preloadFrame+'.png';  
	preloadAnimTimer = setInterval("preloadAnim()", 100);
}

// Preview: Display and ANIMATE the jibber-jabber widget. Once preloadActive is false, bail and preview it up!
function preloadAnim(from) 
{
	if (preloadActive != false)
	{
		document.getElementById(waitAnimImageID).src = ImagesURI+'wait_anim_'+preloadFrame+'.png';
		preloadFrame++;
		if (preloadFrame > 12) preloadFrame = 1;
	}
	else 
	{
		document.getElementById(waitAnimID).style.visibility = "hidden";    
		clearInterval(preloadAnimTimer);
		preloadAnimTimer = 0;
		previewIn(preloadFrom);
	}
}

// ZOOM CLICK: We got a click! Should we do the preview? Or wait for the preload to complete?
// todo?: Double check that imgPreload src = clicked src
function previewClick(from, evt) 
{
	var shift = getShift(evt);

	// Check for Command / Alt key. If pressed, pass them through -- don't preview!
	if (!evt && window.event && (window.event.metaKey || window.event.altKey)) 
		return true;
	else if (evt && (evt.metaKey|| evt.altKey)) 
		return true;

	// Get browser dimensions
	getSize();

	// If preloading still, wait, and display the spinner.
	if (preloadActive == true) 
	{
		// But only display the spinner if it's not already being displayed!
		if (preloadAnimTimer == 0) 
		{
			preloadFrom = from;
			preloadAnimStart();	
		}
	} 
	else 
	{
	    previewPreload(from);
		// Otherwise, we're loaded: do the preview!
		previewIn(from, shift);
	}
	return false;
}

// Preview: Move an element in to endH endW, using previewHost as a starting point.
// "from" is an object reference to the href that spawned the preview.
function previewIn(from, shift) 
{
	previewimg.src = from.getAttribute("href");

	// Determine the preview settings from where we came from, the element in the <a>.
	// If there's no element in the <a>, or we can't get the width, make stuff up
	if (from.childNodes[0].width) 
	{
		startW = from.childNodes[0].width;
		startH = from.childNodes[0].height;
		startPos = findElementPos(from.childNodes[0]);
	}
	else 
	{
		startW = 50;
		startH = 12;
		startPos = findElementPos(from);
	}

	hostX = startPos[0];
	hostY = startPos[1];

	// Make up for a scrolled containing div.
	// TODO: This HAS to move into findElementPos.
	if (document.getElementById('scroller')) 
		hostX = hostX - document.getElementById('scroller').scrollLeft;

	// Determine the target preview settings from the preloaded image object
	endW = imgPreload.width;
	endH = imgPreload.height;

	// Start! But only if we're not previewing already!
	if (previewActive[previewImageID] != true) 
	{
		// Store original position in an array for future previewOut.
		previewOrigW[previewImageID] = startW;
		previewOrigH[previewImageID] = startH;
		previewOrigX[previewImageID] = hostX;
		previewOrigY[previewImageID] = hostY;

		// Now set the starting dimensions
		previewimg.style.width  = startW + 'px';
		previewimg.style.height = startH + 'px';
		previewdiv.style.left   = hostX + 'px';
		previewdiv.style.top    = hostY + 'px';

		// Show the previewing image container, make it invisible

		if (includeFade == 1) 
			setOpacity(0, previewID);
		previewdiv.style.visibility = "visible";
		// If it's too big to fit in the window, shrink the width and height to fit (with ratio).
		sizeRatio = endW / endH;
		if (endW > windowWidth - minBorder) 
		{
			endW = windowWidth - minBorder;
			endH = endW / sizeRatio;
		}
		if (endH > windowHeight - minBorder) 
		{
			endH = windowHeight - minBorder;
			endW = endH * sizeRatio;
		}

		previewChangeX = ((windowWidth / 2) - (endW / 2) - hostX);
		previewChangeY = (((windowHeight / 2) - (endH / 2) - hostY) + windowScroll);
		previewChangeW = (endW - startW);
		previewChangeH = (endH - startH);
		
		// Shift key?
	
		if (shift) 
			tempSteps = previewSteps * 7;
		else 
			tempSteps = previewSteps;

		// Setup Preview
		previewCurrent = 0;

		// Setup Fade with Preview, If Requested
		if (includeFade == 1) 
		{
			fadeCurrent = 0;
			fadeAmount = (0 - 100) / tempSteps;
		}
		else 
		{
			fadeAmount = 0;
		}

		// Do It!
		
		previewTimer[previewImageID] = setInterval("previewElement('"+previewID+"', '"+previewImageID+"', "+previewCurrent+", "+startW+", "+previewChangeW+", "+startH+", "+previewChangeH+", "+hostX+", "+previewChangeX+", "+hostY+", "+previewChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'previewDoneIn(previewID)')", previewTime);		
		previewActive[previewImageID] = true; 
	}
}

// Preview it back out.
function previewOut(from, evt) 
{
	// Get shift key status.
	// IE events don't seem to get passed through the function, so grab it from the window.
	if (getShift(evt)) 
		tempSteps = previewSteps * 7;
	else 
		tempSteps = previewSteps;

	// Check to see if something is happening/open
	if (previewActive[previewImageID] != true) 
	{
		// Now, figure out where we came from, to get back there
		startX = parseInt(previewdiv.style.left);
		startY = parseInt(previewdiv.style.top);
		startW = previewimg.width;
		startH = previewimg.height;
		previewChangeX = previewOrigX[previewImageID] - startX;
		previewChangeY = previewOrigY[previewImageID] - startY;
		previewChangeW = previewOrigW[previewImageID] - startW;
		previewChangeH = previewOrigH[previewImageID] - startH;

		// Setup Preview
		previewCurrent = 0;

		// Setup Fade with Preview, If Requested
		if (includeFade == 1) 
		{
			fadeCurrent = 0;
			fadeAmount = (100 - 0) / tempSteps;
		}
		else
		{
			fadeAmount = 0;
		}

		// Do It!
		previewTimer[previewImageID] = setInterval("previewElement('"+previewID+"', '"+previewImageID+"', "+previewCurrent+", "+startW+", "+previewChangeW+", "+startH+", "+previewChangeH+", "+startX+", "+previewChangeX+", "+startY+", "+previewChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'previewDone(previewID, previewImageID)')", previewTime);	
		previewActive[previewImageID] = true;
	}
}

// Finished Previewing In
function previewDoneIn(previewdiv, previewImageID) 
{
	// Note that it's open
	previewOpen = true;
	previewdiv = document.getElementById(previewdiv);

	// Get keypresses
	document.onkeypress = getKey;
}

// Finished Previewing Out
function previewDone(previewdiv, previewImageID) 
{
	// No longer open
	previewOpen = false;

	// Clear stuff out, clean up
	previewOrigH[previewImageID] = "";
	previewOrigW[previewImageID] = "";
	document.getElementById(previewdiv).style.visibility = "hidden";
	previewActive[previewImageID] == false;

	// Stop getting keypresses
	document.onkeypress = null;
}

// Actually preview the element
function previewElement(previewdiv, previewImageID, previewCurrent, previewStartW, previewChangeW, previewStartH, previewChangeH, previewStartX, previewChangeX, previewStartY, previewChangeY, previewSteps, includeFade, fadeAmount, execWhenDone) 
{
	// Test if we're done, or if we continue
	if (previewCurrent == (previewSteps + 1)) 
	{
		previewActive[previewImageID] = false;
		clearInterval(previewTimer[previewImageID]);

		if (execWhenDone != "") 
			eval(execWhenDone);
	} 
	else 
	{
		// Do the Fade!
		if (includeFade == 1) 
		{
			if (fadeAmount < 0) 
				setOpacity(Math.abs(previewCurrent * fadeAmount), previewdiv);
			else 
				setOpacity(100 - (previewCurrent * fadeAmount), previewdiv);
		}
	  
		// Calculate this step's difference, and move it!
		moveW = cubicInOut(previewCurrent, previewStartW, previewChangeW, previewSteps);
		moveH = cubicInOut(previewCurrent, previewStartH, previewChangeH, previewSteps);
		moveX = cubicInOut(previewCurrent, previewStartX, previewChangeX, previewSteps);
		moveY = cubicInOut(previewCurrent, previewStartY, previewChangeY, previewSteps);
	
		document.getElementById(previewdiv).style.left = moveX + 'px';
		document.getElementById(previewdiv).style.top = moveY + 'px';
		previewimg.style.width = moveW + 'px';
		previewimg.style.height = moveH + 'px';
	
		previewCurrent++;
		
		clearInterval(previewTimer[previewImageID]);
		previewTimer[previewImageID] = setInterval("previewElement('"+previewdiv+"', '"+previewImageID+"', "+previewCurrent+", "+previewStartW+", "+previewChangeW+", "+previewStartH+", "+previewChangeH+", "+previewStartX+", "+previewChangeX+", "+previewStartY+", "+previewChangeY+", "+previewSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", previewTime);
        temp = "previewElement('"+previewdiv+"', '"+previewImageID+"', "+previewCurrent+", "+previewStartW+", "+previewChangeW+", "+previewStartH+", "+previewChangeH+", "+previewStartX+", "+previewChangeX+", "+previewStartY+", "+previewChangeY+", "+previewSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", previewTime		
	}
}

// Preview Utility: Get Key Press when image is open, and act accordingly
function getKey(evt) 
{
    if (!evt) 
        theKey = event.keyCode;
    else 
        theKey = evt.keyCode;

    if (theKey == 27) // ESC
        previewOut(this, evt);
}

////////////////////////////
//
// FADE Functions
//
function fadeOut(elem) 
{
	if (elem.id) 
		fadeElementSetup(elem.id, 100, 0, 10);
}

function fadeIn(elem) 
{
	if (elem.id)
		fadeElementSetup(elem.id, 0, 100, 10);	
}

// Fade: Initialize the fade function
var fadeActive = new Array();
var fadeQueue  = new Array();
var fadeTimer  = new Array();
var fadeClose  = new Array();
var fadeMode   = new Array();
function fadeElementSetup(previewImageID, fdStart, fdEnd, fdSteps, fdClose, fdMode) 
{
	if (fadeActive[previewImageID] == true) 
	{
		// Already animating, queue up this command
		fadeQueue[previewImageID] = new Array(previewImageID, fdStart, fdEnd, fdSteps);
	}
	else 
	{
		fadeSteps = fdSteps;
		fadeCurrent = 0;
		fadeAmount = (fdStart - fdEnd) / fadeSteps;
		fadeTimer[previewImageID] = setInterval("fadeElement('"+previewImageID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
		fadeActive[previewImageID] = true;
		fadeMode[previewImageID] = fdMode;
		
		if (fdClose == 1) 
			fadeClose[previewImageID] = true;
		else 
			fadeClose[previewImageID] = false;
	}
}

// Fade: Do the fade. This function will call itself, modifying the parameters, so
// many instances can run concurrently. Can fade using opacity, or fade using a box-shadow.
function fadeElement(previewImageID, fadeCurrent, fadeAmount, fadeSteps) 
{
    if (fadeCurrent == fadeSteps) 
    {
        // We're done, so clear.
        clearInterval(fadeTimer[previewImageID]);
        fadeActive[previewImageID] = false;
        fadeTimer[previewImageID] = false;

        // Should we close it once the fade is complete?
        if (fadeClose[previewImageID] == true) 
            document.getElementById(previewImageID).style.visibility = "hidden";
    
        // Hang on.. did a command queue while we were working? If so, make it happen now
        if (fadeQueue[previewImageID] && fadeQueue[previewImageID] != false) 
        {
            fadeElementSetup(fadeQueue[previewImageID][0], fadeQueue[previewImageID][1], fadeQueue[previewImageID][2], fadeQueue[previewImageID][3]);
            fadeQueue[previewImageID] = false;
        }
    } 
    else 
    {
        fadeCurrent++;

        // Set the opacity depending on if we're adding or subtracting (pos or neg)
        if (fadeAmount < 0) 
            setOpacity(Math.abs(fadeCurrent * fadeAmount), previewImageID);
        else 
            setOpacity(100 - (fadeCurrent * fadeAmount), previewImageID);

        // Keep going, and send myself the updated variables
        clearInterval(fadeTimer[previewImageID]);
        fadeTimer[previewImageID] = setInterval("fadeElement('"+previewImageID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
    }
}

// Utility: Set the opacity, compatible with a number of browsers. Value from 0 to 100.
function setOpacity(opacity, previewImageID) 
{

	var object = document.getElementById(previewImageID).style;

	// If it's 100, set it to 99 for Firefox.
	if ((navigator.userAgent.indexOf("Firefox") != -1) && (opacity == 100))
	    opacity = 99.9999;// This is majorly awkward

	// Multi-browser opacity setting
	object.filter = "alpha(opacity=" + opacity + ")"; // IE/Win
	object.opacity = (opacity / 100);                 // Safari 1.2, Firefox+Mozilla
}

function cubicInOut(t, b, c, d)
{
	if ((t/=d/2) < 1) 
        return c/2*t*t*t + b;
	return c/2*((t-=2)*t*t + 2) + b;
}

// Utility: Get the size of the window, and set windowWidth and windowHeight
// Credit to quirksmode.org
function getSize() 
{
	// Window Size
	if (self.innerHeight) 
	{ // Everyone but IE
		windowWidth     = window.innerWidth;
		windowHeight    = window.innerHeight;
		windowScroll    = window.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.clientHeight) 
	{ // IE6 Strict
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
		windowScroll = document.documentElement.scrollTop;
	}
	else if (document.body) 
	{ // Other IE, such as IE7
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
		windowScroll = document.body.scrollTop;
	}

	// Page size w/offscreen areas
	if (window.innerHeight && window.scrollMaxY) 
	{
		windowScrollWidth = document.body.scrollWidth;
		windowScrollHeight = window.innerHeight + window.scrollMaxY;
	}
	else if (document.body.scrollHeight > document.body.offsetHeight) 
	{ // All but Explorer Mac
		windowScrollWidth = document.body.scrollWidth;
		windowScrollHeight = document.body.scrollHeight;
	}
	else 
	{ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		windowScrollWidth = document.body.offsetWidth;
		windowScrollHeight = document.body.offsetHeight;
	}
}

// Utility: Get Shift Key Status
// IE events don't seem to get passed through the function, so grab it from the window.
function getShift(evt) 
{
	var shift = false;
	if (!evt && window.event) 
		shift = window.event.shiftKey;
	else if (evt) 
	{
		shift = evt.shiftKey;
		if (shift) 
		    evt.stopPropagation(); // Prevents Firefox from doing shifty things
	}
	return shift;
}

// Utility: Find the Y position of an element on a page. Return Y and X as an array
function findElementPos(elemFind)
{
    var elemX = 0;
    var elemY = 0;
    do 
    {
        elemX += elemFind.offsetLeft;
        elemY += elemFind.offsetTop;
    }
    while (elemFind = elemFind.offsetParent)

    return Array(elemX, elemY);
}

function insertPreviewHTML() 
{
	var inBody = document.getElementsByTagName("body").item(0);
	
    //wait animation
	var inWaitAnimBox = document.createElement("div");
	inWaitAnimBox.setAttribute('id', waitAnimID);
	inWaitAnimBox.style.position    = 'absolute';
	inWaitAnimBox.style.left        = '10px';
	inWaitAnimBox.style.top         = '10px';
	inWaitAnimBox.style.visibility  = 'hidden';
	inWaitAnimBox.style.zIndex      = '525';
	inBody.insertBefore(inWaitAnimBox, inBody.firstChild);
	
	var inWaitAnimImage = document.createElement("img");
	inWaitAnimImage.setAttribute('id', waitAnimImageID);
	inWaitAnimImage.setAttribute('src', ImagesURI+'wait_anim_1.png');
	inWaitAnimBox.appendChild(inWaitAnimImage);
	
		
	var inPreviewBox = document.createElement("div");
	inPreviewBox.setAttribute('id', previewID);
	
	inPreviewBox.style.position         = 'absolute'; 
	inPreviewBox.style.left             = '10px';
	inPreviewBox.style.top              = '10px';
	inPreviewBox.style.visibility       = 'hidden';
	inPreviewBox.style.zIndex           = '499';	
	inBody.insertBefore(inPreviewBox, inBody.firstChild);
	
	
	var inImage = document.createElement("img");
	inImage.onclick = function (event) { previewOut(this, event); return false; };	
	inImage.setAttribute('src', ImagesURI+'preview_spacer.gif');
	inImage.setAttribute('id', previewImageID);
	inImage.setAttribute('border', '0');
	inImage.style.display   = 'block';
	inImage.style.width     = '10px';
	inImage.style.height    = '10px';
	inImage.style.cursor    = 'pointer';
	inPreviewBox.appendChild(inImage);
}
