//Code to grab the FrontPage database news items via JSON and display them on the library home page

//define some constants - yeah, I know there are no real constants in JS, but it has become a habit 
//var CONST_NewsfeedCGILocation="Newsfeed_Data.json"; //"clean" dummy data for testing
var CONST_NewsfeedCGILocation="_design/scripts/"+"Newsfeed_JSON_Export.cfm"; //"Newsfeed_JSON_Export.cfm";
var CONST_NewsfeedDisplayDiv="spotlight";
var CONST_NewsfeedHeaderItemDiv="NewsHeader";
var CONST_NewsfeedContentItemDivBaseName="NewsItem";
var CONST_NewsfeedContentItemTempDiv=CONST_NewsfeedContentItemDivBaseName+"Temp";
var CONST_NewsfeedThrobberImg='NewsThrobber'; //data gets loaded so fast, it might not be worth having this
var CONST_NewsContainerHighlightColor='#'+'ffffcc';
var CONST_DebugDiv=""; //give it a name if you want to enable it

//I don't like defining globals like this, but it is required for dealing with the looping animations in jQuery
var Global_CurrentNewsItem=0;
var Global_MaxNewsItem=0;
var Global_FadeDuration=1000;
var Global_FadePause=3000;
var Global_FadeBetweenPause=0;
var Global_NewsContainerColor=''; //this gets populated later

//call to init all the required functions to display the newsfeed items
//one call starts them all
function DoInitNewsfeed() {
	FetchNewsfeedData(20); //fetch up to 20 results
} //end function

//is this really needed here give the access time?
function SetNewsfeedThrobberStatus(bIsVisible) {
	if(bIsVisible == 1) {
		//show the throbber
		$('#'+CONST_NewsfeedThrobberImg).fadeOut("slow");
	} else {
		//all done, so hide the throbber
		$('#'+CONST_NewsfeedThrobberImg).fadeIn("fast");
	} //end if
	
	return 1;
}// end function

//This function rotates the news item display (forever)
function FadeInOutNewsItem() {
	//check the global item var to see if we are still in range, reset if not
	if(Global_CurrentNewsItem>Global_MaxNewsItem) {Global_CurrentNewsItem=0;}

	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text("FadeInOutNewsItem, Q="+$targetNewsItem.queue("fx").length);}
	
	//set the animations for the fade in/hold/fade out
	$targetNewsItem.animate({"opacity": "show"}, { delay: 0, duration: Global_FadeDuration, queue: true });
	$targetNewsItem.animate({delay: Global_FadePause}, { delay: 0, duration: Global_FadePause, queue: true });
	$targetNewsItem.animate({"opacity": "hide"}, { delay: 0, duration: Global_FadeDuration, queue: true });
	
	//index the global item var
	Global_CurrentNewsItem=Global_CurrentNewsItem+1;

	//queue the final pause, then call the function again - looping forever
	$targetNewsItem.animate({delay:Global_FadePause}, FadeInOutNewsItem);
} //end function

//This function starts the whole fade in/hold/fade out process
//Same as the code above does, but it is broken down into a number of smaller functions that can be interrupted
function FadeInNewsItem() {
	//check the global item var to see if we are still in range, reset if not
	if(Global_CurrentNewsItem>=Global_MaxNewsItem) {Global_CurrentNewsItem=0;}

	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text("FadeInNewsItem, Q="+$targetNewsItem.queue("fx").length);}
	
	//set the animations for the fade in/hold/fade out
	$targetNewsItem.animate({"opacity": "show"}, { delay: 0, duration: Global_FadeDuration, queue: true });
	$targetNewsItem.animate({delay: 0}, HoldNewsItem);
} //end function

//This function halts any current animation process and does a fast display of the current news item
function ShowNowNewsItem() {
	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text(">>ShowNowNewsItem, Q="+$targetNewsItem.queue("fx").length);}
	
	//stop and move to the end of the current animation
//	$targetNewsItem.stop(true, true); //.stop(clearQueue, jumpToEnd)
//	$targetNewsItem.clearQueue(); //.clearQueue([queueName]);
	
	//quick fade in the news item and then do nothing further
	$targetNewsItem.animate({"opacity": "show"}, { delay: 0, duration: (Global_FadeDuration/4), queue: true });	
	//$targetNewsItem.animate({"opacity": "show"}, { delay: 0, duration: 100, queue: true });	
} //end function


//This function just sets pause in the animation, then calls the fade out process
function HoldNewsItem() {
	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text("HoldNewsItem, Q="+$targetNewsItem.queue("fx").length);}

	//queue up the pause in animation and the fade out function call
	$targetNewsItem.animate({delay: Global_FadePause}, { delay: 0, duration: Global_FadePause, queue: true });
	$targetNewsItem.animate({delay: 0}, FadeOutNewsItem);
} //end function

//This function fades out the current news item, then calls the IndexNewsItem function
function FadeOutNewsItem() {
	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text("FadeOutNewsItem, Q="+$targetNewsItem.queue("fx").length);}

	//queue up the fade out and the index function call
	$targetNewsItem.animate({"opacity": "hide"}, { delay: 0, duration: Global_FadeDuration, queue: true });
	$targetNewsItem.animate({delay: 0}, IndexNewsItem);
} //end function

//This function once the fade out animation is finished, then indexes the news item so that the next item can be faded in
function IndexNewsItem() {
	//this simplifies the next few lines
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	if(CONST_DebugDiv!='') {$("#"+CONST_DebugDiv).text("IndexNewsItem, Q="+$targetNewsItem.queue("fx").length);}

	//index the global news item var, then start the process again
	Global_CurrentNewsItem=Global_CurrentNewsItem+1;
	$targetNewsItem.animate({delay:0}, FadeInNewsItem);
} //end function

//wrapper the ShowNowNewsItem triggered from the mouseover event
function ShowNowNewsItemWrapper() {
	//record the news item container color and then set it with the highlight color
	Global_NewsContainerColor=$('#'+CONST_NewsfeedDisplayDiv).css("backgroundColor");
	$('#'+CONST_NewsfeedDisplayDiv).css("backgroundColor", CONST_NewsContainerHighlightColor);
	
	//start the news item hold process if there is more than one news item to show
	if(Global_MaxNewsItem>1) {
		//hack to prevent events from stacking up on mouse events
		var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
		$targetNewsItem.stop(true, true); //.stop(clearQueue, jumpToEnd)
		$targetNewsItem.clearQueue(); //.clearQueue([queueName]);
		ShowNowNewsItem();
	} //end more than one news item check if
} //end function

//wrapper the ShowNowNewsItem triggered from the mouseover event
function HoldNewsItemWrapper() {
	//restore the news item container color to what it once was
	$('#'+CONST_NewsfeedDisplayDiv).css("backgroundColor", Global_NewsContainerColor);
	
	//start the show again if there is more than one news item to show
	if(Global_MaxNewsItem>1) {
		//hack to prevent events from stacking up on mouse events
		//this section really needed for OnClick type events and not so much on MouseOut type events
		var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
		$targetNewsItem.stop(true, true); //.stop(clearQueue, jumpToEnd)
		$targetNewsItem.clearQueue(); //.clearQueue([queueName]);
		HoldNewsItem();
	} //end more than one news item check if
} //end function

//In the event that we have only one news item, we just fade it up, then do nothing further
function FadeInSingleNewsItem() {
	//set the animations for the fade in only
	var $targetNewsItem=$('#'+CONST_NewsfeedContentItemDivBaseName+(Global_CurrentNewsItem));
	$targetNewsItem.animate({"opacity": "show"}, { duration: Global_FadeDuration, queue: true });
} //end function

//if we got news items back, this is where we process them
function ShowNewsfeedData(data) {
	//here's the problem with the rotating content...
	//the target div element has no defined height and width, and because the content varies
	//in length, the current displayable news item might be shorter than the one to follow it.
	//So, what has to happen is that the content needs to be checked so that the content with
	//the longest content defines the length for all the news items to be displayed.
	//
	//this will work great until someone resizes the browser and the height will need to be
	//calculated again.
	
	//this location is created via Apache directive, so don't look for this directory via the file system
	//var recImgBaseLocation='http://www.lib.uconn.edu/uploads/frontpage/';
	var recImgBaseLocation='/_design/scripts/Newsfeed_Serve_Image.cfm?id=';
	//var recImgBaseLocation='http://staging.lib.uconn.edu/uploads/frontpage/';
	
	var recHeaderText='';
	var headerHeight=0;
	var recMaxHeight=0;
	var recMaxHeightId=0;
	var lastDivInserted='';
	var targetLinkDest='_self';
	Global_MaxNewsItem=data.Content.length;
	
	//do we have anything to work with? Sometimes we might not
	if(Global_MaxNewsItem==undefined) {
		//no?, ok, then just hide the news panel so we don't look foolish
		if(CONST_DebugDiv!='') {
			$("#"+CONST_NewsfeedDisplayDiv).after('<div id="'+CONST_DebugDiv+'"></div>');
			$("#"+CONST_DebugDiv).text("No records to show");
		} //end debug if
		
		//hide the display since there is nothing to see
		$('#'+CONST_NewsfeedDisplayDiv).css('display', 'none');
	} else {
		//yeah, we got at least one items, so start the display process
		
		//create the common header elements that will not change
		recHeaderText=recHeaderText+'<div id="'+CONST_NewsfeedHeaderItemDiv+'">\n';
		recHeaderText=recHeaderText+'<h4>News</h4>\n';
		recHeaderText=recHeaderText+'<span id="controls">';
		recHeaderText=recHeaderText+'<a href="/about/news" title="Go to the news page" target="'+targetLinkDest+'">&gt;&gt;More News</a>';
		recHeaderText=recHeaderText+'<a href="/webapps/eventsfeed.xml" title="Link to RSS version" target="'+targetLinkDest+'">';
		recHeaderText=recHeaderText+'<img src="/_design/images/rss.png" alt="rss feed">';
		recHeaderText=recHeaderText+'</a>';
		recHeaderText=recHeaderText+'</span>\n';
		recHeaderText=recHeaderText+'</div>\n';
	
		//add it to CONST_NewsfeedDisplayDiv 
		$('#'+CONST_NewsfeedDisplayDiv).html(recHeaderText+'\n');
	
		//get the height of the header for later
		headerHeight=$('#'+CONST_NewsfeedHeaderItemDiv).height();	
		
		//Create a hidden, temp div to use for height calculations
		//to be removed after all the content is loaded and checked for size
		$('#'+CONST_NewsfeedHeaderItemDiv).after('<div id="'+CONST_NewsfeedContentItemTempDiv+'"></div>');
	
		//set lastDivInserted to use later
		lastDivInserted=CONST_NewsfeedHeaderItemDiv;
	
		//walk through all the content items
		for (var recIndex=0;recIndex<Global_MaxNewsItem;recIndex=recIndex+1) {
			//reset the item content var
			var recContentText='';
			
			//create the div to hold the record
			recContentText=recContentText+'<div id="'+CONST_NewsfeedContentItemDivBaseName+recIndex+'" class="NewsItemContainer">\n';
	
			//crerate the new content item
			//recText=recText+''+data.Content[recIndex].Id+'<br/>\n';
			//recText=recText+''+data.Content[recIndex].Campus+'<br/>\n';
			var LinkText=decode64(data.Content[recIndex].Link);
			var BylineText=decode64(data.Content[recIndex].Byline);
			var TitleText=decode64(data.Content[recIndex].Title);
			var BlurbText=decode64(data.Content[recIndex].Blurb);
			
			if(LinkText!='') {recContentText=recContentText+'<a href="'+LinkText+'" target="'+targetLinkDest+'">';}
			//recContentText=recContentText+'<h5>'+TitleText+'</h5>\n';
			recContentText=recContentText+'<div class="BlurbTitle">'+TitleText+'</div>\n';
			if(LinkText!='') {recContentText=recContentText+'</a>\n';}
			//recContentText=recContentText+'<p>Display start: '+data.Content[recIndex].Start+'</p>\n';
			//recContentText=recContentText+'<p>Display end: '+data.Content[recIndex].End+'</p><br/>\n';
			if(data.Content[recIndex].Image!='') {
				if(LinkText!='') {recContentText=recContentText+'<div class="BlurbImage"><a href="'+LinkText+'" target="'+targetLinkDest+'">';}
				//recContentText=recContentText+'<img src="'+recImgBaseLocation+data.Content[recIndex].Image+'" alt="'+TitleText+'" align="right" border="0">';
				//recContentText=recContentText+'<img src="'+recImgBaseLocation+data.Content[recIndex].Id+'" align="right" border="0">';
				recContentText=recContentText+'<img src="'+recImgBaseLocation+data.Content[recIndex].Id+'">';
				if(LinkText!='') {recContentText=recContentText+'</a></div>\n';}
			} //end image check if
			//recContentText=recContentText+'<p style="font-size: 85%;">'+BylineText+'</p>\n';
			//recContentText=recContentText+'<p style="text-align: left; font-size: 85%;">'+BlurbText+'<br/></p>\n';
			//recContentText=recContentText+'<p style="text-align: right; font-size: 85%; color: blue; font-style: italic;">'+'';
			recContentText=recContentText+'<div class="BlurbBylineText">'+BylineText+'</div>\n';
			recContentText=recContentText+'<div class="BlurbContentText">'+BlurbText+'<br/></div>\n';
			recContentText=recContentText+'<div class="BlurbLinkText">'+'';
			if(LinkText!='') {recContentText=recContentText+'<a href="'+LinkText+'" title="Tell me more" target="'+targetLinkDest+'"><i>More information...</i></a>';} //end link check if
			recContentText=recContentText+'</div>\n';
			
			//close up the record div
			recContentText=recContentText+'</div>\n';
			
			//add it to CONST_NewsfeedPreloadDiv
			//CONST_NewsfeedContentItemTempDiv
			$('#'+CONST_NewsfeedContentItemTempDiv).html(recContentText);
			
			//check the height of the current item div to see if we found a new max
			if($('#'+CONST_NewsfeedContentItemTempDiv).height()>recMaxHeight) {
				recMaxHeight=$('#'+CONST_NewsfeedContentItemTempDiv).height();
				recMaxHeightId=recIndex;
			} //end height check if
			
			//now that we have a height, hide it before moving it
			$('#'+CONST_NewsfeedContentItemDivBaseName+recIndex).css('display', 'none');
			
			//mode the item html using a var rather thna directly or jQuery passes a bunch of garbage
			var tempHTML=$('#'+CONST_NewsfeedContentItemTempDiv).html();
			$('#'+lastDivInserted).after(tempHTML+'\n');
			
			//note lastDivInserted to use the next time around
			lastDivInserted=CONST_NewsfeedContentItemDivBaseName+recIndex;
		} //end record for
		
		//set the height of CONST_NewsfeedDisplayDiv based on the largest observed height and also include the height of the news header, if needed
		if($('#'+CONST_NewsfeedDisplayDiv).css('height')<headerHeight+recMaxHeight) {
			$('#'+CONST_NewsfeedDisplayDiv).css('height', headerHeight+recMaxHeight);
		} //end if
	
		if(CONST_DebugDiv!='') {
			$("#"+CONST_NewsfeedDisplayDiv).after('<div id="'+CONST_DebugDiv+'"></div>');
			$("#"+CONST_DebugDiv).text("Debug enabled - "+Global_MaxNewsItem+" items to display");
		} //end debug if
	
		//spawn the code to do the actual rotation of the inews items here
		if(Global_MaxNewsItem>=2) {
			//if we have more than one item, we need to rotate them
			//start the show
			FadeInNewsItem();
		} else {
			//if we only have one item, just fade it in and then do nothing else
			FadeInSingleNewsItem();
		} //end function
	
		//next, set the mouseover events so people can pause the news items if they are rotating
		//this needs to be done AFTER the display process starts
		//if there is only one item, just do the highlight only
		$('#'+CONST_NewsfeedDisplayDiv).mouseenter(ShowNowNewsItemWrapper);
		$('#'+CONST_NewsfeedDisplayDiv).mouseleave(HoldNewsItemWrapper);
		
		//add a final onclick event to start things moving again when links are clicked
		//this can cause problems with animation queue stacking, so clear the animation queue at end of fade process
		$('#'+CONST_NewsfeedDisplayDiv).click(HoldNewsItemWrapper); 
	} //end we got somthing to display check if
	return 1;
} //end function

function FetchNewsfeedData() {
	//reqest the data from the server
	$.ajax({
		url: CONST_NewsfeedCGILocation,
		success: function(data) {
			//need to preprocess the data to remove the leading spaces and tabs, then convert into a JS data array
			//the spaces are the result of using ColdFusion code to generate the JSON
			data=data.replace(/^\s+\n/gim, '\n');
			data=data.replace(/\n+/gim, '\n');

			//now parse the string and hope for the best
			var cleanedData=jQuery.parseJSON(data);

			//we got data, so show it
			$('#'+CONST_NewsfeedDisplayDiv).css('display', 'block');
			ShowNewsfeedData(cleanedData);
			SetNewsfeedThrobberStatus(0);
		}, //end success handling
		error: function(xhr, ajaxOptions, thrownError) {
			//oh dear, this didn't go as expected
			$('#'+CONST_NewsfeedDisplayDiv).text(xhr.status+'<br/>'+thrownError);
			
			//in the event of an error, just hide the newsfeed continer and pretend nothing happened after first inserting the error message
			$('#'+CONST_NewsfeedDisplayDiv).css('display', 'none');
		} //end error handling
	}); //end ajax handling
	
	//return 1;
} //end function



//code below here to be moved into another file


//function to set the search tab content on the library home page
//this code assumes jQuery is already loaded at some point
function MakeTabeActive(targetTab) {
     //need to validate input here
     
     //first, disable all of the tabs
     $('#WCL').css('display', 'none');
     $('#WCLTab').removeClass('active');
     $('#homer').css('display', 'none');
     $('#homerTab').removeClass('active');
     $('#ejournals').css('display', 'none');
     $('#ejournalsTab').removeClass('active');
     $('#databases').css('display', 'none');
     $('#databasesTab').removeClass('active');
     
     //next, enable only the targeted one
     $('#'+targetTab).css('display', 'block');
     $('#'+targetTab+'Tab').addClass('active');

     return 1;
} //end function



//function to toggle a block element item display to visible or hidden
function ShowHideItem(targetItem) {
	//need to validate input here
	
	if($('#'+targetItem).css('display')=='none') {
		$('#'+targetItem).css('display', 'block');
	} else {
		$('#'+targetItem).css('display', 'none');
	} //end display check if
	
	return 1;
} //end function


//function to decode strings to base 64 - needed for passing text that might have "'" and "&" chars via URI params
//http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
function decode64(input) {
	if (input == "") {return "";}
	var keyStr = "ABCDEFGHIJKLMNOP" +
			     "QRSTUVWXYZabcdef" +
			     "ghijklmnopqrstuv" +
			     "wxyz0123456789+/" +
			     "=";
	var output = "";
	var chr1, chr2, chr3 = "";
	var enc1, enc2, enc3, enc4 = "";
	var i = 0;
	// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
	var base64test = /[^A-Za-z0-9\+\/\=]/g;
	if (base64test.exec(input)) {
	alert("There were invalid base64 characters in the input text.\n" +
	"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
	"Expect errors in decoding.");
	}
	input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
	do {
		enc1 = keyStr.indexOf(input.charAt(i++));
		enc2 = keyStr.indexOf(input.charAt(i++));
		enc3 = keyStr.indexOf(input.charAt(i++));
		enc4 = keyStr.indexOf(input.charAt(i++));
		chr1 = (enc1 << 2) | (enc2 >> 4);
		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
		chr3 = ((enc3 & 3) << 6) | enc4;
		output = output + String.fromCharCode(chr1);
		if (enc3 != 64) {
			output = output + String.fromCharCode(chr2);
		} //end if
		if (enc4 != 64) {
			output = output + String.fromCharCode(chr3);
		} //end if
		chr1 = chr2 = chr3 = "";
		enc1 = enc2 = enc3 = enc4 = "";
	} while (i < input.length);

	return unescape(output);
} //end function
