// runAfter
var runAfter = {
	functions: new Array(),
	
	init: function() {
		runAfter.timer();
	},
	add: function(f,delay, sender) {
		for(var i=0;i<runAfter.functions.length; i++) {
			o=runAfter.functions[i];
			if (o.func==f) {
				o.delay=delay;
				return;
			}
		}

		o=new Object();
		o.func=f;
		o.delay=delay;
		o.sender=sender;
		runAfter.functions.push(o);
	},
	timer: function() {
		for(var i=0;i<runAfter.functions.length; i++) {
			o=runAfter.functions[i];
			if (o.delay==0) {
				o.func(o.sender);
				runAfter.functions.splice(i,1);
			}
			else o.delay--;
		}
		setTimeout(runAfter.timer,1000);
	},
	isIn: function(f) {
		for(var i=0;i<runAfter.functions.length; i++) {
			o=runAfter.functions[i];
			if (o.func==f) return true;
		}
		return false;
	}
}

// EIBCommunicator
var EIBCommunicator = {
	listeners: new Object(),
	
	add: function(o) {
		var l=o.getListeningObject();
		for(var i=0;i<l.length; i++)
			if (l[i]) {
		    	if (!EIBCommunicator.listeners[l[i]]) EIBCommunicator.listeners[l[i]]=Array();
	    		EIBCommunicator.listeners[l[i]].push(o);
    		}
	},
	remove: function(o) {
		for(key in EIBCommunicator.listeners) {
			for (var i=0;i<EIBCommunicator.listeners[key].length; i++) {
				if (EIBCommunicator.listeners[key][i]==o) EIBCommunicator.listeners[key].splice(i,1);
			}
			if (EIBCommunicator.listeners[key].length==0) delete EIBCommunicator.listeners[key];
		}
	},
	eibWrite: function(obj,value, successCallBack) {
	    if (!obj)
	        return;
		var body = "<write><object id='"+obj+"' value='"+value+"'/></write>";

		req = jQuery.ajax({ type: 'post', url: 'linknx.php?action=cmd', data: body, processData: false, dataType: 'xml' ,
			success: function(responseXML, status) {
				var xmlResponse = responseXML.documentElement;
				if (xmlResponse.getAttribute('status') == 'success') {
		   			EIBCommunicator.sendUpdate(obj, value);
				}
				else
					alert("error: "+xmlResponse.textContent);
				if (successCallBack) successCallBack(response);
			}
		})
	},
	sendUpdate: function(obj,value) {
		var listeners = EIBCommunicator.listeners[obj];
		if (listeners) {
			for (var i=0;i<listeners.length; i++)
				listeners[i].updateObject(obj,value);
		}
	},
	eibRead: function(objects,successCallBack) {
		if (objects.length > 0) {
			var body = '<read><objects>';
			for (i=0; i < objects.length; i++)
        	    if (objects[i])
				    body += "<object id='" + objects[i] + "'/>";
			body += "</objects></read>";

			req = jQuery.ajax({ type: 'post', url: 'linknx.php?action=cmd', data: body, processData: false, dataType: 'xml',
				success: function(responseXML, status) {
					var xmlResponse = responseXML.documentElement;
					if (xmlResponse.getAttribute('status') != 'error') {
						// Send update to subscribers
						var objs = xmlResponse.getElementsByTagName('object');
						if (objs.length == 0)
								EIBCommunicator.sendUpdate(objects, xmlResponse.childNodes[0].nodeValue);	
						else {
							for (i=0; i < objs.length; i++) {
								var element = objs[i];
								EIBCommunicator.sendUpdate(element.getAttribute('id'),element.getAttribute('value'));
							}
						}
					}
					else
						alert("error: "+xmlResponse.textContent);
					if (successCallBack) successCallBack(response);
				}
			});
		}
	},
	loadObjectList: function() {
		var body = '<read><config><objects/></config></read>';
		req = jQuery.ajax({ type: 'post', url: 'linknx.php?action=cmd', data: body, processData: false, dataType: 'xml',
			success: function(responseXML, status) {
				var xmlResponse = responseXML.documentElement;
				if (xmlResponse.getAttribute('status') != 'error') {
					UIController.setObjectsList(xmlResponse);
				}
				else
					alert("error: "+xmlResponse.textContent);
			}
		});
	},
	updateAll: function() {
		var obj = new Array();
		for(key in EIBCommunicator.listeners)
			obj.push(key);
		EIBCommunicator.eibRead(obj);
	},
	periodicUpdate: function() {
		EIBCommunicator.updateAll();
		setTimeout('EIBCommunicator.periodicUpdate()', 10000);
	},
	removeAll: function() {
		for(key in EIBCommunicator.listeners) 
			delete EIBCommunicator.listeners[key];
	}
}

// UIController
var UIController = {
	objects: new Array(),
	editMode: false,
	leftOffset: null,
	topOffset: null,
	currentZone: '',
	setConfig: function(doc, name) {
		this.config = doc;
		this.designName = name;
	},
	getDesignName: function() {
		return this.designName;
	},
	setObjectsList: function(doc) {
		UIController.objectlist = doc;
		$('object',doc).each(function() {
			var id = this.getAttribute('id');
			var type = this.getAttribute('type');
			var option = "<option value='"+id+"'>"+id+"</option>";
			if (type == "EIS5") {
				$('#newThermostatWTempObject').append($(option));
				$('#newThermostatTempObject').append($(option));
			}
			else if (type == "EIS6") {
				$('#newDimmerValueObject').append($(option));
			}
			else if (type == "heat-mode") {
				$('#newThermostatModeObject').append($(option));
			}
			else if (type == "EIS2") {
				$('#newDimmerCommandObject').append($(option));
			}
			else {
				$('#newSwitchCommandObject').append($(option));
				$('#newDimmerOnOffObject').append($(option));
			}
		});
	},
	changeZoneBackground: function(zoneid, bg) {
		$('zone[id='+zoneid+']', UIController.config).attr('img', bg);
		this.setZoneBackground(bg);
	},
	setZoneBackground: function(bg) {
		if (bg == null || bg == "")
			bg = 'images/1pixel.gif';
		else
			bg = 'design/'+this.designName+'/'+bg;
		$('#bgImage').attr('src', bg);
	},
	drawZone: function(zoneid) {
		UIController.removeAll();
		EIBCommunicator.removeAll();
		if (!zoneid)
		    zoneid = $('zone', UIController.config).attr('id');
		this.currentZone = zoneid;
		var zone = $('zone[id='+zoneid+']', UIController.config);
		UIController.setZoneBackground(zone.attr('img'));
		zone.children('control').each(function() {
			UIController.addWidget(this, UIController.editMode);
		});
		EIBCommunicator.updateAll();
	},
	editZone: function(mode) {
		this.editMode = (mode != null) ? mode : !this.editMode;
		for(var i=0;i<UIController.objects.length; i++)
			UIController.objects[i].edit(this.editMode, this.editMode);
	},

	addWidget: function(o, modify) {
		var obj=null;
		var type = o.getAttribute('type');
		if (type == "switch")
			obj=new CSwitch(o);
		else if (type == "thermostat")
			obj=new CThermostat(o);
		else if (type == "goto")
			obj=new CGoto(o);
		else if (type == "camera")
			obj=new CCamera(o);
		else if (type == "dimmer")
			obj=new CDimmer(o);
		else if (type == "text")
			obj=new CText(o);
		if (modify)
			obj.edit(true, true);
		if (obj!=null) {
			document.body.appendChild(obj.div);
			UIController.objects.push(obj);
			EIBCommunicator.add(obj);
		}
	},
	add: function(conf) {
		$('zone[id='+this.currentZone+']', UIController.config).each(function() {
			this.appendChild(conf);
		});
		UIController.addWidget(conf, true);
	},
	createControl: function(type) {
		var conf = UIController.config.createElement('control');
   		conf.setAttribute('type', type);
   		return conf;
	},
	remove: function(o) {
		for(var i=0;i<UIController.objects.length; i++) {
			if (o==UIController.objects[i]) {
				document.body.removeChild(o.div);
				UIController.objects.splice(i,1);
				$(o.conf).remove();
				EIBCommunicator.remove(o);
				return;
			}
		}
	},
	addZone: function(zoneid, zoneName) {
		var newzone = UIController.config.createElement('zone');
		newzone.setAttribute('id', zoneid);
		newzone.setAttribute('name', zoneName);
		$('zones', UIController.config).append(newzone);
	},
	removeZone: function(zoneid) {
		$('zone[id='+zoneid+']', UIController.config).remove();
	},
	saveDesign: function(version) {
		var string = (new XMLSerializer()).serializeToString(UIController.config);
		var url = 'design.php?action=savedesign&name='+this.designName+'&ver='+version;
		req = jQuery.ajax({ type: 'post', url: url, data: string, processData: false, dataType: 'xml' ,
			success: function(responseXML, status) {
				var xmlResponse = responseXML.documentElement;
				if (xmlResponse.getAttribute('status') == 'success') {
					UIController.setNotification("Design saved successfully");
				}
				else {
					UIController.setNotification("Error while saving design: "+xmlResponse.textContent);
					alert("Error while saving design: "+xmlResponse.textContent);
				}
			},
			error: function (XMLHttpRequest, textStatus, errorThrown) {
				UIController.setNotification("Error while saving design: "+textStatus);
			}
		});
	},
	displayDesign: function() {
		var string = (new XMLSerializer()).serializeToString(UIController.config);
		var popup = window.open();
		popup.document.write("<html><body><textarea rows=30 cols=100>"+string+"</textarea></body></html>");
		popup.document.close();
	},
	setNotification: function(text)	{
		$('#notificationZone').text(text).show();
		runAfter.add(UIController.clearNotification, 5, this);
	},
	clearNotification: function()	{
		$('#notificationZone').text('').hide();
	},
	removeAll: function(o) {
		zo = UIController.objects.shift();
		while (zo != null) {
			document.body.removeChild(zo.div);
			zo = UIController.objects.shift();
		}
	}
}

