/**
 * Byng XML handler
 * 
 * Handler for ByngXml responses from the framework
 *
 * @requires Mootools-1.11
 * 
 * @copyright Byng Systems LLP
 * @author Ollie Maitland
 */
Byng.register('byng.ajax.xml', 
{
	name : 'byngxml',
	
	initialize : function (xmlTag)
	{
		// set the document to handle
		if (['collection','element','object'].contains($type(xmlTag))) {
			if (xmlTag.name == 'byngxml') {
				this.document = xmlTag.document;
				this.length   = xmlTag.length;
			} else {	
				this.document = xmlTag;
				this.length   = this.document.length;
			}
		} else {
			this.length = 0;
		}
	},
	
	/**
	 * Check if a tag is valid
	 * 
	 * @param String s
	 */
	isValidTag : function (s)
	{
		if ($type(this.document.getElementsByTagName(s)[0]) == 'element') {
			return true;
		} else {
			return false;
		}
	},
	
	/**
	 * Return the code in the XML response
	 * 
	 * @return String
	 */
	getCode : function ()
	{
		try {
			return Byng.ui.trim(this.getChildContent ("code"));
		} catch (e) {
			if (Byng.debug) alert('Invalid XML document: ' + e.toString());
		}
	},
	
	/**
	 * Get errors as an array
	 * 
	 * @return Array
	 */
	getErrors : function ()
	{
		try {
			var rtn = new Array ();
			var tags = this.document.getElementsByTagName("error");
			for (var i = 0; i < tags.length; i++ ) {
				rtn.push( tags[i].childNodes[0].nodeValue );
			}
			return rtn;		
		} catch (e) {
			return [];
		}
	},
	
	/**
	 * Get feedback as an array
	 * 
	 * @return Array
	 */
	getFeedback : function ()
	{
		try {
			var rtn = new Array ();
			var tags = this.document.getElementsByTagName("feedback");
			for (var i = 0; i < tags.length; i++ ) {
				rtn.push( tags[i].childNodes[0].nodeValue );
			}
			return rtn;
		} catch (e) {
			return [];
		}
	},	
	
	/**
	 * Return the body of the XML reponse
	 * 
	 * @return ByngXml
	 */
	getBody : function ()
	{
		try {
			return new ByngXml(this.getChildTag ("body"));
		} catch (e) {
			if (Byng.debug) alert('No body tag');
		}				
	},
	
	/**
	 * Get child content tag
	 * 
	 * @param String s
	 */
	getChildContent : function (s)
	{
		if (!$chk(this.document.getElementsByTagName(s)[0]) ||
			this.document.getElementsByTagName(s)[0] == null) throw ('No child tag called "'+ s +'"');
	
		var length = this.document.getElementsByTagName(s)[0].childNodes.length;
	
		// if value is empty IE does not have a nodeValue set (so return null)
		if (this.document.getElementsByTagName(s)[0].childNodes[0] == null) { return null; }
		else if (length > 1) {
			// DomParser splits up strings so concactinate them here
			var str = new String();
			for (i=0;i<length;i++) { str += this.document.getElementsByTagName(s)[0].childNodes[i].nodeValue; }
			return str;
		} else {
			return this.document.getElementsByTagName(s)[0].childNodes[0].nodeValue;
		}
	},
	
	/**
	 * Get the content of this XmlTag
	 * 
	 */
	getContent : function ()
	{
		return this.document.childNodes[0].nodeValue;
	},
	
	/**
	 * Get a parameter from the Xml response
	 * 
	 * @param String s Parameter name
	 */
	getParam : function (s)
	{
		var params = this.getChildTag("params");
		if ($type(params) != 'element') {
			throw Exception ("No parameters found in XML response");
		}
		var x = new ByngXml(params);
		if ($type(params) != 'element') return false;
		else {
			var param = x.getChildTag(s);
			var content = x.getChildContent(s);
			switch (param.getAttribute('type')) {
				case "array":
						var obj = this.fromJson(String(content));
						return obj.data;
				case "object":
						return this.fromJson(String(content));		
				case "int":
						return parseInt (content);
				case "double":
				case "float":
						return parseFloat(content);
				case "boolean":
						return (content == "0" ? false : Boolean(content));
			}
			return String(content);
		}
	},
	
	/**
	 * Get an object from the XML response
	 * 
	 * @param String type
	 */
	getObject : function (type)
	{
		var objects = this.getElementsByTagName('object');
		for (var i = 0;i<objects.length;i++) {
			if (objects[i].getAttribute('type') == type) {
				switch (objects[i].getAttribute('encoding')) {
					case "json":							
						return this.fromJson(objects[i].childNodes[0].nodeValue);
					break;
					case "soap":
						// ByngSoap?
					break;								
				}
	
			}
		}
	},
	
	/**
	 * Get the debug message in the ByngXml response
	 * 
	 * @return String
	 */
	getDebug : function()
	{
		return this.getChildContent("debug");
	},
	
	/**
	 * Convert a string from JSON to an object
	 * 
	 * @param String s
	 * @return ByngJson
	 */
	fromJson : function (s)
	{
		return Byng.init('byng.ajax.json', s);
	},
	
	/**
	 * Conver this XmlTag to a hash
	 * 
	 * @return Hash
	 */
	toHash : function ()
	{
		var hash = {};
		this.each(function(tag,indexOf) {
			hash[indexOf] = tag.get('text');
		});
		return new Hash(hash);
	},
	
	/**
	 * Return XmlTag as an array
	 * 
	 * @return Array
	 */
	toArray : function ()
	{
		var rtn = [];		
		this.each(function(tag,indexOf) {
			rtn.push(tag.get('text'));
		});
		return rtn;
	},
	
	/**
	 * Get an attribute of this XmlTag
	 * 
	 * @param String s Attribute name
	 */
	getAttribute : function (s)
	{
		return this.document.getAttribute (s);
	},
	
	/**
	 * Get a child Tag
	 * 
	 * @param String s
	 */
	getChildTag : function (s)
	{
		return this.document.getElementsByTagName(s)[0];
	},
	
	/**
	 * Wrapping method to get elements by tag name
	 * 
	 * @param String s
	 */
	getElementsByTagName : function (s)
	{
		return this.document.getElementsByTagName(s);
	},
	
	/**
	 * Get elements as ByngXml objects
	 * 
	 * @param String s
	 */
	getElements : function (s)
	{
		var rtn = new Array ();
		var tags = this.document.getElementsByTagName(s);
		for (var i = 0; i < tags.length; i++ ) {
			rtn.push( new ByngXml (tags[i]) );
		}
		return rtn;
	},
	
	/**
	 * Get the first element found
	 * 
	 * @param String s
	 */
	getElement : function (s)
	{
		return new ByngXml (this.document.getElementsByTagName(s)[0]);
	},
	
	/**
	 * Parse XML into a JavaScript data object
	 * 
	 * @param String xml
	 * @return DomElement
	 */ 
	parseXml : function (xml, rtnByngXml)
	{
		// Internet Explorer
		if (window.ActiveXObject)
		{
		  var doc = new ActiveXObject("Microsoft.XMLDOM");
		  doc.async = "false";
		  doc.loadXML(xml);
		}
		// Mozilla, Firefox, Opera, etc.
		else
		{
		  var parser = new DOMParser();
		  var doc = parser.parseFromString(xml, "text/xml");
		}
		
		if (rtnByngXml == true) return new ByngXml(doc.documentElement);
		else return doc.documentElement;
	},
	
	/**
	 * Add support for looping
	 * 
	 * @param Function fn
	 */
	each : function (fn)
	{
		for (var i =0;i<this.document.length;i++){
			fn(this.document[i],i);
		}				
	},
	
	/**
	 * Get workflow by event
	 * 
	 * @param String event
	 */
	getWorkflow : function ( event )
	{
		var workflow = this.getChildTag('workflow');
		if ($chk(workflow) && workflow.getAttribute('event') == event ) {
			return this.fromJson(this.getChildContent('workflow'));
		}
	}
				
});

/**
 * @legacy
 * 
 */
var ByngXml = Byng.source('byng.ajax.xml');

