Ext.namespace('W');

W.XMLModel = Ext.extend(Ext.util.Observable, {
	constructor: function () {
		this.addEvents(this.eventList);
	},
	xml:null,
	eventList: ['XMLLoaded','XMLSaved'],
	load: function (config) {
		Ext.Ajax.request(Ext.apply(config, {
			success: function ( result, request ) { 
				var error = this.getError(result.responseXML);
				if( error.length > 0) {
					console.log('XML Failed to load\n' + error);
				}
				else {
					this.loadXML(result.responseXML);
				}
			},
			failure: function ( result, request) { 
				console.log('Failed to load xml. ' + result.responseText); 
			},
			scope:this
		}));
	},
	
	loadXML: function (xml) {
		this.xml = xml;
		this.fireEvent('XMLLoaded',this.xml);
	},
	
	selectNode: function(cssSelector, xml)  {
		if (xml === null || xml === undefined) { xml = this.xml; }
		return Ext.DomQuery.selectNode(cssSelector,xml);
	},
	
	getError: function(xml) {
		var error = this.selectNode("response > error", xml);
		if( error !== null && error !== undefined) {
			return error.text;
		}
		return "";
	},
	
	xml2json: function(node) {
		var o = {
			elementNode:1, attributeNode:2, textNode:3, cdataNode:4, commentNode:8, documentNode:9,
			toObj : function(xml) {
				var json = {attr:[]};
				if (xml.nodeType == this.elementNode) { 
					//attributes
					for (var i=0; i < xml.attributes.length; i++) {
						json[xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue !== null) ? xml.attributes[i].nodeValue : "";
						json.attr[json.attr.length] = xml.attributes[i].nodeName;
					}
					//sub elements
					for (var childNode=xml.firstChild; childNode !== null; childNode=childNode.nextSibling) {
						if (childNode.nodeType == this.cdataNode) {
							json = childNode.nodeValue;
						}
						else if(childNode.nodeType == this.elementNode) {
							var nodeName = childNode.nodeName;
							var nodeValue = this.toObj(childNode);
							if(json[nodeName] !== undefined && json[nodeName].length === undefined) { // curntly single element
								json[nodeName] = [ json[nodeName], nodeValue ]; 
							}
							else if(json[nodeName] !== undefined && json[nodeName].length >1) { // curntly array
								json[nodeName][json[nodeName].length] = nodeValue; 
							}
							else { //undefined
								json[nodeName] = nodeValue;
							}
						}
						else if (childNode.nodeType == this.textNode || childNode.nodeType == this.commentNode) {
							continue;
						}
						else {
							throw new Error("xml2json: Unknown node type: " + xml.nodeType);
						}
					}
					return json;
				}
				else if( xml.nodeType == this.textNode || xml.nodeType == this.cdataNode) {
					return xml.nodeValue;
				}
				else if( xml.nodeType == this.documentNode) {
					return this.toObj(xml.documentElement);
				}
				else {
					throw new Error("xml2json: Unknown node type: " + xml.nodeType);
				}
			}
		};
		if( node === undefined) { node = this.xml; }
		return o.toObj(node);
	},
	
	json2xml: function(node) {
		var toXML = function (node, name, indent) {
			var xml = "";
			if ( node instanceof Array ) {
				for( var i=0; i< node.length; i++) {
					xml += toXML(node[i], name, indent);
				}
			}
			else if (typeof(node) == "object") {
				xml += indent + "<" + name;
				for (i=0; i < node.attr.length; i++) {
					xml += " " + node.attr[i] + "=\"" + node[node.attr[i]].toString() + "\"";
				}
				xml += ">\n";
				for (i in node) {
					if(i === "attr") { continue; }
					if( ! node.attr.contains(i) ) {
						xml += toXML(node[i], i, indent + "\t");
					}
				}
				xml += indent + "</" + name + ">\n";
			}
			else {
				xml += indent + "<" + name + ">\n";
				xml += indent + "\t<![CDATA[" + node.toString() + "]]>\n";
				xml += indent + "</" + name + ">\n";
			}
			return xml;
		};
		return toXML(node, "module", "");
	}
});



















