/*
              ######---      B u l l e t i n     o b j e c t      ---######

The Bulletin object uses the same global Event array variable "evArray" dropped in event.js as used by the Calendar object. 
Each Event which has a non-zero bulletin entry attribute "bentry=99 will appear in the bulletin. The bulletin will display
Events according to date and priority. All Events with dates will appear first by date. All non-dated events with a higher bentry value
will appear 1st.

An ID is generated with the evArray index. e.g. bulletin.html#E52 would be the 53rd entry (we start with 0) in evArray.  At some future time, this may be accessible. it is not right now because of the dynamic nature of the html. Instead we are using overlib tooltips which works very nicely to display content.
*/

// ********************************************************
/*
The global variable VPAST="NO" will turn off the date display in the bulletin for items whose dates have gone by, and subsequently move the entry below other entries.  This is useful when you want to keep a multi-date event in the bulletin, without affecting the starting date for the calendar.
*/
var  VPAST = "NO";

/*
The global variable TODAY is today's date. It will be used to determine whether an event should display in the bulletin. 
*/
var TODAY = new Date();

// ********************************************************


function Bulletin()
{ 
//***  Bulletin properties     ***
	this.idarray    = new Array();		//array holding the ID of each event used in bulletin
	this.bullarray = new Array(); 	 	//array of events that comprise the bulletin
	this.html = '';				//html which displays the bulletin

//***  Bulletin methods***
	this.build = buildBulletin;		//mainline build
	this.getEntries = getEntries;
	this.pastDate = pastDate;
	this.sortEntries = sortEntries;
	this.displayin = showBulletin;
	this.positionOkay = positionOkay;
	this.swapEntries = swapEntries;
}

/*   ######---  buildBulletin() Method   ---###### */
function buildBulletin()
{
        var monthname = new Array( 'January', 'February', 'March', 'April', 'May', 'June', 
		'July', 'August', 'September', 'October', 'November', 'December'); 
	this.getEntries();
	this.sortEntries(0,this.bullarray.length-1);	
	this.html =  '<table class=bulletin>';
	for (i = 0; i < this.bullarray.length; i++)
	{
		this.html += '<tr><td><p><em class="bulletin"><a name=E'+this.idarray[i]+'>&#134;&nbsp;</a>';
		this.html += this.bullarray[i].sdesc+'</em></td>';

		if (this.bullarray[i].year != "")
		{
			var tdate = new Date (this.bullarray[i].year, this.bullarray[i].month, this.bullarray[i].day);
			this.html += '<td  style="text-align:right"><em>'+monthname[tdate.getMonth()] + " "+tdate.getDate() + ", "+tdate.getFullYear()+'</em></td>';
		}
		else
		{
			this.html += '<td> &nbsp; </td>';
		} 
		this.html += '<tr><td colspan=2>'+this.bullarray[i].ldesc+'</td></tr>';
		this.html += '<tr><td colspan=2>&nbsp;</td></tr>';
	};
	this.html += '</table>';
};


/*   ######---  showBulletin(<Div ID=?>) Method   ---###### */
function showBulletin(DivID) 
{
	if (document.layers)     // old Netscape 4.xx
	{
		document.layers[DivID].document.write(this.html);
		document.layers[DivID].document.close();
	} else	{
		var refNode = document.getElementById(DivID);
		if (document.all)   //MSIE
		{
			refNode.innerHTML = this.html;
		}
		else  // NS6+ 
		{	
			var range = document.createRange();
			range.selectNodeContents(refNode);
			range.deleteContents();
			var cfrag = range.createContextualFragment(this.html);
			refNode.appendChild(cfrag);
		};
	};
};



/*    ######--- the getEntries method retrieves all active applicable entries from evArray.   ---###### 
To be applicable, it must have a long description and either a specific date or a non-zero(non null) bentry attribute. */


function getEntries() 
{
	var b_idx = 0;				//the bulletin array index
        for (i=0; i < evArray.length; i++)
	{
		if ( VPAST == "NO" && this.pastDate(evArray[i]) )
				evArray[i].ldesc = "";
		if (evArray[i].ldesc != "")
		{
			if (evArray[i].bentry != 0)
			{
				this.bullarray[b_idx] = new Event();
				this.bullarray[b_idx].month = evArray[i].month;
				this.bullarray[b_idx].day = evArray[i].day;
				this.bullarray[b_idx].year = evArray[i].year;
				this.bullarray[b_idx].sdesc = evArray[i].sdesc;
				this.bullarray[b_idx].ldesc = evArray[i].ldesc;
				this.bullarray[b_idx].bentry = evArray[i].bentry;
				this.idarray[b_idx] = i;
				b_idx++;
			};				

		};
	};

};



/*    
######--- VPAST = "NO" shuts off display of past dates in the bulletin.

*/


function pastDate(Event) 
{
	if (Event.year == "") 
	   return false;
	var chkDate = new Date(Event.year,Event.month,Event.day);
	if (chkDate.valueOf() < TODAY.valueOf())	
	{
		return true;
	} else {
		return false;
	};
};



/* QuickSort Algorithm to sort bulletin */
      
function sortEntries(Lo0, Hi0) 
{
 	var lo = Lo0; 
	var hi = Hi0;
	var pivot = new Event(); 

	if (lo >= hi) 
	{ 
		return; 
	} 

	if( lo == hi - 1 ) 
	{ 
	/* sort a two element list by swapping if necessary */ 
		if (!this.positionOkay(this.bullarray[lo], this.bullarray[hi])) 
		{ 
			this.swapEntries(lo,hi); 
		} 
		return; 
	};

	// find the midpoint and swap it to the end...
	var pix = Math.floor((lo + hi) / 2);
	var pivot = this.bullarray[pix]; 
	this.bullarray[pix] = this.bullarray[hi]; 
	this.bullarray[hi] = pivot;  

	while( lo < hi ) 
	{ 
	/* Search forward from this.bullarray[lo] until an element is found that needs swapping with the pivot or lo >= hi */ 
		while (this.positionOkay(this.bullarray[lo], pivot) && lo < hi) 
		{ 
			lo++; 
		}; 

	/* Search backward from this.bullarray[hi] until element is found that is less than the pivot, or lo >= hi */ 
		while (this.positionOkay(pivot, this.bullarray[hi]) && lo < hi ) 
		{ 
			hi--; 
		}; 


	/* Swap elements this.bullarray[lo] and this.bullarray[hi] */ 
		if( lo < hi ) 
		{ 

			this.swapEntries(lo,hi);
 		}
	}

	/* Put the median in the "center" of the list */ 
	this.bullarray[Hi0] = this.bullarray[hi]; 
	this.bullarray[hi] = pivot; 

	
	this.sortEntries(Lo0, lo-1);
	this.sortEntries(hi+1, Hi0);
}	


		
/* ======================================================== */
/* 
This function determines if there is no need to swap to set the lo - hi pointer settings.
If something is in place, it will return 1 (true- no need to swap).
High priority comes first. then equal priority with an earlier date. lastly, undated items.   
*/

function positionOkay(eventi, eventj)
{

	if (eventi.bentry > eventj.bentry)				//i is higher priority; (no need to swap)
		return 1;                  

	if (eventi.bentry < eventj.bentry)				//i is lower priority (swap)
		return 0;                  

	/* -- equal priority items    -- check if date is present  */
	if (eventi.year == "" && eventj.year != "")			//no datei but datej present (swap)
		return 0;

        /* if two dates are present compare the two dates   */
	if ((eventi.year != "") && (eventj.year != ""))
	{ 
		var datei = new Date (eventi.year, eventi.month, eventi.day);
		var datej = new Date (eventj.year, eventj.month, eventj.day);

		if (datej.valueOf() < datei.valueOf())			//datej is sooner than datei
			return 0;
	}
	return 1;	 
}

		
/* ======================================================== */

function swapEntries(i,j)
{
	var hold_idx = 0;
	var hold_event = new Event();

	hold_event = this.bullarray[j];
	this.bullarray[j] = this.bullarray[i];
	this.bullarray[i] = hold_event;
	hold_idx = this.idarray[i]; 
	this.idarray[i] = this.idarray[j];
	this.idarray[j] = hold_idx;
}

