// simple_it_time.js
//
// Changelog:
// ver. 0.6 	2010-07-09	Eliminata l'indicazione dei secondi, ridotta la frequenza delle chiamate e
//							semplificata la gestione del TZ e del DST 
// ver  0.5 	2010-04-01 	Esclude Opera per problema sull'ora locale
// ver. 0.4  -  2009-10-27	Limita il nulero di chiamate al time server 
// ver. 0.3  -  2009-03-27	Correzione errore DST client 
// ver. 0.2	 -  2008-12-23  Modifica formato data/ora
// ver. 0.1  -  2008-11-19	Prima versione

var timeServer = "/ntp/itRefTime.php";	// URL del time server
var nRichiesteInviate = 0;
var nRichiesteRicevute = 0;
var startTime;					// Ora di avvio dello script 
var ultimaSinc = 0;				// Ora dell'ultime sicronizzazione
var clientTzOffset;			// Timezone offset del client
var serverTzOffset;			// Timezone offset del server
var txTime;					// Ora del client di invio della richiesta
var rxTime;					// Ora del client di ricezione della richiesta
var serverTime;				// Ora del server
var timeOffset;				// Scarto di tempo tra l'ora del client e del server
var dstIsOn;				// Vale uno se e' in vigore l'ora legale, altrimenti vale 0 
var timeCorrection;			// Correzione in ms da applicare all'ora del client 
var precAggiornamento;		// ora del precedente aggiornamento della pagina
var nSecondiPA;				// numero di secondi del precedente aggioranmento dell'orologio

var httpRequest;	
// Crea l'oggetto httpRrequest per connetersi col server
// se non ci riesce e' inutile proseguire lo script
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
    var httpRequest = new XMLHttpRequest();
    if (httpRequest.overrideMimeType) {
    	httpRequest.overrideMimeType('text/xml');
    }
} else if (window.ActiveXObject) { // IE
	try {
    	var httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
	    try {
		    var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        catch (e) {}
    }
    if (!httpRequest) {
    	alert('Giving up :( Cannot create an XMLHTTP instance');
    }
}

/* if (navigator.appName == "Opera") {
	throw "Applicazione non compatibile con Opera";
} */

GDS = ["Domenica", "Luned&igrave;", "Marted&igrave;", "Mercoled&igrave;", 
	"Gioved&igrave;", "Venerd&igrave;", "Sabato"];

MESE =["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno",
	"luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"];



function timer() {
	// programma tutte le funzioni di aggiornamento della pagina
	// il tempo di aggiornamento in millisecondi
	//if (richiestaInviata === false) {
	window.setTimeout("inviaRichiesta()", 500); 
	//}
	window.setTimeout("aggiornaOra()", 500); 
}


function aggiornaOra() {
	var adesso = new Date().getTime();
	if (precAggiornamento === undefined) {
		precAggiornamento = adesso;
	} else {
		if (Math.abs(adesso - precAggiornamento) > 1000) { 
			// possibile cambio di ora sul client, resetta tutte le correzioni
			timeOffset = timeCorrection = startTime = correzionePrec = undefined;
			ultimaSinc = 0;
			precAggiornamento = adesso;
			timer();
			return;
		}	
		if ((nRichiesteInviate - nRichiesteRicevute) > 3) { 
			// il server non risponde, cancella l'ora visualizzata e interrrompe le richieste
			elemId = document.getElementById("oraEsatta");
		 	elemId.innerHTML = "&nbsp;";
			return;
		}	
		precAggiornamento = adesso;
	}
	
	if (timeCorrection !== undefined) {
		/* // client DST detection
		stTime = (new Date(2008, 0)).getTimezoneOffset();
		dlTime = (new Date(2008, 6)).getTimezoneOffset();
		dlOffset = dlTime - stTime; 
		if (dlOffset !=0 ) {
			if (((new Date()).getTimezoneOffset() - stTime) == dlOffset) {
				var clientDST = 1;
			} else {
				var clientDST = 0;
			}
		} else {
			var clientDST = 0;
		} */
		var clientTime = new Date().getTime();
		
		// Ora locale italiana 
		var oraLocale = new Date(clientTime + timeCorrection); 
		/*if (dstIsOn == clientDST) {
			var oraLocale = new Date(clientTime + timeCorrection); 
		} else {
			if (clientDST == 0){
				var oraLocale = new Date(clientTime + timeCorrection + dlOffset * 60000);
			} else {
				var oraLocale = new Date(clientTime + timeCorrection - dlOffset * 60000);
			}
			
		}*/
		
		if (nSecondiPA === undefined) { 
			nSecondiPA = oraLocale.getSeconds();
		} else {
			if (nSecondiPA == oraLocale.getSeconds()) {
				timer(); 
				return;
			}
		}
		
		// Aggiorna l'informazione sulla pagina
		var dataOraLocale = GDS[oraLocale.getDay()] + ", " 
			+ addZero(oraLocale.getDate()) + " "
			+ MESE[oraLocale.getMonth()] + " "
			+ String(oraLocale.getFullYear()) + " &nbsp; "
			+ addZero(oraLocale.getHours()) + ":"
			+ addZero(oraLocale.getMinutes()) + "  ";
		elemId = document.getElementById("oraEsatta");
	 	elemId.innerHTML = dataOraLocale;
	
	 	nSecondiPA = oraLocale.getSeconds();
	} else {
		elemId = document.getElementById("oraEsatta");
	 	elemId.innerHTML = "&nbsp;";
	} 
	
	// rilancia il timer
 	timer(); 
}


function inviaRichiesta() {
	var adesso = new Date().getTime();
	
	// controlla che sia stata definita l'ora di avvio dello script
	if (startTime === undefined) {
		startTime = adesso;
	}
	
	// tempo trascorso dall'avvio (in secondi)
	var differenza = (adesso - startTime)/1000; 	
	
	// Frequenza delle sincronizzazioni
	if (differenza < 300) {
		// ogni 10 secondi nei primi 5 minuti
		var prossimaSinc = ultimaSinc + 10000;
	} else {
		// ogni minuto dopo i primi 5 minuti
		var prossimaSinc = ultimaSinc + 60000;
	}
	
	// Se e' trascorso il tempo minimo, invia la richiesta di sincronizzazione
	if (adesso >= prossimaSinc) {
		//richiestaInviata = true;
		ultimaSinc = new Date().getTime();
		
		// Invia una richiesta al time server
		txTime = new Date().getTime();
		stringa = timeServer + "?txTime=" + String(txTime);
		httpRequest.open("GET", stringa, true);
		httpRequest.setRequestHeader("Cache-Control","no-store,no-cache,must-revalidate");
		httpRequest.setRequestHeader("Pragma", "no-cache");
		httpRequest.onreadystatechange = elaboraRisposta;
		httpRequest.send(null);
		nRichiesteInviate ++;
	}		
}


function elaboraRisposta() {
	if (httpRequest.readyState != 4) {
		// La risposta ricevuta non e' completa
		return;
	}
	
	if (httpRequest.status != 200) {
    	// Il server ha segnalato un errore
    	return;
	}
    var responseString = httpRequest.responseText;
	rxTime = new Date().getTime();
    
	// Estrae l'informazione di tempo e di TZ Offset
	var arrString = responseString.split("\n"); 
	if (arrString.length != 5) {
		// Il server ha fornito una risposta incompleta
		return;
	}
	
	txTime = parseInt(arrString[0], 10);
	
	serverTime = parseInt(arrString[1], 10);
	serverTzOffset= parseInt(arrString[2], 10) * 1000;
	dstIsOn = parseInt(arrString[3], 10);
	if (serverTime == 0 || isNaN(serverTime)) {
		// Il server ha fornito un informazione anomala
		return;
	}	
	if (txTime == 0 || isNaN(txTime)) {
		// Il server ha fornito un informazione anomala
		return;
	}
		
	nRichiesteRicevute ++;
	 		
	// Aggiorna la correzione da applicare all'orologio del client
	calcolaCorrezione ();
}

function calcolaCorrezione () {
	var n1 = 0;
	// Rileva il Timezone offset del client
	clientTzOffset = new Date().getTimezoneOffset()*60*1000;
	
	// Calcola lo scarto di tempo tra client e server
	if (rxTime >= txTime) {
 		n1 = (rxTime + txTime) / 2;
 		timeOffset = serverTime - n1 ;
	} else {
		timeOffset = timeCorrection = startTime = correzionePrec = undefined;
		ultimaSinc = 0;
		timer();
		return;
	}
	
 	// Calcola la correzione da applicare all'orologio locale
 	if (timeCorrection !== undefined) {
 		var correzionePrec = timeCorrection; 
 	}	
 	if (timeOffset !== undefined) {
 		timeCorrection = timeOffset + clientTzOffset + serverTzOffset;
 	}
}


function addZero(valIn) {
	// Converte il numero in stringa e aggiunge uno zero iniziale 
	// ai numeri di una sola cifra
	if (valIn < 10) {
		stringaOut = "0" + 	String(valIn);
	} else {
		stringaOut = String(valIn);
	}
	return stringaOut;
}

