/**
DOM Element creator.
Elm is an object that shouldn't be modified.
Methods take any number of arguments, however the first should be an object of element attributes
Those thereafter will be nodes to append.

	Elm.p( {id:'chocobo',className:'wark'}, 'WARK! ', Elm.b({},'WARK!'), 'WARK!');

Strings and Numbers are converted into text nodes, and regular objects are simply appended.
@author bibby
@requires XO.js
@requires Error.js
@requires XUtil.js
*/

var Elm = new (function()
{
	var tags=['strong','b','p','em','tt','div','span','a','dd','dt','ul','ol','li','h1','h2','h3','h4','h5','h6','table','tbody','tr','td','th','thead','tfoot','form','input','textarea'];
	
	tags.each(function(i, me)
	{
		var tag = this.toString();
		
		me[tag]=function(attribs)
		{
			var content = XUtil.toArray(arguments);
			content.shift();
			return Elm.createNode(tag, attribs, content);
		};
	}, this);
	
	
	//generic text node
	this.text = function(txt)
	{
		return document.createTextNode(txt);
	};
	
	// shortcuts
    this.button = function(attribs, value)
    {
    	return this.createNode('input', XO.x(attribs, {type:'button', 'value':value}) );
    };
	
	this.checkbox = function(attribs, state)
	{
    	return this.createNode('input',  XO.x(attribs, {type:'checkbox', 'checked':!!state}) );
	};
    
    this.script= function(src)
    {
    	return this.createNode('script', {type:'text/javascript', 'src':src} );
    };
    
    
    this.styleSheet= function(cssfile)
    {
    	return this.createNode('link', {type:'text/stylesheet', 'href':cssfile, media:'all'} );
    };
	
	
	/**
	@access private
	@param string  tagName
	@param object html attribute name:value pairs
	@param array innerHTML parts. May be strings, numbers, objects/nodes/elements
	*/
	this.createNode=function(tag, attribs, content)
	{
		var elm = document.createElement(tag);
		if(!is(elm,'object'))
			return Error.IllegalArgument( new Error('couldn\'t create element!'), 'Elm.createNode HTML tagName', tag);
		
		// fix the word 'class' to 'className'
		if(is(attribs,'object'))
		{
			['class','cls'].each(function()
			{
				if(is(attribs[this],'string'))
				{
					attribs.className = attribs[this];
				}
			});
		}
		
		// apply attributes to the element
		XO.x(elm,attribs);
		
		// content is almost guaranteed to be an array
		if(!is(content,'array'))
			content=[];
			//return Error.IllegalProcedure(new Error(), 'createNode called publically with bad args?!');
		
		//attach child nodes to the new element
		content.each(function()
		{
			elm.appendChild( Elm.parseContent(this) );
		});
		
		// give new element new methods
		Elm.api(elm);
		
		return elm;
	};
	
	/**
	@access private
	@param mixed , stuff you want to append
	@return object DOM node
	*/
	this.parseContent = function(content)
	{
		switch(is(content,'type'))
		{
			case 'array':
				content = content.join(', ');
			case 'number':
			case 'string':
				content = document.createTextNode(content);
			case 'object':
				if(!is(content.tagName,'string'))
				break;
		}
		
		return content;
	};
	
	this.api = function(elm)
	{
		
		XO.x(elm,{
			attr:function(get,set)
			{
				if(is(get,'object'))
				{
					XUtil.keys(get).each(function(k,elm)
					{
						elm.attr(this,get[this]);
					},this);
					return true;
				}
					
				if(is(set,'undefined'))
					return this.getAttribute(get);
				else
				{
					this.setAttribute(get,set);
					return set;
				}
			},
			css:function(req)
			{
				if(is(XUI,'object') && is(XUI.css,'function'))
					return XUI.css(this,req);
			}
		});
		return elm;
	}
});
