/* Initialization function */
$(function() {
  $('#email, #company, #firstname, #lastname, #address, #city, #zipcode, #phone, #state, #Services, #notes').blur(blur).keyup(keyup);
  $('#state, #services').change(function(event){validate(getEventSrc(event))});
    
  // build the G.fields structure
  for (f in G.validations) {G.fieldIds.push(f);};
  G.fields=$($.map(G.fieldIds,toSelector).join(","));
  
  // select all the fields that are non-blank
  G.interacted=$.makeArray(G.fields.filter("[value!='']").map(function(){return this.id}));
  G.activeValidation=$.makeArray(G.fields.filter("[value!='']").map(function(){return this.id}));
  if (G.interacted.length>0){G.fields.each(function(){validate(this)})}

  /* Bind the submit event */
  $("#main-form").submit(function() {
    G.fields.each(function(){validate(this)});
    // if there are any errored fields ...
    if ($(".error").length >0) {
      G.interacted=$.makeArray(G.fields.map(function(){return this.id}));
      G.activeValidation=$.makeArray(G.fields.map(function(){return this.id}));
      $("#cant-submit").show();
      G.failedSubmit=true;
      return false;
    } else {
      $("#cant-submit").hide();
      return true;
    }
  });
});	


/* Keyup -- mark the field as interacted with, and validate if it's marked for active validation */
function keyup(event){
  var key = event.charCode || event.keyCode || 0;
  var f=getEventSrc(event);
  // record the fact that the field has been interacted with unless it's a tab key
  if (key != 9) {
    G.interacted.addIfNeeded(f.id);
  };

  if (G.activeValidation.contains(f.id)){
    validate(f);
  }
}

/* The blur event validates if appropriate */
function blur(event){
  var f=getEventSrc(event);
  if (G.interacted.contains(f.id)){
    validate(f);
  }
}

/* validation */
function validate(field){
  var valid=G.validations[field.id](field);
  var status = valid ? "" : "error";
  if (!valid) {
    G.activeValidation.addIfNeeded(field.id);
  }
  /* hide the "can't submit" message if it's showen and there are no more errored fields */
  if (valid && G.failedSubmit){
    $("#cant-submit").hide();  
  }
  field.className=status;
};


/* Global object. Includes per-field validations */
var G={
  validations:{
    email:function(e){
      return (e.value.match(/^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/));
    },
    company: nonBlank,
    firstname: nonBlank,
    lastname: nonBlank,
    address: nonBlank,
    city: nonBlank,
    state: nonBlank,
    zipcode: function(e){
      return e.value.match(/[0-9]{5,5}/);
    },
    phone: function(e){
      var v=e.value.replace(/[^\d]/g,'');
      if (v.length == 10){
        e.value=v.substr(0,3)+"-"+v.substr(3,3)+'-'+v.substr(6,4);
        return true;
      }  else {
        return false;
      }
    },
    notes: nonBlank,
    services: function(e){
      return $(e).selectedValues().length >= 1;
    }
  },
  fieldIds:[], // to be created in init
  interacted:[],       // list of fields
  activeValidation:[], // list of fields
  hasErrored:[],        // list of fields
  failedSubmit:false
}

/* Common validation functions */
function nonBlank(e){
  return ($.trim(e.value).length >0);
}

/* helpers with selectors and events */
function toSelector(s){return "#"+s};

function getEventSrc(e) {
	if (!e) e = window.event;
	if (e.originalTarget){
		return e.originalTarget;
	} else if (e.srcElement) {
	return e.srcElement;
	}
};

/* Array Prototype additions */
Array.prototype.contains = function (d) {
	var e, i = 0;
	while (e = this[i++]) {if (d == e) return true};
	return false;
};

Array.prototype.addIfNeeded = function(item) {
  if (!this.contains(item)) {this.push(item)};
  return this;
};

Array.prototype.remove = function(item) {
  for(var i=0; i<this.length; i++) {
    if(this[i]==item) { this.splice(i,1);}
  }
  return this;
};

/**
 * jQuery extenstion for select boxes. Returns an array of values which have been selected
 */
$.fn.selectedValues = function(){
	var v = [];
	this.find("option:selected").each(
		function(){
			v[v.length] = this.value;
		}
	);
	return v;
};

/* Window open function */
function openWindow(name, url, opt){
  $.extend({
    left: 0,
    top: 0,
    width: 635, 
    height: 500, 
    toolbar: 'no', 
    menubar: 'no', 
    statusbar: 'no', 
    scrollbar: 'no', 
    resizable: 'no'
  },opt);
  
  window.open(url, name, 'left='+opt.left+',top='+opt.top+',width='+opt.width+',height='+opt.height+',toolbar='+opt.toolbar+',menubar='+opt.menubar+',status='+opt.statusbar+',scrollbars='+opt.scrollbar+',resizable='+opt.resizable);
}