Date.prototype.skipUTCWeekdays = function(dayOfWeek, skipNum) {
	var skipped = 0;
	for (var i=1;i<=28;i++) { /* There is lots of room for optimization here. */
		this.setUTCDate(i);
		if (this.getUTCDay() == dayOfWeek) {
			if (skipNum == skipped) return;
			skipped++;
		}
	}
}

Date.prototype.isUSDst = function(offsetUTCMin) {
	var offset = offsetUTCMin * 60 * 1000; /* offset in ms */
	var baseDate = new Date();

	baseDate.setTime(0);
	baseDate.setUTCHours(2)
	baseDate.setUTCFullYear(new Date().getUTCFullYear());

	/* DST in US Starts 2nd Sunday in March at 2 AM local time. */
	baseDate.setUTCMonth(2);
	baseDate.skipUTCWeekdays(0, 1);

	/* If it's before DST start + offset, it isn't dst. */
	if ((this.getTime()+offset) < baseDate.getTime()) {
		return(false);
	}

	/* DST in US Ends 1st Sunday in November at 2 AM local time. */
	baseDate.setUTCMonth(10);
	baseDate.skipUTCWeekdays(0, 0);

	/* If it's between DST start + offset and DST end + offset, it is dst. */
	if ((this.getTime()+offset) < baseDate.getTime()) {
		return(true);
	}

	/* Not DST */
	return(false);
}

/* YYYYMMDD */
function datestamp(unixtime) {
	var date = new Date();

	var pacificOffset = date.isUSDst(-480) ? -420 : -480; /* Pacific is -480/-420 daylight time, or GMT-8/-7*/

	/* Offset to Pacific time in seconds. Datestamps have to be in PDT/PST, because they're generated in PDT/PST */
	var offset = pacificOffset * 60;

	date.setTime((unixtime + offset) * 1000);

	var year  = date.getUTCFullYear();
	var month = date.getUTCMonth() + 1;
	var day   = date.getUTCDate();
	return("" + year + ((month<10) ? "0" + month : month) + ((day<10) ? "0" + day : day));
}

function get(id) {
	if (typeof id == "string") {
		return(document.getElementById(id));
	} else {
		return(id);
	}
}

function show(id) {
	if (e = get(id)) {
		//YAHOO.util.Dom.setStyle(e, 'opacity', 1);
		e.style.display = '';
	}
}

function hide(id) {
	if (e = get(id)) {
		/* YAHOO.util.Dom.setStyle(e, 'opacity', 1);
		e.style.display = '';
		var onComplete = function(ev) {
			var e = this.getEl();
			YAHOO.util.Dom.setStyle(e, 'display', 'none');
			YAHOO.util.Dom.setStyle(e, 'opacity', 1);
		}		
		var anim = new YAHOO.util.Anim(e, { opacity: { from: 1, to: 0 }}, 0.2, YAHOO.util.Easing.easeOut);
		anim.onComplete.subscribe(onComplete);
		anim.animate(); */
		e.style.display = 'none';
	}
}

function toggle(id) {
	target = document.getElementById(id);
	if (!target) {
		return;
	}

	if (target.style.display == 'none') {
		//target.style.display = '';
		show(target)
	} else {
		hide(target);
		//target.style.display = 'none';
	}
}

function toggleCurrent(obj, id) {
	target = document.getElementById(id);

	if (!target) {
		return;	
	}

	if (target.style.display == 'none') {
		target.style.display = '';
		obj.innerHTML = 'less <img src="images/less.gif" />';
	} else {
		target.style.display = 'none';
		obj.innerHTML = 'more <img src="images/more.gif" />';
	}
}

var rows = 0;
var cols = 0;
var day = 86400;
var cursor = day;
var today = 0;
var lock = false;
var services = new Array();

var curTable;
var newTable;

var months = new Array(
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
);

function showDate(date, left) {
	lock = true;

	document.getElementById('nextDate_img').src = 'images/arrows-grey-left.gif';
	document.getElementById('prevDate_img').src = 'images/arrows-grey-right.gif';
	
	if (!curTable)
		curTable = document.getElementById('statusHistoryContent');
		
	curTable.parentNode.style.overflow = 'hidden';

	newTable = document.createElement('table');
	newTable.className = curTable.className;
	var b = document.createElement('tbody');

	/* Header row */
	var r = document.createElement('tr');
	var dates = new Array(cols);
	for (var j=0;j<cols;j++) {
		var timestamp = date - (j*day);
		dates[j] = new Date();
        dates[j].setTime(timestamp*1000);
		
		var h = document.createElement('th');
        h.innerHTML = months[dates[j].getUTCMonth()] + " " + dates[j].getUTCDate();
		r.appendChild(h);
	}
	b.appendChild(r);
	
	/* Body row */
	for (var i=0;i<rows;i++) {
		r = document.createElement('tr');
        for (var j=0;j<cols;j++) {
			var stamp = datestamp(dates[j].getTime() / 1000);
			var index = services[i] + "_" + stamp;
			if ("20080413" >= stamp) { /* We don't have any info before this date. */
				var c = document.createElement('td');
				c.innerHTML = '<img src="images/status-disabled.gif" />';
				r.appendChild(c);
			} else if (eventData.archive[index]) {
				var event = eventData.archive[index];
				var td = document.createElement('td');
				var s1 = document.createElement('span');
				var im = document.createElement('img');
				var s2 = document.createElement('span');
				var dv = document.createElement('div');

				/* Status popup */
				var dvp = document.createElement('div');
				var dvi = document.createElement('div');
				var dvs = document.createElement('div');
				var dvd = document.createElement('div');
				var im1 = document.createElement('img');

				/* Set table properties/contents. */
				dvp.className = "whitebg pad4";
				dvi.className = "pad4 floatLeft";
				dvs.className = "pad4 bold yellowfg floatLeft";
				dvd.className = "pad4 clear";
				im1.src = "images/status" + event.status + ".gif";
				dvs.innerHTML = event.summary;
				dvd.innerHTML = event.description;
				
				/* Put elements in the right spot. */
				dvi.appendChild(im1);
				dvp.appendChild(dvi);
				dvp.appendChild(dvs);
				dvp.appendChild(dvd);
				dv.appendChild(dvp);

				im.src = 'images/status' + event.status + '.gif';
				s1.id = "imagecontainer_archive_" + index;
				dv.id = "archive_" + index;
				s2.style.position = 'relative';
				dv.style.display = 'none';
				dv.className = 'greybg bordered-dark pad8 archivePopup';
				s1.appendChild(im);
				s2.appendChild(dv);
				td.appendChild(s1);
				td.appendChild(s2);
				r.appendChild(td);

				setupHistoryEventHandler("archive_" + index);
			} else {
	            var c = document.createElement('td');
    	        c.innerHTML = '<img src="images/status0.gif" />';
				r.appendChild(c);
			}
        }
		b.appendChild(r);
    }
	newTable.appendChild(b);
	
	var doComplete = function(e) {
		element = this.getEl();
		par = element.parentNode;
		par.removeChild(element);
		par.style.overflow = 'visible';
		lock = false;
	}
	
	if (left) {
		newTable.style.left = '470px';
		var animCur = new YAHOO.util.Anim(curTable, { left: { from: 0, to: -470 }}, 0.5, YAHOO.util.Easing.easeBoth);
		var animNew = new YAHOO.util.Anim(newTable, { left: { from: 470, to: 0 }}, 0.5, YAHOO.util.Easing.easeBoth);
	} else {
		newTable.style.left = '-470px';
		var animCur = new YAHOO.util.Anim(curTable, { left: { from: 0, to: 470 }}, 0.5, YAHOO.util.Easing.easeBoth);
		var animNew = new YAHOO.util.Anim(newTable, { left: { from: -470, to: 0 }}, 0.5, YAHOO.util.Easing.easeBoth);
	}
	newTable.style.position = 'absolute';
	newTable.style.visibility = 'hidden';
	curTable.parentNode.appendChild(newTable);
    animCur.onComplete.subscribe( doComplete );
	newTable.style.visibility = 'visible';
    animCur.animate();
    animNew.animate();
	
	curTable = newTable;
	newTable = null;
	
    if (cursor <= day) {
        document.getElementById('nextDate_img').src = 'images/arrows-grey-left.gif';
    } else {
        document.getElementById('nextDate_img').src = 'images/arrows-red-left.gif';
    }

    if (cursor >= (day * 28)) {
        document.getElementById('prevDate_img').src = 'images/arrows-grey-right.gif';
    } else {
        document.getElementById('prevDate_img').src = 'images/arrows-red-right.gif';
    }
}

function nextDate() {
    if (cursor <= day) return;
	if (lock == true) return;

    cursor -= day * 7;
    showDate(today - cursor, false);
}

function prevDate() {
    if (cursor >= (day * 28)) return;
	if (lock == true) return;

    cursor += day * 7;
    showDate(today - cursor, true);
}


/* Pre-load data immediately */
var eventData = {
	fetch:
		function() {
			YAHOO.util.Connect.asyncRequest('GET', '/data.json', { success: this.onSuccess, scope: this }, null);
		},
	onSuccess:
		function(obj) {
			var data = YAHOO.lang.JSON.parse(obj.responseText);
			this.current = data.current;
			this.archive = data.archive;
                                                                                                                                                     
			/* Index the archive array, add objects as properties to the array. */
			for (var i=0;i<this.archive.length;i++) {
				var date = datestamp(this.archive[i].date);
				var index = this.archive[i].service + "_" + date;
				this.archive[index] = this.archive[i];
			}
		},
	current: null,
	archive: null
}

var onImageClick = function(event, id) {
	event.cancelBubble = true;
	if (e = document.getElementById(id)) {
		if (e.clicked) {
			hide(id);
			e.clicked = false;
		} else {
			show(id);
			e.clicked = true;
		}
	}
}
                                                                                                                                                             
var onImageMouseOver = function(event, id) {
	if (!document.getElementById(id).clicked) {
		event.cancelBubble = true;
		show(id);
	}
}
                                                                                                                                                             
var onImageMouseOut = function(event, id) {
	if (!document.getElementById(id).clicked) {
		event.cancelBubble = true;
		hide(id);
	}
}
                                                                                                                                                             
var onDocumentClick = function(event, id) {
	if (e = get(id)) {
		hide(e);
		e.clicked = false;
	}
}
                                                                                                                                                             
function setupHistoryEventHandler(id) {
	YAHOO.util.Event.addListener('imagecontainer_' + id, 'click',     onImageClick,     id);
	YAHOO.util.Event.addListener('imagecontainer_' + id, 'mouseover', onImageMouseOver, id);
	YAHOO.util.Event.addListener('imagecontainer_' + id, 'mouseout',  onImageMouseOut,  id);
	YAHOO.util.Event.addListener(id,                     'mouseover', onImageMouseOver, id);
	YAHOO.util.Event.addListener(id,                     'mouseout',  onImageMouseOut,  id);
	YAHOO.util.Event.addListener(document,               'click',     onDocumentClick,  id);
}
