/* ------------------------------------------------------------------

File:		metar.js
Abstract:	fetch metar/taf data from NWS
Version:	0.1
Author:		Pascal Dreer

------------------------------------------------------------------ */


var xml_request;
var firstConnection = true;
var fetchInProgress = false;
var updateTime = new Date();
var keepPastData = false;
var gMetricFormat = true;
var gShowLocalTime = true;

var metarTimer;
var metarStations = [];


function startMetarInterval()
{
	var ids = "";
	for (var i = 0; i < gMappoints.length; i++)
		if (gMappoints[i].type == 1 || gMappoints[i].type == 2 || gMappoints[i].type == 9) {
			if (gMappoints[i].code.length == 4) {
				ids = ids + gMappoints[i].code + " ";
				metarStations.push(gMappoints[i].code);
			}
		}
	getDataNWS(ids);
	
	if (!metarTimer)
		metarTimer = window.setInterval("getDataNWS('" + ids + "')",60 * 1000 * 15);			// 15 min.
}


function stopMetarInterval()
{
	if (metarTimer)
		window.clearInterval(metarTimer);
}



function updateMetarInterval()
{
	for (var i = 0; i < metarStations.length; i++)
		metarStations.pop();
	
	if (metarTimer)
		window.clearInterval(metarTimer);
	
	startMetarInterval();
}



function loadNWSData(responseStr) 
{	
	var curDate = new Date();
	
	for (var i=0;i<metarStations.length;i++) {												// get all presets
		if (metarStations[i].length == 4) {
			var obj = new Object();
			obj.date = curDate;
			obj.icao = metarStations[i];
			obj.source = 1;



			var tmpposA = responseStr.indexOf(">" + metarStations[i]);		// get latest METAR first
			if (tmpposA == -1) {
					obj.metar = "";
					obj.metarPast = "";
			}
			else {
				tmpposA = tmpposA + 5;
				var tmpposB = responseStr.indexOf("<",tmpposA);
				if (tmpposB == -1) {
					obj.metar = "";
					obj.metarPast = "";
					obj.taf = "";
					obj.err = 2;										// something's messed up with nws data structure
				}
				var metar = responseStr.substring(tmpposA-4,tmpposB);
					obj.metar = metar;
					obj.metarPast = "";
			}

			if (keepPastData && obj.metar != "") {						// get additional past METARs
				obj.metarPast = new Array();
				
				obj.metarPast.push(metar);								// put current METAR first
			
				while (true) {				
					tmpposA = responseStr.indexOf(">" + metarStations[i],tmpposB);		
					if (tmpposA == -1) {
						break;
					}
					else {
						tmpposA = tmpposA + 5;
						tmpposB = responseStr.indexOf("<",tmpposA);
						if (tmpposB == -1) {
							obj.metarPast = "";
							obj.taf = "";
							obj.err = 2;								// something's messed up with nws data structure
							continue;
						}
						metar = responseStr.substring(tmpposA-4,tmpposB);
						obj.metarPast.push(metar);
					}
				}
				obj.metarPastPos = 0;
				
				if (obj.metar.indexOf("NIL") > 0 && obj.metarPast.length > 1) {			// use next METAR if latest is NIL
					obj.metarPastPos = 1;
					obj.metar = obj.metarPast[1];
				}
			}

			tmpposA = responseStr.indexOf(">\n" + metarStations[i]);		// then, get TAFs
			if (tmpposA == -1) {
				obj.taf = "Not Available.";											// taf is not there
				obj.err = 0;
				putMetarTaf(metarStations[i],obj.metar,obj.taf);
				delete obj;			
				continue;
			}
			tmpposA = tmpposA + 5;
			tmpposB = responseStr.indexOf("<",tmpposA);
			if (tmpposB == -1) {
				obj.taf = "Not Available.";
				obj.err = 2;											// something's messed up with nws data structure
				putMetarTaf(metarStations[i],obj.metar,obj.taf);
				delete obj;			
				continue;
			}
			var taf = responseStr.substring(tmpposA-3,tmpposB);			// everything went fine
			obj.taf = taf;
			obj.err = 0;
	
	
			putMetarTaf(metarStations[i],obj.metar,obj.taf);
			delete obj;
		}
		else {
			putMetarTaf(metarStations[i],"","");
		}
	}
}



function putMetarTaf(id,metar,taf)
{
	for (var j=0;j<gMappoints.length;j++) {
		if (id.indexOf(gMappoints[j].code) >= 0) {
			gMappoints[j].metar = metar;
			gMappoints[j].taf = taf;
			gMappoints[j].flightrule = parseFlightRules(metar);
//			break;
		}
	}
}
				
				


// -----------------------------------------------------------
// CONNECTION HANDLING
// -----------------------------------------------------------

function processNWSReq() 
{
	var err = 0;
	

    if (xml_request.readyState == 4) {
        // only if "OK"
//		alert(xml_request.status + "//" + xml_request.responseText);
        if (xml_request.status == 200) {
	//		alert(xml_request.responseText);
			loadNWSData(xml_request.responseText);			// into global objects array "actData"
			displayMPList();
			document.getElementById("footer").innerText = displayStatusLine("footer","NWS",0);
		}
		else {
			if (firstConnection) {
	//			displayMessage("Failed to retrieve data!",true);	// there's nothing else to show :-(
				document.getElementById("footer").innerText = displayStatusLine("footer","---",2);
	//			stopProgress();
			}
			else {
	//			actData = lastData;
		//		err = parseNWSData(0);
//				stopProgress();
	//			
		//		displayData();								// display Old Data
		//		displayMessage("Data might not be current!",true);
				document.getElementById("footer").innerText = displayStatusLine("footer","NWS",1);
			}
			alert("Failed to retrieve data (" + xml_request.status + "/" + err + ")");
		}
	}
	else {
//		stopProgress();
		document.getElementById("footer").innerText = displayStatusLine("footer","-?-",2);
//		alert(xml_request.status + "//" + xml_request.readyState);
	}
}


function getDataNWS(station_ids)
{	
	xml_request = false;
    if (typeof XMLHttpRequest != 'undefined') {
    	try {
			xml_request = new XMLHttpRequest();
        } catch(e) {
			xml_request = false;
        }
    } else if(window.ActiveXObject) {
       	try {
        	xml_request = new ActiveXObject("Msxml2.XMLHTTP");
      	} catch(e) {
        	try {
          		xml_request = new ActiveXObject("Microsoft.XMLHTTP");
        	} catch(e) {
          		xml_request = false;
        	}
		}
    }
	if(xml_request) {
		var localfile = document.URL.indexOf("file:",0);
		if (localfile < 0)
			var url = document.URL.substring(0,(document.URL.indexOf(".ch/") + 4)) + "cgi-local/";
		else
			var url = "http://flightmap.ch/cgi-local/";

		
		xml_request.onreadystatechange = processNWSReq;
		url += "NSWQuery.pl?station_ids=" + station_ids;
		xml_request.open("GET",url,true);
		xml_request.send(null);
	
	
//		if (keepPastData)
//			xml_request.send("station_ids=" + station_ids + "&chk_metars=on&chk_tafs=on&hoursStr=" + keepPastDataHrs + "&std_trans=standard&submit=1");
//		else
//			xml_request.send("station_ids=" + station_ids + "&chk_metars=on&chk_tafs=on&hoursStr=0&std_trans=standard&submit=1");
	}
	
}




function displayStatusLine(elem,sourceStr,err)
{
	if (!gConfigShowMetar)
		return "";
	
	var ampmText = "";

	var lastUpdate = new Date();
	if (gMetricFormat) {
		var nowStr = ((lastUpdate.getHours() < 10) ? "0" + lastUpdate.getHours() : lastUpdate.getHours()) + ":"
					+ ((lastUpdate.getMinutes() < 10) ? "0" + lastUpdate.getMinutes() : lastUpdate.getMinutes());
		ampmText = "";
	}
	else {
		if (lastUpdate.getHours() >= 0 && lastUpdate.getHours() <= 11) {
			var nowStr = ((lastUpdate.getHours() < 10) ? "0" + lastUpdate.getHours() : lastUpdate.getHours()) + ":"
						+ ((lastUpdate.getMinutes() < 10) ? "0" + lastUpdate.getMinutes() : lastUpdate.getMinutes());
			ampmText = " AM";
		}
		else {
			var usHours = (lastUpdate.getHours() == 12) ? 12 : lastUpdate.getHours() - 12;
			var nowStr = ((usHours < 10) ? "0" + usHours : usHours) + ":"
						+ ((lastUpdate.getMinutes() < 10) ? "0" + lastUpdate.getMinutes() : lastUpdate.getMinutes());
			ampmText = " PM";
		}
	}
		
	var utcText = ((lastUpdate.getUTCHours() < 10) ? "0" + lastUpdate.getUTCHours() : lastUpdate.getUTCHours()) + ":"
					+ ((lastUpdate.getMinutes() < 10) ? "0" + lastUpdate.getMinutes() : lastUpdate.getMinutes());
	
	var updateText = "METAR updated at ";
	if (elem != null)
		document.getElementById(elem).style.color = "#009933";
	if (gShowLocalTime)
		return updateText + nowStr + ampmText + ". " + "Source: " + sourceStr + ".";
	else
		return updateText + nowStr + ampmText + " (" + utcText + " UTC). " + "Source: " + sourceStr + ".";

	if (err > 0) {
		var updateText = "METAR update failed at ";
		if (elem != null)
			document.getElementById(elem).style.color = "red";
		return updateText + nowStr + ampmText + ". " + "Source: " + sourceStr + ".";
	}
}


// -----------------------------------------------------------
// METAR PARSING
// -----------------------------------------------------------



function parseFlightRules(metarstr)
{
	var tmpstr = metarstr.substring(metarstr.indexOf(" ")+1,metarstr.length)

	var limit = tmpstr.length;

	var trend = tmpstr.indexOf("BECMG");					// omit trend data for flight condition evaluation
	if (trend > 0)
		limit = trend;
	var trend = tmpstr.indexOf("TEMPO");
	if (trend > 0 && trend < limit)
		limit = trend;
	var trend = tmpstr.indexOf("FM");
	if (trend > 0 && trend < limit)
		limit = trend;
	var trend = tmpstr.indexOf("INTER");
	if (trend > 0 && trend < limit)
		limit = trend;
	var trend = tmpstr.indexOf("RMK");
	if (trend > 0 && trend < limit)
		limit = trend;

	var mstr = tmpstr.substring(0,limit);

	if (mstr.length < 12)
		return "";


	var ceiling = 0;
	if (mstr.indexOf("CAVOK") >= 0 || mstr.indexOf("CLR ") >= 0 || mstr.indexOf("SKC") >= 0 || mstr.indexOf("NSC") >= 0 || mstr.indexOf("NCD") >= 0) {
		ceiling = 5000;
	}
	else {
		ceiling = 5000;
		var bkn = mstr.indexOf("BKN");
		if (bkn >= 0)
			ceiling = parseInt(mstr.substr(bkn+3,3),10) * 100;
			
		var ovc = mstr.indexOf("OVC");
		if (ovc >= 0) {
			var ovcCeiling = parseInt(mstr.substr(ovc+3,3),10) * 100;
			if (ovcCeiling < ceiling)
				ceiling = ovcCeiling;
		}
	}
	

	var visibility = 0;
	if (mstr.indexOf("9999") >= 0 || mstr.indexOf("10SM") >= 0) {
		visibility = 6;
	}
	else {
		var tmp = mstr.indexOf("SM ");
		if (tmp > 0) {
			var tmp3 = mstr.indexOf("/");
			if (tmp3 > 0 && tmp3 < tmp) {
				var miles = parseInt(mstr.substr(tmp3-1,1),10) / parseInt(mstr.substr(tmp3+1,1),10);
				visibility = miles;
			}
			else {
				var tmp2 = mstr.lastIndexOf(" ",tmp);
				var miles = parseInt(mstr.substring(tmp2+1,tmp),10);
				visibility = miles;
			}
		}
		else {
			var tmp = mstr.indexOf("KT ");
			if (tmp > 0) {
				if (mstr.charAt(tmp + 6) == "V")
					tmp = tmp + 10;
				
				var tmp2 = mstr.indexOf("0 ",tmp);
				if (mstr.charAt(tmp2-4) == " ") {
					visibility = parseInt(mstr.substr(tmp2-3,4),10) / 1.609344 / 1000;
				}
				else {
					visibility = 6;
				}
			}
			else {
				var tmp = mstr.indexOf("MPS ");
				if (tmp > 0) {
					if (mstr.charAt(tmp + 7) == "V")
						tmp = tmp + 11;
						
					var tmp2 = mstr.indexOf("0 ",tmp);
					if (mstr.charAt(tmp2-4) == " ") {
						visibility = parseInt(mstr.substr(tmp2-3,4),10) / 1.609344 / 1000;
					}
					else {
						visibility = 6;
					}
				}
				else {
					visibility = 6;
				}
			}
		}
	}

	if (ceiling < 500 || visibility < 1)
		return "LIFR";
	else
		if ((ceiling >= 500 && ceiling < 1000) || (visibility >= 1 && visibility < 3))
			return "IFR";
		else
			if ((ceiling >= 1000 && ceiling < 3000) || (visibility >= 3 && visibility < 5))
				return "MVFR";
			else
				if (ceiling >= 3000 && visibility >= 5)
					return "VFR";
				else
					return "";
}

