var timerID = 0; // used internaly
var prevFrameTime = 0; // previous value of "current time", to compute delta time
var prevGetInfoTime = 0;
var isFirstTime = true;
var cityIndexList = new Array(cityList.length);
for (var i in cityList) cityIndexList[cityList[i].i] = i;



function formatNumber(value, numDecimals, decimalChar) {
	if (numDecimals < 1) numDecimals = 1;
	if (numDecimals > 8) numDecimals = 8;
	if (decimalChar == null) decimalChar = ".";
	var factor = 1;
	for (var i = 0; i < numDecimals; i++) factor *= 10;
	value = Math.floor(factor * value) / factor;
	value = value.toString();
	var dotPos = value.indexOf(".");
	if (dotPos < 0) dotPos = value.indexOf(",");
	if (dotPos >= 0) {
		value = value.substring(0, dotPos) + decimalChar + value.substring(dotPos + 1);
		var numZerosToAdd = numDecimals - (value.length - dotPos);
		while (numZerosToAdd >= 0) {
			value += "0";
			numZerosToAdd--;
		}
	}
	else {
		value += decimalChar;
		for (var i = 0; i < numDecimals; i++) value += "0";
	}
	return value;
}


function createHttpRequester() {
	if (window.XMLHttpRequest) { // code for Mozilla, Safari, etc
		try {
			return new XMLHttpRequest();
		} 
		catch(e) {}
	} 
	else if (window.ActiveXObject) { // IE/Windows ActiveX version
		try {
			return new ActiveXObject("Msxml2.XMLHTTP");
		} 
		catch(e) {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch(e) {}
		}
	}
	return null;
}


function getRemoteFile(url, callbackFunc, callbackData) {
	var xmlHttp = createHttpRequester();
	if (xmlHttp == null) return null;
	try {
		var isAsync = (callbackFunc != null);
		xmlHttp.open("GET", url, isAsync);
		xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
		
		if (isAsync) {
			xmlHttp.onreadystatechange = function() {
				if (xmlHttp.readyState == 4) {
					callbackFunc(xmlHttp.responseText, callbackData);
					delete xmlHttp.onreadystatechange;
				}
			};
		}
		
		xmlHttp.send("");
		if (isAsync) return null; // later
		return xmlHttp.responseText;
	}
	catch (e) {}
	return null;
}


function onGetData(infoData, userData) {
    if ((infoData == null) || (infoData == "")) return;
    
    infoData = infoData.split("\n");
    for (var i in infoData) {
        var info = infoData[i].split(",");
        if (info.length >= 2) {
            var cityIndex = info[0];
            var temperature = info[1];
            if ((cityIndex >= 0) && (cityIndex < cityList.length)) {
                cityList[cityIndexList[cityIndex]].t = parseFloat(temperature) + (Math.random() - 0.5);
            }
        }
    }
    
    if (isFirstTime) {
        document.styleSheets[0].cssRules[0].style.fontSize = ((FONT_SIZE > 0) ? FONT_SIZE : Math.floor((screen.width * 26) / 1280)) + 'px';
        isFirstTime = false;
        computeDynamics(0);
        renderInfo();
    }
}


function cityCompareFunc(city1, city2) {
    var t1 = city1.t2 + city1.v2;
    var t2 = city2.t2 + city2.v2;
	if (t1 < t2) return +1;
	else if (t1 > t2) return -1;
	if (city1.n < city2.n) return +1;
	else if (city1.n > city2.n) return -1;
	return 0;
}


function renderInfo() {
    var listElem = document.getElementById("list");
    if (listElem == null) return;
    
    if (SORT_CITIES) cityList.sort(cityCompareFunc);
    for (var i in cityList) cityIndexList[cityList[i].i] = i;
    
    var text = "";
    var isFirst = true;
    for (var i in cityList) {
        if (cityList[i].t != 1000) {
            if (isFirst) isFirst = false;
            else text += SHOW_TEMPERATURES ? "<br />" : ", ";
            text += cityList[i].n;
            if (SHOW_TEMPERATURES) text += " (" + formatNumber(cityList[i].t2 + cityList[i].v2, 4, ".") + ", " + formatNumber(cityList[i].v2, 4, ".") + ")";
        }
    }
    
    listElem.innerHTML = text;
}


function computeDynamics(deltaTime) {
    for (var i in cityList) {
        if (cityList[i].t2 == 1000) {
            cityList[i].t2 = cityList[i].t;
            cityList[i].v0 = 0;
            cityList[i].v1 = 0;
            cityList[i].v2 = 0;
        }
        var f = deltaTime / TEMPERATURE_SMOOTH_FACTOR;
        if (f > 1) f = 1;
        cityList[i].t2 += f * (cityList[i].t - cityList[i].t2);
        
        var rand = (2*Math.random()-1) * RANDOM_POWER;
        f = deltaTime / RANDOM_SMOOTH_FACTOR;
        if (f > 1) f = 1;
        cityList[i].v0 += f * (rand - cityList[i].v0);
        cityList[i].v1 += f * (cityList[i].v0 - cityList[i].v1);
        cityList[i].v2 += f * (cityList[i].v1 - cityList[i].v2);
    }
}


function onUpdateTimer() {
	if (timerID) {
		clearTimeout(timerID);
		timerID = 0;
	}
	
	var newFrameTime = (new Date()).getTime();
	if (prevFrameTime == 0) prevFrameTime = newFrameTime;
	var frameDeltaTime = newFrameTime - prevFrameTime;
	prevFrameTime = newFrameTime;
	
	if (prevGetInfoTime == 0) prevGetInfoTime = newFrameTime;
	if (newFrameTime - prevGetInfoTime > SERVER_UPDATE_INTERVAL) {
	    prevGetInfoTime = newFrameTime;
	    getRemoteFile("getinfo.php", onGetData, 0);
	}
	
	computeDynamics(frameDeltaTime);
	renderInfo();
	
	timerID = setTimeout("onUpdateTimer()", Math.floor(RENDER_UPDATE_INTERVAL + Math.random() * (RENDER_UPDATE_INTERVAL_MAX - RENDER_UPDATE_INTERVAL)));
}

getRemoteFile("getinfo.php", onGetData, 0);
timerID = setTimeout("onUpdateTimer()", RENDER_UPDATE_INTERVAL);
