/** 	AJAX Komponente zur Anzeige des laufenden Tracks
 *		endo.ch 2006, Christoph Berger	
 */

window.onload = initCurrentSong;

// exemplarischer Aufbau des Track-Objekts (JSON, AJAX Antwort), wird auf der HTML-Seite überschrieben
var currentTrack = {
	'name': 'unknown',
	'artist': 'unknown',
	'album': 'unknown',
	'id': -1,
	'year': -1,
	'state': 'playing',
	'timeSec': 1,
	'elapsed': 0,
	'artwork': 'no',
	'artworkBig': 'no',
	'context': 'offline',
	'source' : 'unknown'
};

var currentSongSize = 'default';


function CurrentSong(size, urlPrefix)
{
	this.isBig = (size=='big' ? true : false);
	
	this.interval = 1000; 		// Millisekunden (Hauptschleife inkl. Progressbar Update)
	this.ajaxIntervalSec = 15; 	// Sekunden
	
	this.ajaxScriptUrl = urlPrefix+'ajaxagent.php';
	if (window.location.host.match(/(^endo\.ch)|(www\.endo\.ch)/)) 
		this.ajaxScriptUrl = 'http://'+window.location.host+'/staff/current_tune/ajaxagent.php';
	this.loadingIndicator = urlPrefix + 'indicator_arrows'+(this.isBig ? '600' : '')+'.gif';
	
	this.track = '';
	this.timestamp = new Date();
	this.handler = -1;
	this.runningSecs = 0;
	this.lastAjaxTime = 0;
	this.requestLock = false;
	this.requestWaiting = false;
	
	this.barElement = document.getElementById('progressbar');
	this.barMaxWidth = 180;
	this.xmlhttp = new AjaxRequest(this.ajaxScriptUrl, catchAjaxReadyState);
		
	
	this.doUpdate = function (selfname) {
		this.selfName = selfname || this.selfName;
		var jetzt = new Date();
		this.runningSecs = Math.floor((jetzt.getTime()-this.timestamp.getTime())/1000);
		
		if (this.track.state == 'playing')
			this.drawProgressBar();
		
		var doUpdate = false;
		var requestLock = (this.xmlhttp.req.readyState == 0 || this.xmlhttp.req.readyState == 4) ? false : true;
		
		// regelmässige Abfrage
		if (this.runningSecs - this.lastAjaxTime >= this.ajaxIntervalSec)
			doUpdate = true;	
		
		// vorzeitige Abfrage nach Ende des Tracks 
		if (this.track.elapsed+this.runningSecs >= this.track.timeSec+3		// 3 Sekunden nach Songende	
		&& this.track.elapsed+this.runningSecs <= this.track.timeSec+this.ajaxIntervalSec	// höchstens ein ajaxIntervalSec lang
		&& this.runningSecs-this.lastAjaxTime >= 2							// max alle 2 Sekunden
		&& this.track.context == 'up to date')								// wenn (bei der letzten Abfrage) aktuelle Daten vorliegen
			doUpdate = true;	

		// laufender Request 
		if (this.requestWaiting 									// die Angaben werden demnächst aktualisiert 	
		&& this.runningSecs-this.lastAjaxTime >= 2)					// wenn (bei der letzten Abfrage) aktuelle Daten vorliegen
			doUpdate = true;	

		if (doUpdate && !requestLock){
			this.lastAjaxTime = this.runningSecs;
			this.xmlhttp.url = this.ajaxScriptUrl+'?dirty='+jetzt.getTime();
			this.xmlhttp.doRequest();
		}
		
					
		// Neudurchgang nach Ablauf von Interval
		var callString =this.selfName+'.doUpdate("'+this.selfName+'")';
		this.handler = window.setTimeout(callString, this.interval);
	}
	
	this.setTrack = function (track) {
		this.track = track;
		this.timestamp = new Date();
		this.runningSecs = 0;
		
		if (this.track.elapsed > this.track.timeSec -(2*this.ajaxIntervalSec) || this.track.context == 'requesting')
			this.lastAjaxTime = 0;	// Wenn Song fast fertig gespielt, normal synchronisieren, ...
		else
			this.lastAjaxTime = Math.floor(this.ajaxIntervalSec*Math.random()); //sonst regelmässige Abfragen etwas verteilen

		document.getElementById('tune_name').innerHTML = track.name;
		document.getElementById('tune_artist').innerHTML = track.artist;
		document.getElementById('tune_album').innerHTML = track.album;
		document.getElementById('tune_year').innerHTML = track.year;
		document.getElementById('tune_artwork').src = (this.isBig && track.artworkBig != 'no') ? track.artworkBig : track.artwork;
		/*if (this.isBig && track.artworkBig != 'no') {
			this.preloadImage.src = track.artworkBig;
		}*/
		this.drawProgressBar();		
	}
	
	this.drawProgressBar = function() {
		var w = Math.floor((this.track.elapsed+this.runningSecs)/this.track.timeSec*this.barMaxWidth)+1;
		w = Math.min(w, this.barMaxWidth);
		this.barElement.style.width = w+'px';
		
		var time = Math.min(this.track.elapsed+this.runningSecs, this.track.timeSec);
		var sec = time%60;
		var title = 'Spielzeit ';
		title += (Math.floor(time/60))+'\''+(sec<10 ? '0' : '')+(sec)+' von '+(Math.floor(this.track.timeSec/60))+'\''+(this.track.timeSec%60<10 ? '0' : '')+(this.track.timeSec%60);
		document.getElementById('progressbardiv').setAttribute('title', title);	
		document.getElementById('progressbar').setAttribute('title', title);	
	}
	
	this.checkNewData = function (newtrack){
		if (!(newtrack)){	// Übertragungsfehler, Client oder endo.ch offline 
			newtrack = new CloneObject(this.track);
			newtrack.state = 'stopped';
		}
		
		if (newtrack.context == 'requesting'){	// Warten auf Info
			if (!this.requestWaiting){
				this.requestWaiting = true;
				document.getElementById('tune_artwork').src = this.loadingIndicator;
			}
			return;
		}

		if (this.track.state == 'stopped' && newtrack.state == 'playing'){
			document.getElementById('progressbardiv').style.display = 'block';
			document.getElementById('tune_titletext').innerHTML = tune_titletext.playing;
		}
		if (this.track.state == 'playing' && newtrack.state == 'stopped'){
			document.getElementById('progressbardiv').style.display = 'none';			
			document.getElementById('tune_titletext').innerHTML = tune_titletext.stopped;
			this.track.state = 'stopped';
		}
		if (newtrack.context == 'up to date' && newtrack.state == 'playing'){
			if (newtrack.id != this.track.id || newtrack.state != this.track.state) {
				window.clearTimeout(this.handler);
				this.requestWaiting = false;
				this.setTrack(newtrack);
				this.doUpdate(this.selfName);
				
				return;
			}
		}
		
		// Fallback aus dem requestWaiting Modus
		if (this.requestWaiting){
			this.requestWaiting = false;
			this.setTrack(newtrack);
		}
	}
	
	this.addListener = function(element, event, listener, bubble) {
		if(element.addEventListener) {
			if(typeof(bubble) == 'undefined'){
				bubble = false;
			}
			element.addEventListener(event, listener, bubble);
		} else if(document.attachEvent) {
			element.attachEvent("on" + event, listener);
		}
	}
	
	
	/*if (this.isBig) {
		this.preloadImage = new Image();
		this.addListener(this.preloadImage, 'load', function(){document.getElementById('tune_artwork').src = current_song.preloadImage.src});
	}*/
}
		
	
function initCurrentSong(){ 
	current_song = new CurrentSong(currentSongSize, urlPrefix);
	current_song.setTrack(currentTrack);
	if (currentSongSize == 'big') current_song.lastAjaxTime = -60; // Sofortupdate
	if (currentTrack.context == 'requesting'){	// Warten auf Info
		current_song.requestWaiting = true;
		document.getElementById('tune_artwork').src = current_song.loadingIndicator;
		currentTrack.state = 'stopped';
	}		
	current_song.doUpdate("current_song");
}

function catchAjaxReadyState(){
	if (current_song.xmlhttp.req.readyState == 4){
		var response = current_song.xmlhttp.req.responseText;
		//console.log(response);
		eval ('newtrack = '+response);
		//console.log(current_song.track, newtrack);
		current_song.checkNewData(newtrack);
	}
}


function AjaxRequest(u,f,m,b,h,s)
{
	this.url = u; //console.log(u);
	this.wState = f || function() { };
	this.method = m || "GET";
	this.body = b || null;
	this.headers = h || false;
	this.sync = s || true;
	this.abortReq = false;
	
	this.req = (window.XMLHttpRequest) ? new XMLHttpRequest() :
				((window.ActiveXObject) ? new ActiveXObject("Microsoft.XMLHTTP") : false);
	
	this.doRequest = doRequest;
	function doRequest(){
		this.req.open(this.method, this.url, this.sync);
		if (this.headers){
			for (var i=0; i<this.headres.length; i+=2){
				this.req.setRequestHeader(this.headers[i], this.headers[i+1]);
			}
		}
		this.req.onreadystatechange = this.wState;
		this.req.send(this.body);
	}
}


function CloneObject(original) {
	 for (var i in original) {
		this[i] = original[i];
	}
}
