//= Copyright 2003, Peter A. Curran. All rights reserved.

// The following array lists the dates of Easter for a series of years,
// starting at the specified base year. Dates can be added as needed.
// Dates can also be removed, if the base year is changed
// appropriately.
baseYr = 2000;
hourLength = (60 * 60 * 1000);
dayLength = (24 * hourLength);
Easters = ["April 23, 2000",
	   "April 15, 2001",
	   "March 31, 2002",
	   "April 20, 2003",
	   "April 11, 2004",
	   "March 27, 2005",
	   "April 16, 2006",
	   "April 8,  2007",
	   "March 23, 2008",
	   "April 12, 2009",
	   "April 4,  2010",
	   "April 24, 2011",
	   "April 8, 2012",
	   "March 31, 2013",
	   "April 20, 2014",
	   "April 5, 2015",
	   "March 27, 2016",
	   "April 16, 2017",
	   "April 1, 2018",
	   "April 21, 2019",
	   "April 12, 2020",
	   "April 4, 2021",
	   "April 17, 2022",
	   "April 9, 2023",
	   "March 31, 2024"];

// The following array will be set to a selected series of significant
// liturgical dates.
dateYear = 0;
LitDates = new Array(17);

// Determine a set of liturgically significant dates, assigning them to the
// array LitDates. The parameter is the date (actually, only the year matters)
// for which the dates are wanted. If the parameter is omitted, the current
// date is used. If the resulting date is outside of the range for which
// data is available, an alternate is used.
function setLitDates (dt)
{
	if (arguments.length <= 0)
		dt = new Date();
	yr = dt.getFullYear();
	if (yr < baseYr)
		yr = baseYr;
	else if ((yr - baseYr) >= Easters.length)
		yr = baseYr + Easters.length - 1;

	if (dateYear != yr) {
		dateYear = yr;
		easter = new Date(Easters[yr - baseYr]);

		LitDates[0] = new Date(yr-1, 11, 31);	// before New Year's Day
		LitDates[1] = new Date(yr, 0, 7);	// day after Epiphany
		LitDates[2] = adjustDate(easter, -46);  // Ash Wednesday
		while (LitDates[2].getDay() != 3)	//  (adj. for Leap Year)
			LitDates[2] = adjustDate(LitDates[2], 1);
		LitDates[3] = adjustDate(LitDates[2], 1); // day after Ash Wed.
		LitDates[4] = adjustDate(easter, -7);   // Palm Sunday
		LitDates[5] = adjustDate(easter, -2);	// Good Friday
		LitDates[6] = easter;			// Easter
		LitDates[7] = adjustDate(easter, 1);    // day after Easter
		LitDates[8] = adjustDate(easter, 49);	// Pentecost
		LitDates[9] = adjustDate(easter, 50);	// day after Pentecost
		LitDates[10] = new Date(yr, 10, 1);	// All Saint's Day
		LitDates[11] = new Date(yr, 10, 2);	// All Saint's Day + 1
		LitDates[12] = new Date(yr, 10, 27);	// Earliest 1st Sun of Advent
		while (LitDates[12].getDay() != 0)      //     (adjust to Sunday)
			LitDates[12] = adjustDate(LitDates[12], 1);
		LitDates[13] = adjustDate(LitDates[12], 14); // 3rd Sunday of Advent
		LitDates[14] = adjustDate(LitDates[13], 7); // 4th Sunday of Advent
		LitDates[15] = new Date(yr, 11, 25);	// Christmas
		LitDates[16] = new Date(yr+1, 0, 1);	// New Year's
	}
}

// Calculate a date a specified number of days after (or before, if negative)
// the base date. If the adjustment period crosses daylight savings, an adjustment
// must be made to the time.
function adjustDate (dt, delta)
{
	rslt = new Date(dt.valueOf() + (delta * dayLength));

	h1 = dt.getHours();
	h2 = rslt.getHours();
	if (h1 != h2) {
		d = h1 - h2;
		if (d > 12)
			d = 24 - d;
		else if (d < -12)
			d = 24 + d;
		rslt = new Date(rslt.valueOf() + (d * hourLength));
	}

	return rslt;
}

// Return the specified date (or today, by default) as the number of the
// day in the year.
function dayInYear (dt)
{
	if (arguments.length <= 0)
		dt = new Date();
	return Math.floor((dt.valueOf()
			   - (new Date(dt.getFullYear(), 0, 1)).valueOf()
			   + (12*hourLength)) / dayLength);
}


// Debug function
// Dump the list of liturgical dates.
/*#*/function showDates ()
/*#*/{
/*#*/	setLitDates();
/*#*/	Log.log("End of year: " + LitDates[0].toString());
/*#*/	Log.log("After Epiphany: " + LitDates[1].toString());
/*#*/	Log.log("Ash Wed: " + LitDates[2].toString());
/*#*/	Log.log("Ash Thurs: " + LitDates[3].toString());
/*#*/	Log.log("Palm Sun: " + LitDates[4].toString());
/*#*/	Log.log("Good Fri: " + LitDates[5].toString());
/*#*/	Log.log("Easter: " + LitDates[6].toString());
/*#*/	Log.log("Easter+1: " + LitDates[7].toString());
/*#*/	Log.log("Pentecost: " + LitDates[8].toString());
/*#*/	Log.log("Pent+1: " + LitDates[9].toString());
/*#*/	Log.log("AllSnt: " + LitDates[10].toString());
/*#*/	Log.log("AllSnt+1: " + LitDates[11].toString());
/*#*/	Log.log("Advent: " + LitDates[12].toString());
/*#*/	Log.log("3rd Advent: " + LitDates[13].toString());
/*#*/	Log.log("4th Advent: " + LitDates[14].toString());
/*#*/	Log.log("Christmas: " + LitDates[15].toString());
/*#*/	Log.log("New Year: " + LitDates[16].toString());
/*#*/}

// Return the colour code corresponding to a colour name. Only names listed
// in the ClrNames array are recognized. If an unknown colour is specified,
// the code for White is returned.
ClrNames  = ["white",   "red",     "scarlet", "pink",    "orange",
	     "yellow",  "gold",    "green",   "blue",    "purple",
	     "violet",  "brown",   "black",    "offwhite",
	     "green0",	"green1",  "green2" ,  "green3", "green4",
	     "green5",  "green6",  "green7",   "green8", "green9"];
ClrCodes  = ["#FFFFFF", "#FF0000", "#DC1434", "#FB889B", "#FFA500", 
             // "#FFFF00", "#FFD700", "#008000", "#0000FF", "#800080",
             "#000000", "#000000", "#008000", "#0000FF", "#830582",
	     "#EE82EE", "#A52A2A", "#000000", "#F5F5DC",
             "#008000", "#228B22", "#7CFC00", "#00FF00", "#32CD32",  //Greens
	     "#90EE90", "#00FA9A", "#00FF7F", "#9ACD32"];
Greens    = 10;

// Given a colour name, return the corresponding hex colour code.
// The tables for colour names and codes include a set of extra green
// colours, to simplify varying the green for a liturgical colour.
function getColourCd (clr)
{
	clr = clr.toLowerCase();
	for (i = 0; i < ClrNames.length; ++i)
		if (clr == ClrNames[i])
			break;

	if (i >= ClrNames.length)
		rslt = WhiteCd;
	else
		rslt = ClrCodes[i];

	return rslt;
}

// The following array must containing one entry for each entry in the
// LitDates array. It names the liuturgical colour to be used for days
// on or after the date in the corresponding entry, and preceding the
// folowing one. The first entry is not used.
// The colours used here (at least originally) are based on an article
// by Rev. Douglas K. Escue, found at
// http://worship.lcms.org/walp/selectedart/29colors.html
// plus some additions.
LitColours = ["white", "white", "green", "black", "purple", "scarlet",
              "black", "gold", "white", "red", "green", "scarlet", "green",
              "blue", "pink", "blue", "white"];

// Determine the appropriate liturgical colour for the specified date, or
// today by default.
// First set up a table representing the transition dates for the various
// colours, than scan the table to determine in which range the
// required date falls. Return the corresponding colour.
manyGreens = 1;
useOffWhite = 2;
useGold = 4;
function getLitColour (dt, opts)
{
	if ((arguments.length <= 0) || (! dt))
		dt = new Date();
	if ((arguments.length <= 1) || (! opts))
		opts = 0;
	setLitDates(dt);

	for (i = 0; i < LitDates.length; ++i)
	        if (dt < LitDates[i])
	                break;
	if (i >= LitColours.length)
		i = 0;
	clr = LitColours[i];

	if ((opts & manyGreens) && (clr == "green"))
		clr = clr + ((dayInYear(dt) + 4) % Greens);
	else if ((opts & useOffWhite) && (clr == "white"))
		clr = "OffWhite";
	else if ((opts & useGold) && (clr == "white"))
		clr = "gold";

	return clr;
}

// Determine the appropriate liturgical colour code for the specified date, or
// today by default.
// First set up a table representing the transition dates for the various
// colours, than scan the table to determine in which range the
// required date falls. Return the corresponding colour.
// If the colour is "green," one of several possible colours is used,
// to create some variety for the commonest colour.
// The option parameter is a set of bit flags that modifieds the result.
function getLitClrCode (dt, opts)
{
	if (arguments.length <= 0)
		dt = new Date();
	if (arguments.length <= 1)
		opts = 0;
	return getColourCd(getLitColour(dt, opts));
}

// Generate a font tag specifying the current liturgical colour.
// If the correct colour is white, it is replaced by the specified
// alternate colour, or gold by default.
// To Do: The background colour should bea parameter. Right now, it
// is assumed to be white.
function setLitTxtClr (dt, alt)
{
	if (arguments.length <= 0)
		dt = new Date();
	rslt = getColourCd(getLitColour(dt, 0));
	if (rslt == "#FFFFFF") {
		if (arguments.length > 1)
			rslt = alt;
		else
			rslt = "gold";
		cd = getColourCd(rslt);
		if (cd.length > 0)
			rslt = cd;
	}
	document.write("<font color='" + rslt + "'>");
}

// Generate text in the appropriate Liturgical colour for today.
// The first parameter specified any additional font tag attributes
// that are to be applied to the text. The default is that the font
// face sans-serif is to be used - this can be overridden by any
// other value, or using a single space as the parameter value.
// Note: If the liturgical colour is white, it is changed to gold,
//       This really should be a replacement based on the background
//       colour, but that is more complicated.
function litTxt (font) 
{
	rslt = getColourCd(getLitColour(new Date(), 0));
	if (rslt == "#FFFFFF") {
		rslt = "gold";
		cd = getColourCd(rslt);
		if (cd.length > 0)
			rslt = cd;
	}

        if (font.length == 0)
                font="face='sans-serif'"
        
	document.write("<font color='" + rslt + "' " + font + ">");
        for (i = 1; i < arguments.length; ++i) {
                if (i > 1)
                        document.write(" ");
                document.write(arguments[i]);
        }
        document.write("</font>");
}

// Generate a reference to a style sheet that uses the current
// liturgical colour.
function setLitCss (dir)
{
	result = getLitColour(new Date(), useGold);
	href = "js/lit" + result + ".css";
	if (arguments.length > 0)
	   href = dir + "/" + href;
       document.write('<link rel="StyleSheet" type="text/css" '
                       + 'href="' + href + '" />');
}
