var dpLogger = LogFactory.getLog("DatePickerDHTML.js");

/* ************************************************************* */
/* Global Variables - configure the script using these           */
/* ************************************************************* */

// CSS Styles
var calDivStyle = "dhtmlCalendar";
var headerTableStyle = "dhtmlCalHeader";
var calendarTableStyle = "dhtmlCalTable";
var weekendStyle = "dhtmlCalWeekend";

// Other configuration
var dayStyle = 0;   // 0=single letter, 1=abbreviations
var calendarTableCellspacing = 1;

/* ************************************************************* */
/* END - Global Variables - no configuration below this point    */
/* ************************************************************* */

// Holds a reference to the calendar image when we popup the div
// so that we can adjust the event handlers
var calendarLinks = new Array();
var calendarLinksOldEvent = new Array();

var weekend = [0,6];

var gNow = new Date();
//var ggWinCal;
isNav = (navigator.appName.indexOf("Netscape") != -1) ? true : false;
isIE = (navigator.appName.indexOf("Microsoft") != -1) ? true : false;

Calendar.Months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];

// Non-Leap year Month days..
Calendar.DOMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Leap year Month days..
Calendar.lDOMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

function Calendar(p_item, p_month, p_year, p_format) {
    dpLogger.debug("Enter Calendar()");
	if ((p_month == null) && (p_year == null))	return;

	if (p_month == null) {
		this.gMonthName = null;
		this.gMonth = null;
		this.gYearly = true;
	} else {
		this.gMonthName = Calendar.get_month(p_month);
		this.gMonth = new Number(p_month);
		this.gYearly = false;
	}

	this.gYear = p_year;
	this.gFormat = p_format;
	this.gBGColor = "white";
	this.gFGColor = "black";
	this.gTextColor = "black";
	this.gHeaderColor = "black";
	this.gReturnItem = p_item;
    dpLogger.debug("Exit Calendar()");
}

Calendar.get_month = Calendar_get_month;
Calendar.get_daysofmonth = Calendar_get_daysofmonth;
Calendar.calc_month_year = Calendar_calc_month_year;
Calendar.print = Calendar_print;

function Calendar_get_month(monthNo) {
	return Calendar.Months[monthNo];
}

function Calendar_get_daysofmonth(monthNo, p_year) {
	/* 
	Check for leap year ..
	1.Years evenly divisible by four are normally leap years, except for... 
	2.Years also evenly divisible by 100 are not leap years, except for... 
	3.Years also evenly divisible by 400 are leap years. 
	*/
	if ((p_year % 4) == 0) {
		if ((p_year % 100) == 0 && (p_year % 400) != 0)
			return Calendar.DOMonth[monthNo];
	
		return Calendar.lDOMonth[monthNo];
	} else
		return Calendar.DOMonth[monthNo];
}

function Calendar_calc_month_year(p_Month, p_Year, incr) {
	/* 
	Will return an 1-D array with 1st element being the calculated month 
	and second being the calculated year 
	after applying the month increment/decrement as specified by 'incr' parameter.
	'incr' will normally have 1/-1 to navigate thru the months.
	*/
	var ret_arr = new Array();
	
	if (incr == -1) {
		// B A C K W A R D
		if (p_Month == 0) {
			ret_arr[0] = 11;
			ret_arr[1] = parseInt(p_Year) - 1;
		}
		else {
			ret_arr[0] = parseInt(p_Month) - 1;
			ret_arr[1] = parseInt(p_Year);
		}
	} else if (incr == 1) {
		// F O R W A R D
		if (p_Month == 11) {
			ret_arr[0] = 0;
			ret_arr[1] = parseInt(p_Year) + 1;
		}
		else {
			ret_arr[0] = parseInt(p_Month) + 1;
			ret_arr[1] = parseInt(p_Year);
		}
	}
	
	return ret_arr;
}

function Calendar_print() {
	ggWinCal.print();
}

function Calendar_calc_month_year(p_Month, p_Year, incr) {
	/* 
	Will return an 1-D array with 1st element being the calculated month 
	and second being the calculated year 
	after applying the month increment/decrement as specified by 'incr' parameter.
	'incr' will normally have 1/-1 to navigate thru the months.
	*/
	var ret_arr = new Array();
	
	if (incr == -1) {
		// B A C K W A R D
		if (p_Month == 0) {
			ret_arr[0] = 11;
			ret_arr[1] = parseInt(p_Year) - 1;
		}
		else {
			ret_arr[0] = parseInt(p_Month) - 1;
			ret_arr[1] = parseInt(p_Year);
		}
	} else if (incr == 1) {
		// F O R W A R D
		if (p_Month == 11) {
			ret_arr[0] = 0;
			ret_arr[1] = parseInt(p_Year) + 1;
		}
		else {
			ret_arr[0] = parseInt(p_Month) + 1;
			ret_arr[1] = parseInt(p_Year);
		}
	}
	
	return ret_arr;
}

// This is for compatibility with Navigator 3, we have to create and discard one object before the prototype object exists.
new Calendar();

Calendar.prototype.getMonthlyCalendarCode = function( calDivId ) {
	var vCode = "";
	var vHeader_Code = "";
	var vData_Code = "";
	
	// Begin Table Drawing code here..
	vCode = "<table cellspacing='" + calendarTableCellspacing +
            "' class='" + calendarTableStyle + "'>";
	
	vHeader_Code = this.calHeader();
	vData_Code = this.calData( calDivId );
	vCode = vCode + vHeader_Code + vData_Code;
	
	vCode = vCode + "</table>";
	
	return vCode;
}

Calendar.prototype.show = function( calDiv ) {
    dpLogger.debug("Enter show()");
	var vCode = "";
    var calDivId = calDiv.getAttribute("id");
	
	// Show navigation buttons
	var prevMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, -1);
	var prevMM = prevMMYYYY[0];
	var prevYYYY = prevMMYYYY[1];

	var nextMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, 1);
	var nextMM = nextMMYYYY[0];
	var nextYYYY = nextMMYYYY[1];
	
    var hdrTable = 
	    "<table cellspacing='0' class='" + headerTableStyle + "'><tr><td>" +
	    "<a href=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', '" + this.gMonth + "', '" + (parseInt(this.gYear)-1) +
        "', '" + this.gFormat + "', '" + calDivId + "');" +
		"\">&lt;&lt;<\/a></td><td>" +
	    "<a href=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', '" + prevMM + "', '" + prevYYYY +
        "', '" + this.gFormat + "', '" + calDivId + "');" +
		"\">&lt;<\/a></td><td>" +

	    this.gMonthName + " " + this.gYear + "</td><td>" +

	    "<a href=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', '" + nextMM + "', '" + nextYYYY + 
        "', '" + this.gFormat + "', '" + calDivId + "');" +
		"\">&gt;<\/a></td><td>" +
	    "<a href=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', '" + this.gMonth + "', '" + (parseInt(this.gYear)+1) +
        "', '" + this.gFormat + "', '" + calDivId + "');" +
		"\">&gt;&gt;<\/a></td></tr></table>";

	this.wwrite(calDiv, hdrTable);

	// Get the complete calendar code for the month..
	vCode = this.getMonthlyCalendarCode(calDivId);
	this.wwrite(calDiv, vCode);

    dpLogger.debug("Exit show()");
}

Calendar.prototype.showY = function( calDiv ) {
    dpLogger.debug("Enter showY()");
    alert("NOT YET IMPLEMENTED!");
    var calDivId = calDiv.getAttribute("id");
	var vCode = "";
	var i;
	var vr, vc, vx, vy;		// Row, Column, X-coord, Y-coord
	var vxf = 285;			// X-Factor
	var vyf = 200;			// Y-Factor
	var vxm = 10;			// X-margin
	var vym;				// Y-margin
	if (isIE)	vym = 75;
	else if (isNav)	vym = 25;
	
	for (i=0; i<12; i++) {
		vc = i % 3;
		if (i>=0 && i<= 2)	vr = 0;
		if (i>=3 && i<= 5)	vr = 1;
		if (i>=6 && i<= 8)	vr = 2;
		if (i>=9 && i<= 11)	vr = 3;
		
		vx = parseInt(vxf * vc) + vxm;
		vy = parseInt(vyf * vr) + vym;

		this.wwrite(calDiv, ".lclass" + i + " {position:absolute;top:" + vy + ";left:" + vx + ";}");
	}
	this.wwrite(calDiv, "-->\n</style>");
	this.wwrite(calDiv, "</head>");

	this.wwrite(calDiv, "<body " + 
		"link=\"" + this.gLinkColor + "\" " + 
		"vlink=\"" + this.gLinkColor + "\" " +
		"alink=\"" + this.gLinkColor + "\" " +
		"text=\"" + this.gTextColor + "\">");
	this.wwrite(calDiv, "<FONT FACE='" + fontface + "' SIZE=2><B>");
	this.wwrite(calDiv, "Year : " + this.gYear);
	this.wwrite(calDiv, "</B><BR>");

	// Show navigation buttons
	var prevYYYY = parseInt(this.gYear) - 1;
	var nextYYYY = parseInt(this.gYear) + 1;
	
	this.wwrite(calDiv, "<TABLE WIDTH='100%' BORDER=1 CELLSPACING=0 CELLPADDING=0 BGCOLOR='#e0e0e0'><TR><TD ALIGN=center>");
	this.wwrite(calDiv, "[<A HREF=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', null, '" + prevYYYY + "', '" + this.gFormat + "'" +
		");" +
		"\" alt='Prev Year'><<<\/A>]</TD><TD ALIGN=center>");
	this.wwrite(calDiv, "[<A HREF=\"javascript:window.print();\">Print</A>]</TD><TD ALIGN=center>");
	this.wwrite(calDiv, "[<A HREF=\"" +
		"javascript:Build(" + 
		"'" + this.gReturnItem + "', null, '" + nextYYYY + "', '" + this.gFormat + "'" +
		");" +
		"\">>><\/A>]</TD></TR></TABLE><BR>");

	// Get the complete calendar code for each month..
	var j;
	for (i=11; i>=0; i--) {
		if (isIE)
			this.wwrite(calDiv, "<DIV ID=\"layer" + i + "\" CLASS=\"lclass" + i + "\">");
		else if (isNav)
			this.wwrite(calDiv, "<LAYER ID=\"layer" + i + "\" CLASS=\"lclass" + i + "\">");

		this.gMonth = i;
		this.gMonthName = Calendar.get_month(this.gMonth);
		vCode = this.getMonthlyCalendarCode(calDivId);
		this.wwrite(calDiv, this.gMonthName + "/" + this.gYear + "<BR>");
		this.wwrite(calDiv, vCode);

		if (isIE)
			this.wwrite(calDiv, "</DIV>");
		else if (isNav)
			this.wwrite(calDiv, "</LAYER>");
	}

    dpLogger.debug("Exit showY()");
}

Calendar.prototype.wwrite = function(calDiv, wtext) {
    var txt = calDiv.innerHTML;
    calDiv.innerHTML = txt + wtext;
}

Calendar.prototype.wwriteA = function(calDiv, wtext) {
    var txt = calDiv.innerHTML;
    calDiv.innerHTML = txt + wtext;
}

Calendar.prototype.calHeader = function() {
	
	var vCode = "<colgroup class='" + weekendStyle + "'></colgroup>" +
	            "<colgroup colspan='5'></colgroup>" +
	            "<colgroup class='" + weekendStyle + "'></colgroup>";

    if( dayStyle == 0 ) {
        vCode +=
                "<tr>" +
                    "<th>S</th>" +
                    "<th>M</th>" +
                    "<th>T</th>" +
                    "<th>W</th>" +
                    "<th>T</th>" +
                    "<th>F</th>" +
                    "<th>S</th>" +
                "</tr>";
    } else {
        vCode +=
                "<tr>" +
                    "<th>Sun</th>" +
                    "<th>Mon</th>" +
                    "<th>Tue</th>" +
                    "<th>Wed</th>" +
                    "<th>Thu</th>" +
                    "<th>Fri</th>" +
                    "<th>Sat</th>" +
                "</tr>";
    }
	
	return vCode;
}

function closeDiv( calDivId ) {
    // now change the event handler for the item
    var calLink = calendarLinks[calDivId];
    calLink.onclick = calendarLinksOldEvent[ calDivId ];

    // Remove the div
    var calDiv = document.getElementById( calDivId );
    var body = document.getElementsByTagName("body").item(0);
    body.removeChild( calDiv );

    delete calendarLinks[calDivId];
    delete calendarLinksOldEvent[calDivId];
}

Calendar.prototype.calData = function(calDivId) {
	var vDate = new Date();
	vDate.setDate(1);
	vDate.setMonth(this.gMonth);
	vDate.setFullYear(this.gYear);

	var vFirstDay=vDate.getDay();
	var vDay=1;
	var vLastDay=Calendar.get_daysofmonth(this.gMonth, this.gYear);
	var vOnLastDay=0;
	var vCode = "";

	/*
	Get day for the 1st of the requested month/year..
	Place as many blank cells before the 1st day of the month as necessary. 
	*/

	vCode = vCode + "<tr>";
	for (i=0; i<vFirstDay; i++) {
		vCode = vCode + "<td class='empty'>&nbsp;</td>";
	}

	// Write rest of the 1st week
	for (j=vFirstDay; j<7; j++) {
		vCode = vCode + "<td>" +
			"<a href='#' " + 
				"onClick=\"setDateField( event, '" + this.gReturnItem + "', '" + 
				this.format_data(vDay) + "', '" + calDivId + "');return false;\">" + 
				this.format_day(vDay) + 
			"</a></td>";
		vDay=vDay + 1;
	}
	vCode = vCode + "</tr>";

	// Write the rest of the weeks
	for (k=2; k<7; k++) {
		vCode = vCode + "<tr>";

		for (j=0; j<7; j++) {
			vCode = vCode + "<td>" +
				"<a href='#' " + 
				"onClick=\"setDateField( event, '" + this.gReturnItem + "', '" + 
                this.format_data(vDay) + "', '" + calDivId + "');return false;\">" + 
				this.format_day(vDay) + 
                "</a></td>";
			vDay=vDay + 1;

			if (vDay > vLastDay) {
				vOnLastDay = 1;
				break;
			}
		}

		if (j == 6)
			vCode = vCode + "</tr>";
		if (vOnLastDay == 1)
			break;
	}
	
	// Fill up the rest of last week with proper blanks, so that we get proper square blocks
	for (m=1; m<(7-j); m++) {
		if (this.gYearly)
            vCode = vCode + "<td class='empty'>&nbsp;</td>";
		else
            vCode = vCode + "<td class='empty'>&nbsp;</td>";
	}
	
	return vCode;
}

Calendar.prototype.format_day = function(vday) {
	var vNowDay = gNow.getDate();
	var vNowMonth = gNow.getMonth();
	var vNowYear = gNow.getFullYear();

	if (vday == vNowDay && this.gMonth == vNowMonth && this.gYear == vNowYear)
		return ("<font color=\"red\"><b>" + vday + "</b></font>");
	else
		return (vday);
}


Calendar.prototype.format_data = function(p_day) {
	var vData;
	var vMonth = 1 + this.gMonth;
	vMonth = (vMonth.toString().length < 2) ? "0" + vMonth : vMonth;
	var vMon = Calendar.get_month(this.gMonth).substr(0,3).toUpperCase();
	var vFMon = Calendar.get_month(this.gMonth).toUpperCase();
	var vY4 = new String(this.gYear);
	var vY2 = new String(this.gYear.substr(2,2));
	var vDD = (p_day.toString().length < 2) ? "0" + p_day : p_day;

	switch (this.gFormat) {
		case "MM\/DD\/YYYY" :
			vData = vMonth + "\/" + vDD + "\/" + vY4;
			break;
		case "MM\/DD\/YY" :
			vData = vMonth + "\/" + vDD + "\/" + vY2;
			break;
		case "MM-DD-YYYY" :
			vData = vMonth + "-" + vDD + "-" + vY4;
			break;
		case "MM-DD-YY" :
			vData = vMonth + "-" + vDD + "-" + vY2;
			break;

		case "DD\/MON\/YYYY" :
			vData = vDD + "\/" + vMon + "\/" + vY4;
			break;
		case "DD\/MON\/YY" :
			vData = vDD + "\/" + vMon + "\/" + vY2;
			break;
		case "DD-MON-YYYY" :
			vData = vDD + "-" + vMon + "-" + vY4;
			break;
		case "DD-MON-YY" :
			vData = vDD + "-" + vMon + "-" + vY2;
			break;

		case "DD\/MONTH\/YYYY" :
			vData = vDD + "\/" + vFMon + "\/" + vY4;
			break;
		case "DD\/MONTH\/YY" :
			vData = vDD + "\/" + vFMon + "\/" + vY2;
			break;
		case "DD-MONTH-YYYY" :
			vData = vDD + "-" + vFMon + "-" + vY4;
			break;
		case "DD-MONTH-YY" :
			vData = vDD + "-" + vFMon + "-" + vY2;
			break;

		case "DD\/MM\/YYYY" :
			vData = vDD + "\/" + vMonth + "\/" + vY4;
			break;
		case "DD\/MM\/YY" :
			vData = vDD + "\/" + vMonth + "\/" + vY2;
			break;
		case "DD-MM-YYYY" :
			vData = vDD + "-" + vMonth + "-" + vY4;
			break;
		case "DD-MM-YY" :
			vData = vDD + "-" + vMonth + "-" + vY2;
			break;

		default :
			vData = vMonth + "\/" + vDD + "\/" + vY4;
	}

	return vData;
}

function Build(p_item, p_month, p_year, p_format, divId) {
    var calDiv = document.getElementById( divId );
    calDiv.innerHTML = "";
	gCal = new Calendar(p_item, p_month, p_year, p_format);

	// Customize your Calendar here..
	gCal.gBGColor="white";
	gCal.gLinkColor="black";
	gCal.gTextColor="black";
	gCal.gHeaderColor="darkgreen";

	// Choose appropriate show function
	if (gCal.gYearly)	gCal.showY( calDiv );
	else	gCal.show( calDiv );
}

/*
 * Event handler used to fill in the form field
 */
function setDateField(event, field, value, calDivId) {
    dpLogger.debug("Enter setDateField()");
    var formName = field.substring( 0, field.indexOf(".") );
    var fieldName = field.substring( field.indexOf(".") + 1, field.length );
    document.forms[ formName ].elements[ fieldName ].value = value;
    closeDiv( calDivId );
    dpLogger.debug("Exit setDateField()");
    return false;
}

/*
 * Event handler used to display the calendar.
 * This should be called with an event, along with 
 * the arguments below.
 */
function showCalendar(event) {
	/* 
		p_month : 0-11 for Jan-Dec; 12 for All Months.
		p_year	: 4-digit year
		p_format: Date format (mm/dd/yyyy, dd/mm/yy, ...)
		p_item	: Return Item.
	*/
	p_item = arguments[1];
	if (arguments[2] == null)
		p_month = new String(gNow.getMonth());
	else
		p_month = arguments[2];
	if (arguments[3] == "" || arguments[3] == null)
		p_year = new String(gNow.getFullYear().toString());
	else
		p_year = arguments[3];
	if (arguments[4] == null)
		p_format = "MM/DD/YYYY";
	else
		p_format = arguments[4];

    // First close all other divs
    for( i in calendarLinks ) {
        closeDiv( i );
    }

    var calDiv = document.createElement("div");
    var pos = getXY( event );
    var txt = document.createTextNode("");
    var id = getUniqueId("dhtmlCalDiv");
    calDiv.className = calDivStyle;
    calDiv.setAttribute("id", id);
    calDiv.style.position = "absolute";
    calDiv.style.top = "" + pos[1] + "px";
    calDiv.style.left = "" + pos[0] + "px";
    calDiv.appendChild( txt );
    var body = document.getElementsByTagName("body").item(0);
    body.appendChild( calDiv );

    // now change the event handler for the item
    calLink = getEventSource( event );
    calendarLinksOldEvent[id] = calLink.onclick;
    calLink.onclick = new function() { return false; };
    calendarLinks[id] = calLink;

    /*
	vWinCal = window.open("", "Calendar", 
		"width=250,height=250,status=no,resizable=no,top=200,left=200");
	vWinCal.opener = self;
	ggWinCal = vWinCal;
    */

	Build(p_item, p_month, p_year, p_format, id);
    return false;
}

// Returns a unique Id within the current document based on the baseId
function getUniqueId( baseId ) {
    var newId = baseId + Math.round( Math.random() * 10000. );
    var elem = document.getElementById( newId );
    if( elem ) {
        newId = getUniqueId( baseId );
    }
    return newId;
}

/*
Yearly Calendar Code Starts here
*/
function show_yearly_calendar(p_item, p_year, p_format) {
	// Load the defaults..
	if (p_year == null || p_year == "")
		p_year = new String(gNow.getFullYear().toString());
	if (p_format == null || p_format == "")
		p_format = "MM/DD/YYYY";

    /*
	var vWinCal = window.open("", "Calendar", "scrollbars=yes");
	vWinCal.opener = self;
	ggWinCal = vWinCal;
    */

	Build(p_item, null, p_year, p_format);
}

function getXY(e) {
    var pos = new Array(0, 0);
	pos[0] = 0;
	pos[1] = 0;
    var elem = getEventSource( e );

    var width = elem.width;

    if (elem.offsetParent) {
        while (elem.offsetParent) {
            pos[0] += elem.offsetLeft
            pos[1] += elem.offsetTop
            elem = elem.offsetParent;
        }
    } else if (elem.x) {
        pos[0] += elem.x;
        pos[1] += elem.y;
    }
    pos[0] += width;

    return pos;
}

function getXYMouse(e) {
    var pos = new Array(0, 0);
	if (!e) var e = window.event;
	if (e.pageX || e.pageY) {
		pos[0] = e.pageX;
		pos[1] = e.pageY;
	} else if (e.clientX || e.clientY) {
        if( document.documentElement ) {
            pos[0] = e.clientX + document.documentElement.scrollLeft;
            pos[1] = e.clientY + document.documentElement.scrollTop;
        } else {
            pos[0] = e.clientX + document.body.scrollLeft;
            pos[1] = e.clientY + document.body.scrollTop;
        }
	}
    return pos;
}

