// Lewjax library: xmlWriter
// libxml inspired xml-thingy.
// dependencies: lewjax.util.js

function xmlWriter() {
	this.doc = new xmlNode(arguments[0]);
	if (arguments.length == 2)
		this.doc.value = arguments[1];
	this.parentpointer = this.doc;
	this.debug = false;
}

function xmlNode(name) {
	this.tagName = name;
	this.parentNode = null;
	this.childNodes = new Array();
	this.attributes = new Array();
	this.styles = new Array(); // special one for html nodes..
	this.events = new Array();
	this.value = '';
	this.raw  = '';
}

function xmlAttribute(name,value) {
	this.name = name;
	this.value = value;
}


function nodeEvent(eventname, func, context, args) {
	this.eventName = eventname;
	this.eventHandler = func;
	this.context = context;
	this.args = args;
}

xmlAttribute.prototype.asCSS = function() {
	return this.name+': '+this.value;
}

xmlNode.prototype.getCSS = function() {
	var styles = new Array();
	for (var i=0;i<this.styles.length;i++) {
		styles[styles.length] = this.styles[i].asCSS();
	}
	return styles.join('; ');
}

xmlNode.prototype.addChildNode = function() {
	var n = new xmlNode(arguments[0]);
	n.parentNode = this;
	if (arguments.length == 2)
		n.value = arguments[1];
	this.childNodes[this.childNodes.length] = n;
	return n;
}

xmlNode.prototype.addAttribute = function(name,value) {
	this.attributes[this.attributes.length] = new xmlAttribute(name,value);
}

xmlNode.prototype.addEvent = function(eventname,func, context, args) {
	this.events[this.events.length] = new nodeEvent(eventname,func,context,args);
}

xmlNode.prototype.addStyle = function(name,value) {
	this.styles[this.styles.length] = new xmlAttribute(name,value);
}

xmlNode.prototype.compile = function(debug) {
	if (debug) { alert('compiling '+this.tagName+' node - '+this.attributes.length+' attributes, '+this.childNodes.length+' childNodes'); }
	var s = '';
	s += '<'+this.tagName;
	for (var i=0;i<this.attributes.length; i++) {
		s += ' '+this.attributes[i].name+'="'+xmlescape(this.attributes[i].value)+'"';
	}
	if (this.childNodes.length == 0 && this.value == '' && this.raw == '') {
		s += ' />';
		return s;
	}
	s += '>'+xmlescape(this.value)+(this.raw);
	for (var j=0;j<this.childNodes.length;j++) {
		s += this.childNodes[j].compile(debug);
	}
	s += '</'+this.tagName+'>';
	return s;
}

xmlNode.prototype.toHTMLNodes = function(debug) {
	if (debug) { alert('Converting '+this.tagName+' to an HTMLnode - '+this.attributes.length+' attributes, '+this.childNodes.length+' childNodes'); }
	var el = document.createElement(this.tagName);
	for (var i=0;i<this.attributes.length; i++) {
		// hack for class/id
		if (this.attributes[i].name=='class')
			el.className = this.attributes[i].value;
		if (this.attributes[i].name=='id')
			el.id = this.attributes[i].value;
		el.setAttribute(this.attributes[i].name, this.attributes[i].value);

	}
	if (this.styles.length>0) {
		el.style.cssText = this.getCSS();		
	}
	for (var i=0;i<this.events.length; i++) {
		// hack for events
		if (el.addEventListener){
			el.addEventListener(this.events[i].eventName,associateObjWithEvent(this.events[i].context,this.events[i].eventHandler,this.events[i].args),false);
		} else if (el.attachEvent) el.attachEvent('on'+this.events[i].eventName,associateObjWithEvent(this.events[i].context,this.events[i].eventHandler,this.events[i].args));
	}
	if (this.childNodes.length == 0 && this.value == '' && this.raw == '') {
		return el;
	}
	if (this.value != '') {
		el.appendChild(document.createTextNode(this.value));
	}
	if (this.raw != '') {
		el.innerHTML = this.raw;
	}
	for (var j=0;j<this.childNodes.length;j++) {
		el.appendChild(this.childNodes[j].toHTMLNodes(debug));
	}
	return el;
}

xmlWriter.prototype.startElement = function(name) {
	if (this.debug)
		alert('Adding \''+name+'\' element to '+this.parentpointer.tagName);
	this.parentpointer = this.parentpointer.addChildNode(name);
}

xmlWriter.prototype.endElement = function() {
	this.parentpointer = this.parentpointer.parentNode;
}

xmlWriter.prototype.writeElement = function(name, value) {
	if (this.debug)
		alert('Adding \''+name+'\' element to '+this.parentpointer.tagName);
	this.parentpointer.addChildNode(name, value);
}

xmlWriter.prototype.writeAttribute = function(name, value) {
	this.parentpointer.addAttribute(name, value);
}

xmlWriter.prototype.writeStyle = function(name, value) {
	this.parentpointer.addStyle(name, value);
}

xmlWriter.prototype.attachEvent = function(eventname, func, context, args) {
	this.parentpointer.addEvent(eventname, func, context, args);
}

xmlWriter.prototype.writeText = function(value) {
	this.parentpointer.value = value;
}

xmlWriter.prototype.writeRaw = function(value) {
	this.parentpointer.raw = value;
}

xmlWriter.prototype.compile = function() {
	return this.doc.compile(this.debug);
}


xmlWriter.prototype.toHTMLNodes = function() {
	return this.doc.toHTMLNodes(this.debug);
}

