/**
	These two functions (addEvent and removeEvent) should be added to common.js
	- they are generally useful functions that could be used across the entire site
	when custom javascript is needed. The lightbox requires them for use.
**/
function addEvent( obj, type, fn )
{
	if (obj.addEventListener)
	{
		obj.addEventListener( type, fn, false );
	}
	else if (obj.attachEvent)
	{
		obj["e"+type+fn] = fn;
		obj[type+fn] = function() { return obj["e"+type+fn]( window.event ); };
		obj.attachEvent( "on"+type, obj[type+fn] );
	}
}

function removeEvent( obj, type, fn )
{
	if (obj.removeEventListener)
	{
		obj.removeEventListener( type, fn, false );
	}
	else if (obj.detachEvent)
	{
		obj.detachEvent( "on"+type, obj[type+fn] );
		obj[type+fn] = null;
		obj["e"+type+fn] = null;
	}
}

/**
	Gets the current scroll position of the window - might want to add
	to common.js? Not sure we'll use it elsewhere.
**/
var getScrollTop = function()
{
	var w = window.pageYOffset;
	var d = document.documentElement ? document.documentElement.scrollTop : 0;
	var b = document.body ? document.body.scrolltop : 0;
	
	var val = w || d || b;
	
	if (val)
	{
		return val;
	}
	else
	{
		return 0;
	}
};

/**
	Gets the height of the window - not the document, but the viewport. Again,
	may want to add to common.js.
**/
var getWindowHeight = function()
{
	var w = window.innerHeight;
	var d = document.documentElement ? document.documentElement.clientHeight : 0;
	var b = document.body ? document.body.clientHeight : 0;
	
	var val = w || d || b;
	
	if (val)
	{
		return val;
	}
	else
	{
		return 0;
	}
};

/**
    Gets the width of the window - not the document, but the viewport. Again,
    may want to add to common.js
**/
var getWindowWidth = function()
{
    var w = window.innerwidth;
    var d = document.documentElement ? document.documentElement.clientWidth : 0;
    var b = document.body ? document.body.clientWidth : 0;
    
    var val = w || d || b;
    
    if (val)
    {
        return val;
    }
    else
    {
        return 0;
    }
};

/**
    Call this function to initialize ALL lightbox elements on the page
    - lightbox elements are determined by links (<a> tags) with rel="lightbox".
    The href should be #id where id is the id of the element to be shown
    by that link.
    
    You can pass a parameters object to the function to customize its behavior:
        openCallBack: The function to be called after the lightbox opens
        closeCallBack: The function to be called after the lightbox closes
        sticky: Whether clicking outside the lightbox will close the lightbox - defaults to false
        blanketColor: The color of the blanket fade-in - defaults to '#FFF'
        
        ex: lb = lightbox({closeCallBack: function, sticky: true, blanketColor: '#000'});
        
    KNOWN ISSUE:
        If 'sticky' is false, checkboxes will not function within the lightbox in Internet Explorer
**/
var lightbox = function(p_params)
{
    var openCallBack;
    var closeCallBack;
    var sticky = false;
    var blanketColor = '#FFF';
    
    if (p_params)
    {
        if (p_params.hasOwnProperty('openCallBack') && typeof p_params.openCallBack === 'function')
        {
            openCallBack = p_params.openCallBack;
        }
        
        if (p_params.hasOwnProperty('closeCallBack') && typeof p_params.closeCallBack === 'function')
        {
            closeCallBack = p_params.closeCallBack;
        }
        
        if (p_params.hasOwnProperty('sticky') && typeof p_params.sticky === 'boolean')
        {
            sticky = p_params.sticky;
        }
        
        if (p_params.hasOwnProperty('blanketColor') && typeof p_params.blanketColor === 'string')
        {
            blanketColor = p_params.blanketColor;
        }
    }

	/**
		The blanket that covers the rest of the content while
		the lightbox is shown. There is only one.
	**/
	var blanket = document.getElementById('lightboxBlanket');
	if (!blanket)
	{
	    blanket = document.createElement('div');
	    blanket.id = 'lightboxBlanket';
	    blanket.style.position = 'absolute';
	    blanket.style.left = '0';
	    blanket.style.top = '0';
	    blanket.style.width = '100%';
	    blanket.style.height = '100%';
	    blanket.style.display = 'none';
	    blanket.style.backgroundColor = blanketColor;
	    blanket.style.filter = 'alpha(opacity=80)';
	    blanket.style.opacity = '0.8';
	    blanket.style.zIndex = '2000';
	}
	
	document.body.appendChild(blanket);
	
	/**
		Fades the blanket in
	**/
	var fadeBlanketIn = function()
	{
		var max = 70;
		var helper = function(p_opacity)
		{
			if (p_opacity < max)
			{
				blanket.style.opacity = p_opacity / 100;
				blanket.style.filter = 'alpha(opacity=' + p_opacity + ')';
				setTimeout(function() {  helper(p_opacity + 5); }, 3);
			}
			else
			{
				blanket.style.opacity = max / 100;
				blanket.style.filter = 'alpha(opacity=' + max + ')';
			}
		};
		
		helper(0);
	};

	/**
		The close link - there is only one, and it gets passed around
		between each of the lightboxes.
	**/
	var closeLink = document.getElementById('lightboxClose');
	if (!closeLink)
	{
	    closeLink = document.createElement('a');
	    var closeText = document.createTextNode('close');
	    closeLink.href = '#';
	    closeLink.className = 'lightboxClose';
	    closeLink.id = 'lightboxClose';
	    closeLink.style.display = 'block';
	    closeLink.style.clear = 'both';
	    closeLink.appendChild(closeText);
	}

	// Keep track of which lightbox is displayed
	var displayed;
	
	// A function to close the displayed lightbox - almost always called as an event handler
	var closeDisplayed = function(e)
	{
		if (displayed)
		{
			displayed.style.display = 'none';
			blanket.style.display = 'none';
			
			if (!sticky)
			{
			    removeEvent(document, 'click', closeDisplayed);
			}
			
			displayed = undefined;
			
			if (closeCallBack)
		    {
		        closeCallBack();
		    }
		}

		if (e && e.preventDefault) 
		{
			e.preventDefault();
		}
		else if (window.event && window.event.returnValue)
		{
			window.eventReturnValue = false;
		}
			
		return false;
	};
	
	// Add the 'close' event
	addEvent(closeLink, 'click', closeDisplayed);

    // Add a resize event, so the blanket doesn't get screwed up	
	addEvent(window, 'resize', function() {
        if (displayed)
        {
            blanket.style.width = getWindowWidth() + 'px';
            blanket.style.height = Math.max(displayed.offsetHeight + 60, Math.max(document.body.offsetHeight + 30, getWindowHeight())) + 'px';
        }
    });

	/**
		Makes a click handler for the rel="lightbox" links, and returns it
		This is where all the actual work happens.
	**/
	var makeClick = function(p_href)
	{
		/** Checking to see if the ID from p_href is valid **/
		var id = p_href.substring(p_href.indexOf('#') + 1);
		var elem = document.getElementById(id);

		if (elem)
		{
			elem.style.position = 'absolute';
			elem.style.top = '50%';
			elem.style.left = '50%';
			elem.style.zIndex = parseInt(blanket.style.zIndex, 10) + 1;
		
			/** The actual event handler **/
			return function(e) {
				/** close anything that's displayed **/
				closeDisplayed();
				
				/** display the blanket **/
				blanket.style.display = 'block';
				blanket.style.width = getWindowWidth() + 'px';
				fadeBlanketIn();
				
				/** display and position the actual lightbox element **/
				elem.style.display = 'block';
				
				var adjustedOffset;
				if (elem.offsetHeight > getWindowHeight())
				{
					// Element is bigger than the viewport
					adjustedOffset = ((getWindowHeight() / 2) - 30) * -1;
				}
				else
				{
					adjustedOffset = ((elem.offsetHeight / 2) - getScrollTop()) * -1;
				}
							
				elem.style.marginTop = adjustedOffset + 'px';
				elem.style.marginLeft = '-' + (elem.offsetWidth / 2) + 'px';
				elem.appendChild(closeLink);
				displayed = elem;

				/**
					If the user clicks anywhere on the document, other than the
					lightbox, it closes the lightbox.
				**/
				if (!sticky)
				{
				    addEvent(document, 'click', closeDisplayed);
				    
				    /**
					    Make sure that if the user clicks on the actual element,
					    it doesn't disappear - this stops the event bubble
				    **/
				    addEvent(elem, 'click', function(e) {
					    if (!e)
					    {
					        e = window.event;
					    }
    					
					    e.cancelBubble = true;
    					
					    if (e.stopPropagation)
					    {
					        e.stopPropagation();
					    }
    					
					    return false;
				    });
				}
				
				/** Set the blanket height after the element is displayed, to make sure we are
				getting accurate measurements **/
				blanket.style.height = Math.max(elem.offsetHeight + 60, Math.max(document.body.offsetHeight + 30, getWindowHeight())) + 'px';

				/**
					Stop event bubbling
				**/
				if (!e) 
				{
				    e = window.event;
				}
				
				e.cancelBubble = true;
				
				if (e.stopPropagation)
				{
				    e.stopPropagation();
				}

				/**
					Prevent the default action (i.e. following the link) for newer browsers
				**/
				if (e &&e.preventDefault) 
				{
					e.preventDefault();
				}
				else if (window.event && window.event.returnValue)
				{
					window.eventReturnValue = false;
				}
				
				if (openCallBack)
				{
				    openCallBack();
				}
				
				/**
					Prevent the default action (i.e. following the link) for older browsers
				**/
				return false;
			};
		}
		else
		{
			/**
				If no element with the given ID exists, use the default action
			**/
			return function() { return true; };
		}
	};

	/**
		Get all the anchors in the document, check to see if they're lightbox links,
		and if they are, make them a click handler via makeClick()
	**/
	var anchors = document.getElementsByTagName('a');
	var i = 0;

	for (i =0; i < anchors.length; i = i + 1)
	{
		if (anchors[i].rel === 'lightbox')
		{
			addEvent(anchors[i], 'click', makeClick(anchors[i].href));
		}
	}
	
	/**
	    Return an object to control various aspects of the lightbox
	        - setCloseCallBack - sets a function to be run when the lightbox is closed
	        - setOpenCallBack - sets a function to be run when the lightbox is opened
	        - close - closes the lightbox
	        - getDisplayed - gets the element currently displayed in the lightbox
	        - setBlanketColor - changes the color of the blanket
	**/
	var controlObject = {
	    setCloseCallBack: function(p_callback)
	    {
	        if (typeof p_callback === 'function')
	        {
	            closeCallBack = p_callback;
	            return true;
	        }
	        
	        return false;
	    },
	    setOpenCallBack: function(p_callback)
	    {
	        if (typeof p_callback === 'function')
	        {
	            openCallBack = p_callback;
	            return true;
	        }
	        
	        return false;
	    },
	    close: function()
	    {
	        closeDisplayed();
	    },
	    getDisplayed: function()
	    {
	        return displayed;
	    },
	    setBlanketColor: function(p_color)
	    {
	        if (typeof p_color === 'string')
	        {
	            blanket.style.backgroundColor = p_color
	        }
	    }
    };
    
    return controlObject;
};
