/*!
 * This function returns an object of JCanvasDSLClass it 
 * expects the id of the canvas element using this 
 * function avoids having to write 'new'
 */
function JCanvasDSL(id){
	return new JCanvasDSLClass(id);
}

/*!
 * Given the id of a canvas, ths JCanvasDSL sets that
 * canvas onReady event to call the init function of this object.
 */
function JCanvasDSLClass(id){
	this.canvas=Canvas();
	this.canvas.id=id;
	this.elements=[];
	var me=this;
	this.canvas.onReady=function(){
		me.init();
	};
}

/*!
 * The rootNode object should be populated with named functions of the tags allowed
 * to be in the root of the XML.
 */
JCanvasDSLClass.prototype.rootNode={};

/*!
 * The nextSibling function jumps over the textNode sibling to the next
 * actual tag sibling.
 */
JCanvasDSLClass.prototype.nextSibling=function(n){
	y=n.nextSibling;
	while (y&&y.nodeType!=1){
  		y=y.nextSibling;
  	}
	return y;
};

/*!
 * The firstChild function jumps over the textNode sibling to the next
 * actual tag firstChild.
 */
JCanvasDSLClass.prototype.firstChild=function(n){
	y=n.firstChild;
	while (y&&y.nodeType!=1){
  		y=y.nextSibling;
  	}
	return y;
};

/*!
 * Parse a boolean string either 'true' or '1' for the true value
 * and 'false' or '0' for the false value. returns the the boolean.
 */
JCanvasDSLClass.prototype.parseBoolean=function(text){
	var hex=null;
	if(text.match(/true|1/i)){
		return true;
	}
	if(text.match(/false|0/i)){
		return false;
	}		
	return false;
};
	
/*!
 * Parses a string as a space separeted sequence of floats
 * and returns the floats as an array.
 */
JCanvasDSLClass.prototype.parseFloats=function(text){
	var temp=text.split(' ');
	if(temp.length>1){
		for(var i in temp){
			temp[i]=parseFloat(temp[i]);
		}
		return temp;
	}else{
		return parseFloat(temp[0]);
	}
};

/*!
 * Returns a function that given a string returns this string if
 * it legal or a default string if its illegal.
 * This function takes an array of the legal strings and the default
 * string as arguments. 
 */
JCanvasDSLClass.prototype.makeParseLegalStrings=function(values,def){
	return function(text){
		for(var i=0;i<values.length;i++){
			if(text==values[i]){
				return text;
			}			
		}
		return def;
	};
};

/*!
 * Converts any of the color strings :
 * "#rrggbb", "#rrggbbaa", "rgb(rrr,ggg,bbb)" or "rgba(rrr,ggg,bbb,aaa)"
 * into a javascript object width the fields r, g, b, a.  
 */
JCanvasDSLClass.prototype.colorSolverRGBA=function(color){
	var dec=null;
	if(dec=color.match(/#[0-9a-fA-F]{6,8}/)){		
		dec=dec[0];
		return ColorObject(
				parseInt(dec.substr(1,2),16)
			   ,parseInt(dec.substr(3,2),16)
			   ,parseInt(dec.substr(5,2),16)
			   ,(dec.length==7)?1:parseInt(dec.substr(7,2),16)/255
		);
	}else if(dec=color.match(/rgb\((\d+),(\d+),(\d+)\)/)){
		return ColorObject(
			parseInt(dec[1])
			,parseInt(dec[2])
			,parseInt(dec[3])
			,1
		);
	}else if(dec=color.match(/rgba\((\d+),(\d+),(\d+),(\d+)\)/)){
		return ColorObject(
			parseInt(dec[1])
			,parseInt(dec[2])
			,parseInt(dec[3])
			,parseInt(dec[4])
		);		
	}else{
		alert(color)
	}
};
/*!
 * Given a node, an object and a map (double array) width the name of the
 * attribute and the name of the field of the object and maybe a function
 * This function sets the field of the object to the value of the attribute
 * or the value returned from the function given the value of the attribute
 */
JCanvasDSLClass.prototype.mapAttributes=function(node,obj,maps){
	for(var i=0;i<maps.length;i++){
		if((node.hasAttribute&&node.hasAttribute(maps[i][0]))||node.getAttribute(maps[i][0])){
			if (maps[i].length == 2) {
				if (typeof(obj[maps[i][1]]) == 'function') {
					obj[maps[i][1]](node.getAttribute(maps[i][0]));
				}else{										
					obj[maps[i][1]] = node.getAttribute(maps[i][0]);
				}
			}else{
				if (typeof(obj[maps[i][1]]) == 'function') {
					obj[maps[i][1]](maps[i][2](node.getAttribute(maps[i][0])));
				}else{		
								
					obj[maps[i][1]] =maps[i][2](node.getAttribute(maps[i][0]));
				}				
			}
		}
	}
};

/*!
 * Searches for the first HTML comment in the canvas element
 * And parse the content of this comment as an xml document.
 * Each child tag of the xml is tested if its name is 
 * registered in the rootnode object if it is the function
 * stored in the rootnode object is called with the canvas
 * and the found node. And the returned object is appended 
 * to the canvas.
 */
JCanvasDSLClass.prototype.init=function(){
	var c=this.canvas.element.firstChild;
	while(c&&c.nodeName!="#comment"){
		c=c.nextSibling;
	}
	var text='<root>'+c.nodeValue+'</root>';
	if (window.DOMParser){
		parser=new DOMParser();
		xmlDoc=parser.parseFromString(text,"text/xml");
	}else // Internet Explorer
	{
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(text);
	}

	var c=this.firstChild(xmlDoc.documentElement);
	while(c){
		if(c.nodeName=="configuration"){
			for(var i=0;i<c.attributes.length;i++){
				switch(c.attributes[i].name){
					case 'sizeToParent':
						this.canvas.autoSizeToParent();
					break;
					case 'color':						
						this.canvas.rgb(c.attributes[i].value);
					break;					
				}
			}
		}
		if(this.rootNode.hasOwnProperty(c.nodeName)){
			this.rootNode[c.nodeName](this,c,this.canvas);				
		}
		c=this.nextSibling(c);
	}	
	this.canvas.drawChildren();
};
