var dc = {
  store: {},
  output: '',
  toAppend: {},
  options: {
    disWarnings: false,
    disCompatMode: false
  },
  warnings:{
    styles: false,
    events: false
  },
  compatFunc: false,
  init: function(){
    YAHOO.util.Event.addListener('dc', 'submit', dc.insertHTML); 
    
    YAHOO.util.Event.addListener('dcDomTool', 'click', dc.onTabSwitch, this, true);   
    YAHOO.util.Event.addListener('dcOptToggle', 'click', dc.onTabSwitch, this, true); 
    YAHOO.util.Event.addListener('dcToggleCompatHelp', 'click', dc.onToggleHelp, this, true);   
    YAHOO.util.Event.addListener('dcToggleWarnHelp', 'click', dc.onToggleHelp, this, true);
    
    YAHOO.util.Event.addListener('dcDisCompat', 'change', dc.onSetOptions, this, true); 
    YAHOO.util.Event.addListener('dcDisWarn', 'change', dc.onSetOptions, this, true); 
    
    dc.options.disCompatMode = (dc.readCookie('disCompatMode') == 'true') ? true : false;
    dc.options.disWarnings = (dc.readCookie('disWarnings') == 'true') ? true : false;
    
    YAHOO.util.Dom.get('dcDisCompat').checked = dc.options.dsCompatMode;
    YAHOO.util.Dom.get('dcDisWarn').checked = dc.options.disWarnings;
  },
  // Cookie functions from Quirksmode.org 
  createCookie: function(name,value,days) {
  	if (days) {
  		var date = new Date();
  		date.setTime(date.getTime()+(days*24*60*60*1000));
  		var expires = "; expires="+date.toGMTString();
  	}
  	else var expires = "";
  	document.cookie = name+"="+value+expires+"; path=/";
  },
  readCookie: function(name) {
  	var nameEQ = name + "=";
  	var ca = document.cookie.split(';');
  	for(var i=0;i < ca.length;i++) {
  		var c = ca[i];
  		while (c.charAt(0)==' ') c = c.substring(1,c.length);
  		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
  	}
  	return null;
  },
  eraseCookie: function(name) {
  	createCookie(name,"",-1);
  },
  trim: function(str){
    return str.replace(/^\s+|\s+$/g,'');
  },
  
  setOption: function(id){
    var el = YAHOO.util.Dom.get(id);
    
    switch(id){
      case "dcDisCompat":
        dc.options.disCompatMode = el.checked;
        dc.createCookie('disCompatMode',dc.options.disCompatMode,360);
      break;
      case "dcDisWarn":
        dc.options.disWarnings = el.checked;
        dc.createCookie('disWarnings',dc.options.disWarnings,360);
      break;
    }
  },
  compatHasAttribute: function(objEl,attr){
    if (objEl.hasAttribute){
      return objEl.hasAttribute(attr);
    }else{
      var attributes = objEl.attributes;
      for (i=0,j=attributes.length; i<j; i++){
        if(objEl.attributes[i].nodeName == attr){
          return true;
        }
      }
    }
    return false;
  },
  onSetOptions: function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if (t && t.id ) dc.setOption(t.id);
    YAHOO.util.Event.stopEvent(e);
  },
  onToggleHelp: function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if (t && t.id ) dc.toggelHelp(t.id);
    YAHOO.util.Event.stopEvent(e);
  },
  toggelHelp: function(id){
    switch(id){
      case 'dcToggleCompatHelp':
        YAHOO.util.Dom.hasClass('dcCompatHelp', 'hidden') ? YAHOO.util.Dom.removeClass('dcCompatHelp', 'hidden') : YAHOO.util.Dom.addClass('dcCompatHelp', 'hidden');
        break;
      case 'dcToggleWarnHelp':
        YAHOO.util.Dom.hasClass('dcWarnHelp', 'hidden') ? YAHOO.util.Dom.removeClass('dcWarnHelp', 'hidden') : YAHOO.util.Dom.addClass('dcWarnHelp', 'hidden');
        break;
    }
  },
  insertHTML: function(e){
    // Clear output textarea
    YAHOO.util.Dom.get('dcDomOutput').value = '';
    YAHOO.util.Dom.get('dcToAppend').value = '';
    YAHOO.util.Dom.addClass('dcNoInput', 'hidden');
    
    // Reset counter and output object
    dc.store = null;
    dc.store = {};
    dc.toAppend = null;
    dc.toAppend = [];
    dc.compatFunc = false;
    dc.output = '';
    dc.warnings={styles: false,events: false};
    // hide stuff as necessary
    YAHOO.util.Dom.addClass('dcCompFuncLab', 'hidden');
    YAHOO.util.Dom.addClass('dcFunc', 'hidden');
    YAHOO.util.Dom.addClass('dcWarnings', 'hidden');  
    YAHOO.util.Dom.addClass('dcWarnStyles', 'hidden'); 
    YAHOO.util.Dom.addClass('dcWarnEvents', 'hidden');
    var inp = YAHOO.util.Dom.get('htmlinput').value;
    if (inp.replace(/^\s+/,'')  != ''){    
      var m = YAHOO.util.Dom.get('dcContainer');
      m.innerHTML = inp;  
      dc.followTree(m);
    } else {
     YAHOO.util.Dom.removeClass('dcNoInput', 'hidden');
    }
    YAHOO.util.Event.stopEvent(e);
  },
  // Straight out of the the YUI DOM's private functions.
  toCamel: function(property) {
     var convert = function(prop) {
        var test = /(-[a-z])/i.exec(prop);
        return prop.replace(RegExp.$1, RegExp.$1.substr(1).toUpperCase());
     };
     while(property.indexOf('-') > -1) {
        property = convert(property);
     }
     return property;
  },
  onTabSwitch: function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if (t && t.id) dc.tabSwitch(t.id);
    YAHOO.util.Event.stopEvent(e);
  },  
  tabSwitch: function(id){
    switch(id){
      case 'dcDomTool':
        YAHOO.util.Dom.removeClass(YAHOO.util.Dom.get('dcOptToggle').parentNode,'urhere');
        YAHOO.util.Dom.addClass(YAHOO.util.Dom.get('dcDomTool').parentNode,'urhere');
        YAHOO.util.Dom.addClass('dcOpt', 'hidden');
        YAHOO.util.Dom.removeClass('dc', 'hidden');
        break;
      case 'dcOptToggle':
        YAHOO.util.Dom.removeClass(YAHOO.util.Dom.get('dcDomTool').parentNode,'urhere');
        YAHOO.util.Dom.addClass(YAHOO.util.Dom.get('dcOptToggle').parentNode,'urhere');
        YAHOO.util.Dom.addClass('dc', 'hidden');
        YAHOO.util.Dom.removeClass('dcOpt', 'hidden');  
        break;
    }
  },
  followTree: function(el){
    var elc = el.childNodes;
    for (var i = 0, j= elc.length; i<j; i++){  
      var av    = '';      
      var nt    = elc[i].nodeType;
      var nn    = (nt == 1) ? elc[i].nodeName.toLowerCase() : 'txt';
      
      var nv    = (nt == 1) ? elc[i].nodeValue : elc[i].nodeValue.replace(/^\n?\s+/,'');
      var pn    = elc[i].parentNode;
      var pnn   = pn.nodeName; 
      var dcc = YAHOO.util.Dom.get('dcContainer');
      var ptags = dcc.getElementsByTagName(pnn);
      // Find Parent Correctly by checking the nodes with the same tag      
      if (ptags && pn.id != 'dcContainer'){
        for(g=0,h=ptags.length; g<h; g++){
          if (ptags[g] == pn ){
            pvr = pnn.toLowerCase()+(g+1);
            break;
          }
        }
      }else{
        pvr = null;
      }
      var attr  = elc[i].attributes; 
      // init store for this element
      if (!dc.store[nn]) dc.store[nn] = [];
      var vr = nn.toLowerCase()+(dc.store[nn].length+1);
      
      // Store element details for later (setting true as a default value.)
      if (nn) dc.store[nn][dc.store[nn].length] = true;             
      switch(nt){
        // ELEMENT
        case 1:
          // Create Element
          //if (.hasAttribute("name") && dc.options.disCompatMode == false) {
          if (dc.compatHasAttribute(elc[i],"name") && dc.options.disCompatMode == false) {
            dc.output += "var "+vr+"=ce('"+nn+"','"+elc[i].getAttribute('name')+"');\n";  
            dc.compatFunc = true;   
          }else{  
            dc.output += "var "+vr+"=document.createElement('"+nn+"');\n";      
          }
          // Build Attributes              
          if (attr){
            for (k=0,l=attr.length; k<l; k++){  
              var attrib = elc[i].attributes[k].nodeName;
              var attribVal = elc[i].attributes[k].nodeValue;
              if (!attribVal) continue;
              av = attribVal.replace(/'|&apos;/g, "\\'");                   // Escape quotes
              av = av.replace(/\s+^/mg, "\\n");                             // Escape carriage return
              switch(attrib.toLowerCase()){
                case 'class':
                  dc.output +=  vr+".className='"+av+"';\n";   
                  break;
                case 'style':
                  var sty = av.split(/[:;]/); 
                  if(sty){
                    for(p=0,q=sty.length; (p+2)<q; p=p+2){
                      var styleProp = dc.trim(sty[p]);
                      styleProp = (styleProp.indexOf('-') > -1) ? dc.toCamel(styleProp) : styleProp; 
                      if (styleProp == 'float') styleProp = 'cssFloat';
                      var styleVal = dc.trim(sty[p+1]);
                      styleVal = styleVal.replace(';','');
                      dc.output += vr+'.style.'+styleProp+'="'+styleVal+'";\n';
                      dc.warnings.styles = true;
                    }
                  }
                  break;
                default:
                  if (attrib.toLowerCase() == 'name' && dc.options.disCompatMode == false){
                    continue;
                  // Inline events YUCK!
                  } else if (attrib.toLowerCase().substring(0,2) == 'on'){
                    // Allows for escaped single quotes already in the input 
                    dc.output +=  vr+"."+attrib+"=function(){"+av.replace(/\\'/g,'\'')+"};\n";
                    dc.warnings.events = true;
                  // Everything else get setAttribute
                  } else{
                    dc.output +=  vr+".setAttribute('"+attrib+"','"+av+"');\n";   
                  }
                  break;
              }   
            }
          }
          // Build object of nodes that will need to be appended
          if (elc[i].parentNode.id == 'dcContainer') dc.toAppend[vr] = true;
          break;
        // TEXTNODE  
        case 3:
          if (nv == '') continue;  
          nv = nv.replace(/'|&apos;/g, "\\'");                                  // Escape quotes
          nv = nv.replace(/\s+^/mg, "\\n");                                     // Escape carriage returns          
          dc.output += "var "+vr+"=document.createTextNode('"+nv+"');\n";
          break;
      }
      if (vr && pvr) {
        dc.output += pvr+".appendChild("+vr+");\n";
      }
      // Recurse
      dc.followTree(elc[i]);
    }  
    // Present DOM output
    YAHOO.util.Dom.get('dcDomOutput').value = dc.output;    
    // Show nodes that need to be appended.
    var tapp = '';
    // Loop through object 
    for (prop in dc.toAppend) {
      if (dc.toAppend[prop] === true) {
        tapp +=  prop+'\n';
      }
    }
    YAHOO.util.Dom.get('dcToAppend').value = tapp; 
    if (dc.compatFunc == true && dc.options.disCompatMode === false){
      YAHOO.util.Dom.removeClass('dcCompFuncLab', 'hidden');  
      YAHOO.util.Dom.removeClass('dcFunc', 'hidden');  
    }   
    if ((dc.warnings.styles == true || dc.warnings.events == true) && dc.options.disWarnings == false){
      YAHOO.util.Dom.removeClass('dcWarnings', 'hidden');  
      if(dc.warnings.styles == true) YAHOO.util.Dom.removeClass('dcWarnStyles', 'hidden'); 
      if(dc.warnings.events == true) YAHOO.util.Dom.removeClass('dcWarnEvents', 'hidden'); 
    }
  }
};
YAHOO.util.Event.addListener(window, 'load', dc.init);

