/* cookiecrumbs constructor  -- dependence on jQuery: minimal, but increasing  */


// classes
var cc = {

  cookieCrumbs : function() {
    this.crumbs = {} ;
    this.types = { val : 'V:' , frm : 'F:' }
    this.seps = { nvs : '~' , ffs : '|' , svm : '^' } 
    // nvs = name/value separator ; ffs = formfields separator ; svm = state-value marker
    
    if (!document.cookie) { 
      this.defaultCookie() ;
    } else {
      this.parseCookie() ;
      if (!this.crumbs.currentBG) { this.newCrumb('currentBG',gp.defaultBG,'val',gp.BGtracking); }
    }
    this.addCustomMethods() ;
  },
  
  cookieCrumb : function(parent, name, value, type, active) {
    this.parent = parent ;
    this.name = name ;
    //this.active = active||true ; 
    this.active = active||false ; 
    this.backup = '' ;

    if (type == null) { // the lack of an explicit type tells us we are parsing document.cookie data

    
      if (value.length > 2) {this.value = unescape(value.slice(2)) };
      if (value.length > 0) {this.type = value.substr(0,2) };
    
    } else { // if type exists we are creating crumb, so when we're done it needs to be set

    
      this.value = value ;
      this.type = type ;
         
      // if form in cookie but form not on page, set active false
      //if (type == parent.types.frm) { 
      //  if (!document.getElementById(this.name)) { this.active = false } ;
      //}

      
      if (type == this.parent.types.val) { // if it's a simple value, get a cookie entry cooking
        if (!this.active) { this.active = true } ;
        this.set() ;
      }
    }
 

    if (this.type == this.parent.types.frm) {
      this.form = new cc.formstore() ;
      this.xhr = new cc.xhr(this) ;
      if ( this.name.indexOf('login') > -1 ) {
        this.xhr.setService('loginprocessor.php','loginX') ;
      }
    }
  },
  
  formstore : function() {
         ;
  },
  
  fieldstore : function(e,sepsref) {
    this.ff = e ;
    this.seps = sepsref ;
    this.name = e.name;
    this.type = e.type ;
    this.value = (e.value) ? e.value : '' ;
    this.checked = (e.checked) ? e.checked : false ;
    this.selectedIndex = (e.selectedIndex) ? e.selectedIndex : null ;
    this.checkedindex = null ;
    this.groupref = null ; // i think you have to consider putting this into the .ff instead, since a radio fieldstore is already irregular
    
    if (e.type == 'radio' ) {
      this.groupref = e.form[e.name] ;
      this.checkedindex = '' ;
      this.value = '' ;
      for ( var i = 0; i < this.groupref.length; i++) {
        if (this.groupref[i].checked) {
          this.checkedindex = i ;
          this.value = this.groupref[i].value ;
        }
      }
    }
  },
  
  xhr : function(parent,service,callback){
    this.parent = parent ;
    this.request = this.create() ;
    if ( !gp.ie ) this.request.parent = this ;  // exclude ie6 -- xhr object is readonly
    this.service = service||'formprocessor.php' ;
    this.handlerName = 'responseX' ;
    this.callback = callback||false ;

    // actually not required here because the exec() always does a initService()
    //this.setService(this.service,this.handlerName) ;
    
    //this.request.onreadystatechange = this[handlerName] ; // now handled by setService method

    // implementing the callback might look something like this, though prob. would have custom service also,
    // and should be set with call to setService method
    //this.request.onreadystatechange = ( jQuery.isFunction(this.callback) ) ? this.callback : this.responseX ;

  }

} // end of cc object


//=================================================================================================
//prototypes

cc.cookieCrumbs.prototype = {

  defaultCookie : function() {
    this.newCrumb('currentBG',gp.defaultBG,'val',gp.BGtracking) ;
    this.newCrumb('adminloginOK',0,'val',true) ;
    this.newCrumb('userloginOK',0,'val',true) ;
    this.newCrumb('timestamp',0,'val',true) ;
  },

  addCustomMethods : function() {
    if (this.crumbs.currentBG) {
      this.crumbs.currentBG.update = function(newvalue) {
        if (newvalue) { 
           this.value = newvalue ; 
           this.set() ;
        }
        if (gp.BGtracking) { 
          document.body.setBG(this.value) ;
          $('#bgcycname').val(this.value) ;
        }
      }
      this.crumbs.currentBG.active = gp.BGtracking ;
    }
  },

  parseCookie : function() {
    var cdat = document.cookie , cprep = new Array() , temp = "" ;
    	   
    if (cdat.indexOf('; ') != -1) {
      var pairs = cdat.split('; ') ;
      for (var p = 0; p < pairs.length; p++) {
        temp = pairs[p].split('=') ;
        this.newCrumb(temp[0],temp[1]) ;
      }  
    } else {
      temp = cdat.split('=') ;
      this.newCrumb(temp[0],temp[1]) ;
    }
  },
	 
  setCookie : function() {
    for (var crumbname in this.crumbs) {
      this[crumbname].set() ;
    }
  },
	 
  newCrumb : function(cname,cvalue,ctype,cactive) {
    this.crumbs[cname] = new cc.cookieCrumb(this,cname,cvalue,this.types[ctype],cactive) ; 
  },
	 
  enableFormTracking : function() {
    if ( gp.trackedforms.length == 0 ) { return } 
    var formname, formcontainer ;
    for ( var i = 0; i < gp.trackedforms.length; i++ ) {
      formname = gp.trackedforms[i].name ;
      if ( document.forms[formname] ) {
        gp.trackedforms[i].active = true ;
        $(document.forms[formname]).addClass(gp.btc.ft) ;
        if ( !this.crumbs[formname]) {
          this.newCrumb(formname,"",'frm',true) ;
        } else {
          this.crumbs[formname].active = true ;
        }
      } else {
//      if (this.crumbs[formname]) { this.crumbs[formname].active = false }
//      so if form not in page, crumb is inactive, SO -- it doesn't get set!
      }
    }
  },

  initTrackedForms : function() {
    for (var crumbname in this.crumbs) {
      if (this.crumbs[crumbname].activeForm()) {
        this.crumbs[crumbname].initformstorage() ;
        if (this.crumbs[crumbname].value != null && this.crumbs[crumbname].value.length > 0) {
          this.crumbs[crumbname].unpack() ;
          this.crumbs[crumbname].restore() ;
        } else {
          this.crumbs[crumbname].set() ;
        }
      }
    }
  },
  	 
  startup : function() {
    if (this.crumbs.currentBG.active) { this.crumbs.currentBG.update() } ;
    this.enableFormTracking() ;
    this.initTrackedForms() ;
  }       
  
}  //end of cc.cookieCrumbs prototype


cc.cookieCrumb.prototype = {

  set : function() {
    //if (!this.active) {return}
    
    switch (this.type) {
      case this.parent.types.frm:
        this.value = this.pack() ;
        break ;
    }
    
    document.cookie = this.name + '=' + this.type + this.value ;
  },
  
  activeForm : function() {
    if (this.active && (this.type == this.parent.types.frm)) { return true }  ;
    return false ;
  },
  
  pack : function() {
    return this.form.pack(this.parent.seps) ;
  },
  
  xhrprep : function() {
    return this.form.xhrprep() ;
  },
  
  unpack : function() {
     var formdat = new Array(), thispair = "" ;
     formdat['nvpairs'] = new Array() ;
     formdat['fields'] = new Array() ;
     
     formdat['nvpairs'] = this.value.split(this.parent.seps.ffs) ;
     for (var i = 0; i < formdat['nvpairs'].length; i++) {
       thispair = formdat['nvpairs'][i].split(this.parent.seps.nvs) ;
       formdat['fields'][thispair[0]] = unescape(thispair[1]) ;
     }
     this.form.fill(formdat['fields']) ;
  },
  
  restore : function() {
     this.form.restore() ;
  },
  
  reset : function() {
     this.backup = this.value ;
     this.form.blank() ;
  },

  recall : function() {
     this.value = this.backup ;
     this.unpack() ;
     this.restore() ;
  },

  initformstorage : function() {
    var radios = new Array() ;
    var rname = '' ;
    	    
    var theform = document[this.name].elements ;
    var valid = {'input' : true ,'textarea' : true , 'select' : true }
    
    for (var i=0; i < theform.length; i++) {
    
      if ( !valid[theform[i].tagName.toLowerCase()] ) { continue }
      
      if ( theform[i].type == "radio" ) {
      
        rname = theform[i].name ;
        
        if ( !radios.length ) {
          radios[radios.length] = [ rname, theform[i] ];
          radios[rname] = true ;
        } else if ( !radios[rname] ) {
          radios[radios.length] = [ rname, theform[i] ];
          radios[rname] = true ;
        } 
      } else {
        this.form[theform[i].name] = new cc.fieldstore(theform[i],this.parent.seps) ;
      }
     
    }
    
    for (var rb = 0; rb < radios.length; rb++) {
      this.form[radios[rb][0]] = new cc.fieldstore(radios[rb][1],this.parent.seps) ;
    }
    
    // i think this is change #5
    //this.set() ;
  }

} // end cc.cookieCrumb prototype
      

cc.formstore.prototype = {
  
  restore : function() {
     for (var fname in this) {
       if ( $.isProp(this[fname]) ) { this[fname].restore() };
     }
  },
  
  blank : function() {
     for (var fname in this) {
       if ( $.isProp(this[fname]) ) { this[fname].blank() };
     }
  },
  
  xhrprep : function() {
    var xhrpost = new Array() ;
    for (var fname in this) {
      if ( $.isProp(this[fname]) ) { xhrpost.push(this[fname].xhrprep()) };
    }
    return xhrpost.join('&') ;
  },
  
  fill : function(fields) {
     for (var fname in this) {
       if ( $.isProp(this[fname]) ) { this[fname].fill(fields[fname]) };
     }
  },
  
  pack : function(seps) {
    var packed = new Array() ;
    for (var fname in this) {
      if ( $.isProp(this[fname]) ) { packed.push(this[fname].pack()) };
    }
    return packed.join(seps.ffs) ;
  }

} // end cc.formstore prototype


cc.fieldstore.prototype = {

  restore : function() {
    this.ff.value = this.value ;
    if (this.type == "checkbox" && this.value == 'true') { this.ff.checked = true }
    if (this.type == 'radio' && this.value) { this.groupref[this.checkedindex].checked = true }
  },
  
  blank : function() {
  
    switch (this.type) {
      case 'radio':
       this.groupref[this.checkedindex].checked = false ;
       break ;
      
      case 'checkbox':
       this.ff.checked = false ;
       break ;
      
      case 'button':
       break ;
      
      default:
        this.ff.value = '' ;
       break ;
    }
  },
  
  fill : function(fieldvalue) {
    var thisval = '';
    switch (this.type) {
      case 'radio':
        thisval = fieldvalue.substr( 0, fieldvalue.indexOf(this.seps.svm) ) ;
        this.checkedindex = fieldvalue.substr(fieldvalue.indexOf(this.seps.svm)+1,1) ;
       break ;
      
      default:
        thisval = fieldvalue ;
       break ;
    }
    this.value = thisval ;
  },
  
  pack : function() {
    var store = "" ;
    var thisval = '';
    switch (this.type) {
      case 'checkbox':
        this.checked = this.ff.checked ;
        thisval = this.ff.checked ;
        this.value = thisval ;
        break ;
      
      case 'radio':
        this.checkedindex = '' ;
        thisval = '' ;
        for (var ri = 0; ri < this.groupref.length; ri++) {
          if (this.groupref[ri].checked) {
            this.checkedindex = ri ;
            this.value = this.groupref[ri].value ;
            thisval = this.value + this.seps.svm + ri ;
          }
        }
        break ;
      
      default:
        thisval = this.ff.value ;
        this.value = thisval ;
        break ;
    }
    store = this.name + this.seps.nvs + escape(thisval) ;
    return store ;
  },
  
  xhrprep : function() {
    var prep = "" ;
    var isButton = { 'button' : true , 'reset' : true , 'submit' : true }
      if ( isButton[this.type] ) {
        prep = 'formctl[' + this.name + ']=' + escape(this.value) ;
      } else if ( (this.type=='hidden') && (this.name.indexOf('cfg-')==0) ) {
        prep = 'formcfg[' + this.name + ']=' + escape(this.value) ; 
      } else {
        prep = 'formdat[' + this.name + ']=' + escape(this.value) ;
      } 
    return prep ;
  }

}  // end cc.fieldstore prototype


cc.xhr.prototype = {
  
  create : function() {
    var xmlHttpObj;
    if (window.XMLHttpRequest) {
      xmlHttpObj = new XMLHttpRequest();
    } else {
      try {
        xmlHttpObj = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (e) {
        try {
          xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (e) {
          xmlHttpObj = false;
        }
      }
    }
    return xmlHttpObj;
  },
  
  exec : function(ev) {
    var evt = (ev) ? ev : window.event ;
    this.popX = evt.pageX ;
    this.popY = evt.pageY ;
    var postdat = this.parent.form.xhrprep() ;
    this.initService() ;
    if (gp.ie) gp.ie6ccref = this.parent ;
    this.request.send(postdat) ;
  },
  
  setService : function(serviceurl,methodname){
    this.service = serviceurl ;
    this.handlerName = methodname ;
  },
  
  initService : function(){
    this.request.open('POST', this.service, true) ;
    this.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') ;
    this.request.onreadystatechange = this[this.handlerName] ;
  },
  
  responseX : function(){
    var crumb = (gp.ie) ? gp.ie6ccref : this.parent.parent ;
    var _this = (gp.ie) ? crumb.xhr.request : this ;
    if ( !(_this.readyState == 4 && _this.status == 200) ) { return }

    var text = this.responseText ;
    var formtab = '#tab-' + crumb.name ;
    
    if ( $.isFunction(crumb.xhr.callback) ) {
      crumb.xhr.callback(text) ;
    } else {
    
      $('body').append('<div id="xhrdata" class="xhrpost"></div>') ;
      $('#xhrdata').html(text) ;
      $('#xhrdata div.tbfill').append('<br><input type="button" value="Done">') ;
      
      var popX = crumb.xhr.popX - $('#xhrdata').outerWidth() ;
      var popY = crumb.xhr.popY - $('#xhrdata').outerHeight() ;
      
      $('#xhrdata').css({'top': popY, 'left' : popX}) ;
      
      $('#xhrdata input[type="button"]').click( function(){
        $('#xhrdata').empty().hide() ;
        $(formtab).hide() ;
        crumb.reset() ;
      } ) ;
    }
  },
  
  loginX : function() {

    var crumb = (gp.ie) ? gp.ie6ccref : this.parent.parent ;
    var _this = (gp.ie) ? crumb.xhr.request : this ;
    if ( !(_this.readyState == 4 && _this.status == 200) ) { return }

    var formtab = '#tab-' + crumb.name ;
    var $form = $('#' + crumb.name) ;
    
    if ( !$form.is(':has(#xhrloginstat)') ) { $form.append('<div id="xhrloginstat" class="xhrloginstat"></div>') } 
    $('#xhrloginstat').append(_this.responseText) ;
      
    if ( $form.is(':has(#admstat)') ) {
      if ( crumb.name == 'adminlogin' ) {
        cC.crumbs.adminloginOK.value = 1 ;
        cC.crumbs.adminloginOK.set() ;
      } else {
        cC.crumbs.userloginOK.value = 1 ;
        cC.crumbs.userloginOK.set() ;
      }
      $('<p>Refreshing Page...</p>').appendTo('#admstat') ;
      window.location.reload( false ) ;
      $(formtab).show() ;
    }
  }

}  // end cc.xhr.prototype
