// Globals
var months;
var usa_stations = ["ATL", "BOS", "BWI", "CVG", "DFW", "DSM", "DTW", "IAH", "LAS", "LGA", "MCI", "MSP",
	"ORD", "PDX", "PHL", "SAC", "SLC", "TUS"];
var eur_stations = ["AMS", "LHR", "ORY", "STK", "THF"];
var data_attrs = ["bz", "b", "a", "az"];
var all_attrs = ["s", "m", "y", "hc", "b", "a", "bz", "az"];

function CheckBrowser() {
	// browser reqs: Windows IE 4 and up
	if (navigator.platform != "Win32")
		window.location = "error.html";
	if(navigator.appName != "Microsoft Internet Explorer")
		window.location = "error.html";
	if(parseInt(navigator.appVersion.match(/MSIE \d+/).toString().match(/\d+/).toString(), 10) < 4)
		window.location = "error.html";
}

function CheckCookie() {
	if(document.cookie.length == 0) {
		window.location = "login.aspx";
		return false;
	}
	return true;
}

function GetDOM() {
	var ARR_ACTIVEX = ["MSXML2.DOMDocument.4.0",
	                   "MSXML2.DOMDocument.3.0",
	                   "MSXML2.DOMDocument",
	                   "MSXML.DOMDocument",
	                   "Microsoft.XmlDom"];
	var bFound = false;
	for (var i=0; i < ARR_ACTIVEX.length && !bFound; ++i) {
		try {
			var dom = new ActiveXObject(ARR_ACTIVEX[i]);
			bFound = true;
		} catch (exception) {
		}
	}
	if (!bFound)
		throw "No DOM Document found on your computer.";
	dom.async = false;
	return dom;
}

function LoadPage(dom, url) {
	dom.load(url);
	if (dom.parseError.errorCode != 0)
		throw "DOM parse error: " + dom.parseError.reason;

	// strip whitespace from all attribute data, so all DOM versions parse it
	var rows = dom.getElementsByTagName("row");
	for (var r = 0; r < rows.length; ++r) {
		for (var a = 0; a < all_attrs.length; ++a) {
			var attrVal = rows.item(r).getAttribute(all_attrs[a]);
			attrVal = attrVal.replace(/\s/g, '');	// strip whitespace
			rows.item(r).setAttribute(all_attrs[a], attrVal);	
		}	
	}
}

function GetAttrData(dom, station, month, year, attr) {
	var nodepath = "/weather/row[@s='" + station + "' and @m='" + month.numStr + "' and @y='" + year 
		+ "' and @hc='" + month.hc + "']";
	var node = dom.selectSingleNode(nodepath);
	var value = node ? node.getAttribute(attr) : null;
	return value ? value : "--";
}

function SetCellValue(cell, value, bRule) {
	var bChanged = cell.innerText.length != 0 && value != cell.innerText;
	cell.innerText = value;
	// possible class names: "newval", "rule", "newvalrule", ""
	cell.className = (bChanged ? "newval" : "") + (bRule ? "rule" : "");
}

function StartUSA() {
	LayoutMonths();	
	UpdateWeatherData(usa_stations);
	setInterval('UpdateWeatherData(usa_stations)', 10000);
}

function StartEurope() {
	LayoutMonths();
	UpdateWeatherData(eur_stations);
	setInterval('UpdateWeatherData(eur_stations)', 10000);
}

function StartStation() {
	var sta = location.search.match(/[A-Z]{3}/).toString();
	document.title = "WT Weather Data for " + CityName(sta);
	document.all.dataTable.all.tblHdr.innerText = CityName(sta) + " (" + sta + ")";
	var europe = eur_stations.join().match(sta);
	document.all.BackLink.href = europe ?  "europe.html" : "index.html";
	document.all.BackLink.innerText = "View all weather data for " + (europe ? "Europe" : "USA");
	LayoutStationMonths();
	UpdateStationData(sta);
	setInterval("UpdateStationData(\"" + sta + "\")", 10000);
}

function CityName(sta) {
	switch(sta) {
		// USA
		case "ATL": return "Atlanta";				break;
		case "BOS": return "Boston";				break;
		case "BWI": return "Baltimore";				break;
		case "CVG": return "Cincinnati";			break;
		case "DFW": return "Dallas/Fort Worth";		break;
		case "DSM": return "Des Moines";			break;
		case "DTW": return "Detroit";				break;
		case "IAH": return "Houston";				break;
		case "LAS": return "Las Vegas";				break;
		case "LGA": return "New York City";			break;
		case "MCI": return "Kansas City";			break;
		case "MSP":	return "Minneapolis/St. Paul";	break;
		case "ORD": return "Chicago";				break;
		case "PDX": return "Portland";				break;
		case "PHL": return "Philadelphia";			break;
		case "SAC": return "Sacramento";			break;
		case "SLC": return "Salt Lake City";		break;
		case "TUS": return "Tuscon";				break;
		
		// Europe
		case "AMS": return "Amsterdam";				break;
		case "LHR": return "London";				break;
		case "ORY": return "Paris";					break;
		case "STK": return "Stockholm";				break;
		case "THF": return "Berlin";				break;
	}
	return "unknown city";
}

// constructor for month object; month 0 is strip
function month(iNum, bCddOrHdd) {
	this.num = iNum;	// month number (0-12)
	this.table = null;	// ref to table it will be stored in
	this.pos = 0;		// 0-based position within table
	this.numStr = (iNum == 0) ? (bCddOrHdd ? 'S' : 'W') : (iNum < 10) ? ('0' + iNum) : (iNum + '');
	this.hc = bCddOrHdd ? 'C' : 'H';
	switch(iNum) {
		case 0:		this.abbr = "";		break;	// strip: labels done manually
		case 1:		this.abbr = "JAN";	break;
		case 2:		this.abbr = "FEB";	break;
		case 3:		this.abbr = "MAR";	break;
		case 4:		this.abbr = "APR";	break;
		case 5:		this.abbr = "MAY";	break;
		case 6:		this.abbr = "JUN";	break;
		case 7:		this.abbr = "JUL";	break;
		case 8:		this.abbr = "AUG";	break;
		case 9:		this.abbr = "SEP";	break;
		case 10:	this.abbr = "OCT";	break;
		case 11:	this.abbr = "NOV";	break;
		case 12:	this.abbr = "DEC";	break;
	}
}

function GetCurMonth() {	// reads query string ?month=n and returns n, otherwise current month (1-12)
	var now = new Date();
	var qsMonth = location.search.match(/month=\d+/);
	if(qsMonth == null)
		return now.getMonth() + 1;
	else {
		var iMonth = parseInt(qsMonth.toString().match(/\d+/).toString(), 10);
		return (iMonth >= 1 && iMonth <= 12) ? iMonth : (now.getMonth() + 1);
	}
}

function LayoutMonths() {
	var cddMonths = new Array;
	var hddMonths = new Array;
	for (m = 0; m <= 12; ++m) {		// month 0 is strip
		if ((m >= 4 && m <= 10) || m == 0)
			cddMonths[cddMonths.length] = new month(m, true);
		if (m <= 4 || m >= 10)
			hddMonths[hddMonths.length] = new month(m, false);
	}
	var iCurMonth = GetCurMonth();
	var bCddOrHdd = iCurMonth >= 5 && iCurMonth <= 9;	// which data comes first?
	
	// layout cdd months
	var cddTable1 = bCddOrHdd ? document.all.table1 : document.all.table3;
	var cddTable2 = bCddOrHdd ? document.all.table2 : document.all.table4;
	cddTable1.all.tblHdr.innerText = location.pathname.match(/europe.html$/) ? "CAT" : "Cooling Degree Days (CDD)";
	var iCddStart = bCddOrHdd || iCurMonth == 10 ? iCurMonth : 4;	//start with April when in HDD month, unless it's October
	for(m = 0; m < cddMonths.length; ++m) {
		cddMonths[m].pos = cddMonths[m].num == 0 ? 7 : cddMonths[m].num - iCddStart;	// strips are always last
		if (cddMonths[m].pos < 0)
			cddMonths[m].pos += cddMonths.length - 1;	// wrap at end, exclude strip
		cddMonths[m].table = cddMonths[m].pos < 4 ? cddTable1 : cddTable2;
		if (cddMonths[m].table == cddTable2)
			cddMonths[m].pos -= 4;
	}

	// layout hdd months
	var hddTable1 = bCddOrHdd ? document.all.table3 : document.all.table1;
	var hddTable2 = bCddOrHdd ? document.all.table4 : document.all.table2;
	hddTable1.all.tblHdr.innerText = "Heating Degree Days (HDD)";
	var iHddStart = !bCddOrHdd ? iCurMonth : 10; // start with October when in CDD month
	for(m = 0; m < hddMonths.length; ++m) {
		hddMonths[m].pos = hddMonths[m].num == 0 ? 7 : hddMonths[m].num - iHddStart;
		if ((hddMonths[m].num < 10) != (iHddStart < 10) && hddMonths[m].num != 0)
			hddMonths[m].pos += iHddStart >= 10 ? 5 : -5;	// skip cdd months in between
		if (hddMonths[m].pos < 0)
			hddMonths[m].pos += hddMonths.length - 1;	// wrap at end, exclude strip
		hddMonths[m].table = hddMonths[m].pos < 4 ? hddTable1 : hddTable2;
		if (hddMonths[m].table == hddTable2)
			hddMonths[m].pos -= 4;
	}
	// concatenate arrays to simplify updates
	months = cddMonths.concat(hddMonths);
}

function UpdateWeatherData(stationArray) {
	try {
		if(!CheckCookie())
			return;
		var dom = GetDOM();
		LoadPage(dom, "getweatherdata.aspx?" + document.cookie);	// query string is ignored by script but shows up in web log
		var now = new Date();
		var thisYear = now.getYear();
		var thisMonth = now.getMonth() + 1;	// getMonth() returns 0-11

		for (i = 0; i < months.length; ++i) {
			var m = months[i];
			if (m.table == null)
				continue;
			var year = (m.numStr == 'S' && thisMonth > 9) || (m.numStr == 'W' && thisMonth > 3) || 
				(m.num < thisMonth && m.num != 0) ? thisYear + 1 : thisYear;
			m.table.rows(1).cells(m.pos + 1).innerText = m.num == 0 ? year + " " + m.hc + "DD Strip" : m.abbr + " " + year;
			for (var s = 0; s < stationArray.length; ++s) {
				var bRule = s % 2 != 0 && s != stationArray.length-1;
				for (var a = 0; a < data_attrs.length; ++a)
					SetCellValue(m.table.rows(s + 3).cells(m.pos * data_attrs.length + a + 1), 
						GetAttrData(dom, stationArray[s], m, year, data_attrs[a]), bRule);
			}
		}
		document.all.refresh.innerText = now.toString();
	} catch (exception) {
		window.alert(exception);
	}
}

function LayoutStationMonths() {
	months = new Array;
	for (var m = 0; m <= 12; ++m) {	// month 0 is strip
		months[months.length] = new month(m, true);
		months[months.length] = new month(m, false);
	}
	var iCurMonth = GetCurMonth();
	for(m = 0; m < months.length; ++m) {
		months[m].pos = months[m].num == 0 ? 12 : months[m].num - iCurMonth;
		if(months[m].pos < 0)
			months[m].pos += 12;
	}
}

function UpdateStationData(sta) {
	try {
		if(!CheckCookie())
			return;

		var dom = GetDOM();
		LoadPage(dom, "getweatherdata.aspx?" + document.cookie + "&station=" + sta);	// query string is ignored by script but shows up in web log
		var now = new Date();
		var thisYear = now.getYear();
		var thisMonth = now.getMonth() + 1;

		for (i = 0; i < months.length; ++i) {
			var m = months[i];
			var year = (m.numStr == 'S' && thisMonth > 9) || (m.numStr == 'W' && thisMonth > 3) || 
				(m.num < thisMonth && m.num != 0) ? thisYear + 1 : thisYear;
			var row = m.pos + 3;
			var bRule = row % 2 == 0;
			document.all.dataTable.rows(row).cells(0).innerText = m.num == 0 ? "Strips" : m.abbr + " " + year;
			for (var a = 0; a < data_attrs.length; ++a)
				SetCellValue(document.all.dataTable.rows(row).cells(m.hc == 'C' ? a+1 : a+5),
					GetAttrData(dom, sta, m, year, data_attrs[a]), bRule);
		}
		document.all.refresh.innerText = now.toString();
	} catch (exception) {
		window.alert(exception);
	}
}