/** var $E = pulp.createElement */
pulp.Modules.createElement = '$E';

(function() {

  /**
   * Create an element given the tag, properties and innerHTML, child node, or array of child nodes
   * 
   * @class
   * @name pulp.createElement
   * @param {String} tag  The tag name (Upper or lower case)
   * @param {Object} [properties={}]  Properties to add to the node
   * @param {String|HTMLElement|HTMLElement[]}  innerHTML, child node, or array of child nodes
   * @return {HTMLElement}
   */
  var $E = pulp.createElement = function(tag, properties, children) {
    var el, div, isNode;
    if (tag.substring(0, 1) == '<') {
      div = document.createElement('div');
      div.innerHTML = tag;
      if (div.childNodes.length == 1) {
        el = div.firstChild
      }
      else {
        el = div;
      }
    }
    else {
      el = pulp.document.createElement(tag);
    }
    
    if (typeof children == 'string') {
      el.innerHTML = children;
      
    } else if (children && children[0] && (children[0].nodeType == 1 || (isNode = (children[0] instanceof pulp.node)))) {
      for (var i = 0, len = children.length; i < len; i++) {
        el.appendChild(isNode ? children[i].raw : children[i]);
      }      
    } else if (children && (children.nodeType == 1 || (isNode = (children instanceof pulp.node)))) {
      el.appendChild(isNode ? children.raw : children);
    }
    for (var prop in properties || {}) {
      $E.setAttribute(el, prop, properties[prop]);
    }
    if ('node' in pulp) {
      el = pulp.node.getInstance(el);
    }
    return el;
  };
  
  // attr that should be mixed case
  var camelAttr = {};
  var names = 'cellPadding cellSpacing colSpan rowSpan vAlign dateTime accessKey tabIndex encType maxLength readOnly longDesc frameBorder'.split(' ');
  for (var i = 0, len = names.length; i < len; i++) {
    camelAttr[names[i].toLowerCase()] = names[i];
  }
  
  // check if cssText should be set instead of style
  var div = document.createElement('div');
  div.setAttribute('style', 'color: red');
  var setAttrStyle = div.style.color.length > 0;
  
  /**
   * Set an attribute on a node
   * 
   * @name pulp.createElement.setAttribute
   * @function
   * @param {HTMLElement} node  The node on which to set the element
   * @param {String} attr  The attribute to set
   * @param {String|undefined|false|null}  The value of the attribute.  
   *   If not given, the attribute will be set to the atribute name.
   *   e.g. $E.setAttribute(el, 'checked')  will set checked="checked"
   *   If false or null, the attribute is removed
   * @return {undefined}
   */
  $E.setAttribute = function(el, attr, value) {
    // TODO: add more support for edge cases    
    if (attr == 'checked') {
      // we want setAttribute('checked') to set to true
      el.checked = (value === undefined ? true : !!value);
      
    } else if (!setAttrStyle && attr == 'style') {
      el.style.cssText = (value ? value : '');
      
    } else if (attr == 'class' || attr == 'className') {
      el.className = value;
      
    } else if (attr == 'for' || attr == 'htmlFor') {
      el.htmlFor = value;
      
    } else {
      if (attr in camelAttr) {
        attr = camelAttr[attr];
      }
      if (value === false || value === null) {
        // e.g. we want setAttribute(attr, false) to remove attribute
        el.removeAttribute(attr);
        
      } else if (value === true) {
        // e.g. we want setAttribute('disabled', true) to set disabled=disabled
        el.setAttribute(attr, attr);
        
      } else {
        el.setAttribute(attr, value);
      }
    }
  };

})();