/*******************************************************************************
 *Validator class
 *requires form elements to be passed (error div, must have validation class)
 *runs utitly functions based on the elements passed, matches validation with class
 *returns true or false
 */
var Validator = Class.create();
Validator.prototype =
{
  initialize: function(form_elements){
    this.current_error_id = "";
    this.validations      = "";
    this.form_elements    = form_elements;

  },
  isFormValid : function(){
    this.validations = this.form_elements.collect(function(element){
      this.current_error_id = element.id;
      var is_valid = true;

      if(/(required)/i.test(element.className)){
        is_valid = (isNotEmptyInput(this.current_error_id));
      }
      if(/(validate-alpha)/i.test(element.className)){
        is_valid = (isValidRequiredAlphaInput(this.current_error_id));
      }
      if(/(validate-email)/i.test(element.className)){
        is_valid = (isValidEmail(this.current_error_id));
      }
      if(/(validate-state)/i.test(element.className)){
        is_valid = (isValidUsState(this.current_error_id));
      }
      if(/(validate-zip)/i.test(element.className)){
        is_valid = (isValidZip(this.current_error_id));
      }
      if(/(validate-phone)/i.test(element.className)){
        is_valid = (isValidPhone(this.current_error_id));
      }
      if(/(validate-checked)/i.test(element.className)){
        var error_msg = (trim(element.innerHTML) == "") ? undefined : element.innerHTML;
        is_valid = (isCheckedBox(this.current_error_id, error_msg));
      }
      if(/(validate-dob)/i.test(element.className)){
        is_valid = (isValidDob(this.current_error_id));
        (is_valid) ? fadeOut(this.current_error_id) : "";
      }
      if(/(validate-child-dob)/i.test(element.className)){
        is_valid = (isValidChildDob(this.current_error_id));
        (is_valid) ? fadeOut(this.current_error_id) : "";
      }
      if(/(validate-request-date)/i.test(element.className)){
        is_valid = (isValidCoverage(this.current_error_id));
        (is_valid) ? fadeOut(this.current_error_id) : "";
      }
      if(/(validate-height)/i.test(element.className)){
        var error_msg = (trim(element.innerHTML) == "") ? undefined : element.innerHTML;
        is_valid = (isValidHeight(this.current_error_id, error_msg));
      }
      if(/(validate-number)/i.test(element.className)){
        var error_msg = (trim(element.innerHTML) == "") ? undefined : element.innerHTML;
        is_valid = (isValidRequiredNumberInput(this.current_error_id, error_msg));
      }
      if(/(validate-weight)/i.test(element.className)){
        var error_msg = (trim(element.innerHTML) == "") ? undefined : element.innerHTML;
        is_valid = (isValidWeight(this.current_error_id, error_msg));
      }
      if(/(validate-one-selected)/i.test(element.className)){
        var error_msg = (trim(element.innerHTML) == "") ? undefined : element.innerHTML;
        is_valid = (isOneSelected(this.current_error_id, error_msg));
      }
      return is_valid;
    });
    return this.validations.all(function(v){ return (v == true); });
  }
}

  /*
   *util functions
   *
   *isNullorEmpty :: check for empty or null values
   *trim :: remove white space
   *showHide:: hide or show hidden fields passing switch state and id
   *isDefined :: checks if id/field exists
   */
  function trim (str){
    return str.replace(/^\s+/, '');
  }

  //test if null or empty
  function isNullOrEmpty(id){
    return (  (trim($F(id)) == null || trim($F(id)) == '') && isDefined(id)  )
  }

  function isDefined(id){
    if($(id) == null){
      if(document.getElementsByName(id).length == 0)
        return false;
    }else{
      return true;
    }
  }

  function fadeIn(id){
    if(isDefined(id)){
      new Effect.Appear(id);
    }
  }

  function fadeOut(id){
    if(isDefined(id)){
      new Effect.Fade(id);
    }
  }

  function clearErrorMessage(id){
    if(isDefined(id)){
      $(id).innerHTML="";
    }
  }

  function isValidSelection(error_id, error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? '\nThis is a required field.' : error_msg;
    if(isDefined(error_id)){
      var parent      = $(error_id).parentNode;
      var selections  = parent.getElementsByTagName('SELECT');
      if(selections.length > 0){
        if ( $(selections[0].id).value == "" ){
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }else{
          fadeOut(error_id);
        }
      }
    }
    return is_valid;
  }

  function isOneSelected(error_id,error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? '\nPlease select one of the above options.' : error_msg;
    if(isDefined(error_id) ){
      var radios = Form.getElements($(error_id).parentNode);
      is_valid   = radios.any(function(e){ return e.checked });
      if ( !is_valid ){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  function isChecked(error_id,error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? '\nPlease select one of the above options.' : error_msg;
    if(isDefined(error_id) ){
      var radios = Form.getElements($(error_id).parentNode);
      if ( radios.length > 0 && !radios[0].checked && !radios[1].checked  ){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
        is_valid = false;
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  function isCheckedBox(error_id,error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? '\nThis is a required field.' : error_msg;
    if(isDefined(error_id) ){
      var checkbox = Form.getElements($(error_id).parentNode);
      if ( checkbox.length > 0 && !checkbox[0].checked){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
        is_valid = false;
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  function unChecked(error_id){
    var is_valid = true;
    if(isDefined(error_id) ){
      var checkbox = Form.getElements($(error_id).parentNode);
      checkbox[0].checked = false;
      checkbox[1].checked = false;
    }
    return is_valid;
  }

  function isNotEmptyInput(error_id, error_msg){
    var is_not_empty = true;
    error_msg    = (error_msg == undefined) ? '\nThis is a required field.' : error_msg;
    if(isDefined(error_id)){
      var input_field   = Form.getElements($(error_id).parentNode);
      if(input_field.length > 0){
        if ( isNullOrEmpty(input_field[0].id)   ){
          $(error_id).innerHTML = error_msg;
          is_not_empty = false;
          fadeIn(error_id);
        }else{
          fadeOut(error_id);
        }
      }
    }
    return is_not_empty;
  }

  function isValidNumber(error_id, error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? '\nThis is a numeric field.' : error_msg;
    if(  isDefined(error_id)  ){
      var number_field  = Form.getElements($(error_id).parentNode);
      if(number_field.length > 0){
        if ( /\D/.test(trim($(number_field[0].id).value) )   ){
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }
      }
    }
    return is_valid;
  }

  function isValidRequiredNumberInput(error_id, error_msg){
    var is_valid = true;
    error_msg    = (error_msg == "" || error_msg == undefined) ? undefined : error_msg;
    if(isDefined(error_id)){
      var number_field   = Form.getElements($(error_id).parentNode);
      if(number_field.length > 0){
        if (isNullOrEmpty(number_field[0].id)){
          error_msg    = '\nThis is a required field.';
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }else if ( /\D/.test( (trim($(number_field[0].id).value)) )  ){
          error_msg    = '\nThis is a numeric field.';
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }else{
          fadeOut(error_id);
        }
      }
    }
    return is_valid;
  }

  function isValidWeight(error_id, error_msg){
    var is_valid = true;
    if(isDefined(error_id)){
      var number_field   = Form.getElements($(error_id).parentNode);

      if(number_field.length > 0){
        if (isNullOrEmpty(number_field[0].id)){
          error_msg    = '\nThis is a required field.';
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }
        if(is_valid){
          if ( /\D/.test( (trim($(number_field[0].id).value)) )  ){
            error_msg    = '\nThis is a numeric field.';
            $(error_id).innerHTML = error_msg;
            fadeIn(error_id);
            is_valid = false;
          }
        }
        if(is_valid){
          if (!/^[1-9]{1}$|^[1-9]{1}[0-9]{1,2}$/.test($F(number_field[0].id))){
            error_msg    = '\nPlease enter a valid weight.';
            $(error_id).innerHTML = error_msg;
            fadeIn(error_id);
            is_valid = false;
          }
        }
        if(is_valid){
          fadeOut(error_id);
        }
      }
    }
    return is_valid;
  }

  function isValidRequiredAlphaInput(error_id, error_msg){
    var is_valid = true;
    if(isDefined(error_id)){
      var alpha_field   = Form.getElements($(error_id).parentNode);
      if(alpha_field.length > 0){
        if (isNullOrEmpty(alpha_field[0].id)){
          error_msg    = '\nThis is a required field.';
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }else if ( !/^[\D]+$/.test( (trim($(alpha_field[0].id).value)) )  ){
          error_msg    = '\nPlease use letters only (a-z).';
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
          is_valid = false;
        }else{
          fadeOut(error_id);
        }
      }
    }
    return is_valid;
  }

  function isValidUsState(error_id, error_msg){
    var is_valid   = true;
    if( isDefined(error_id) ){
      var parent_node    = $(error_id).parentNode;
      var states         = parent_node.getElementsByTagName('SELECT');
      error_msg          = (error_msg == undefined) ? '\nPlease select a state.' : error_msg;

      if(states.length == 0){ //checks for drop down element is valid
        var states   = parent_node.getElementsByTagName('INPUT');
        error_msg    = (error_msg == undefined) ? '\nPlease enter a valid state.' : error_msg;
      }else if( !/^[a-z]{2}$/i.test(states[0].value)   ){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
        is_valid = false;
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  function isValidEmail(error_id){
    var is_valid = true;
    // validate email
    if( isDefined(error_id)  ){
      var email_field = Form.getElements($(error_id).parentNode);
      if(email_field.length > 0){
        var email     = email_field[0].id;
        if (isNullOrEmpty(email)  ){
          $(error_id).innerHTML = '\nPlease enter your email address.';
          fadeIn(error_id);
          is_valid = false;
        }else if (!/^([A-Z0-9]+[._]?){1,}[A-Z0-9-]+\@(([A-Z0-9]+[-]?){1,}[A-Z0-9]+\.){1,}([A-Z]{2,4}|museum)$/i.test($F(email))){
          $(error_id).innerHTML = '\nPlease enter a valid email address.';
          fadeIn(error_id);
          is_valid = false;
        }else{
          fadeOut(error_id);
        }
      }
    }
    return is_valid;
  }

  function isValidPhone(error_id, error_msg){
    var is_valid     = true;
    if(  isDefined(error_id)  ){
      var phone_fields = Form.getElements($(error_id).parentNode);
      if(phone_fields.length == 3){
        var phone_area      = phone_fields[0].value;
        var phone_exchange  = phone_fields[1].value;
        var phone_station   = phone_fields[2].value;
      }else if(phone_fields.length == 1){
        var phone_area      = phone_fields[0].value.substr(0,3);
        var phone_exchange  = phone_fields[0].value.substr(3,3);
        var phone_station   = phone_fields[0].value.substr(6,4);
      }

      if(  !/^[2-9][0-8][0-9]$/.test(phone_area) || !/^[2-9][0-9][0-9]$/.test(phone_exchange) || !/^[0-9][0-9][0-9][0-9]$/.test(phone_station)  ){
        is_valid = false;
        $(error_id).innerHTML = (error_msg == undefined) ? "\nPlease enter a valid phone number." : error_msg;;
        fadeIn(error_id);
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  function isValidHeight(error_id, error_msg){
    var is_valid = true;
    error_msg    = (error_msg == undefined) ? "\nPlease select a valid height." : error_msg;
    //validate height-weight
    if(isDefined(error_id)){
        var parent_node   = $(error_id).parentNode;
        var height_fields = parent_node.getElementsByTagName('SELECT');

        if(height_fields.length == 0){
          var height_fields = parent_node.getElementsByTagName('INPUT');
          error_msg = (error_msg == undefined) ? "\nPlease enter a valid height." : error_msg;
        }

        var height_feet   = trim($(height_fields[0].id).value);
        var height_inches = trim($(height_fields[1].id).value);

        if(  !/^\d$/.test(height_feet) && /^$/.test(height_feet) ){
          is_valid = false;
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
        }
        if(  is_valid  ){
          if(  !/^\d$/.test(height_inches) && /^$/.test(height_inches) ){
            is_valid = false;
            $(error_id).innerHTML = error_msg;
            fadeIn(error_id);
          }
        }

        if(  is_valid  ){
          fadeOut(error_id);
        }
    }
    return is_valid;
  }

  function isValidZip(error_id, error_msg){
    var is_valid   = true;
    error_msg    = (error_msg == undefined) ? '\nPlease enter a valid zip code.' : error_msg;
    if(isDefined(error_id)){
      var zipcode     = Form.getElements($(error_id).parentNode);
      if(  !/^\d{5}$/.test($F(zipcode[0].id))  ){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
        is_valid = false;
      }else{
        fadeOut(error_id);
      }
    }
    return is_valid;
  }

  /*
   *isValidDate(error_id)
   *returns: true/false
   *checks that the date belongs to the month within the given year
   */
  function isValidDob(error_id){
    var is_valid = true;
    is_valid     = isValidDate(error_id);

    if(is_valid){
      var todays_date   = new Date();

      var parent_node   = $(error_id).parentNode;
      var date_fields   = parent_node.getElementsByTagName('SELECT');
      error_msg         = '\nPlease select a valid date of birth.';

      if(date_fields.length == 0){
        var date_fields = parent_node.getElementsByTagName('INPUT');
        error_msg       = '\nPlease enter a valid date of birth.';
      }
      if(  date_fields.length == 3  ){
        var df_mm   = date_fields[0].value - 1;
        var df_dd   = date_fields[1].value;
        var df_yyyy = date_fields[2].value;
        var ins_date= new Date();
        ins_date.setFullYear(df_yyyy, df_mm, df_dd)
        is_valid    = (todays_date > ins_date);

        if(!is_valid){
          $(error_id).innerHTML = error_msg;
          fadeIn(error_id);
        }
      }
    }
    return is_valid;
  }

  /*
   *isValidChildDob(error_id)
   *returns: true/false
   *validates the date, child has to be  less than 25 yrs old, and younger than the youngest parent
   */
  function isValidChildDob(error_id){
    var is_valid = true;
    is_valid     = isValidDate(error_id);

    if(is_valid){
      var parent_node   = $(error_id).parentNode;
      var date_fields   = parent_node.getElementsByTagName('SELECT');
      error_msg         = '\nPlease select a valid date of birth.';

      if(date_fields.length == 0){
        var date_fields = parent_node.getElementsByTagName('INPUT');
        error_msg       = '\nPlease enter a valid date of birth.';
      }
      if( date_fields.length == 3 ){
        var child_mm     = $F(date_fields[0].id) - 1;
        var child_dd     = $F(date_fields[1].id);
        var child_yyyy   = $F(date_fields[2].id);
        var child_date   = new Date();
        var todays_date  = new Date();
        child_date.setFullYear(child_yyyy, child_mm, child_dd);

        //cannot be a future date
        is_valid         = (todays_date > child_date);

        if(is_valid){
          /*
           *child has to be at least 25yrs old
          */
          var child_age   = todays_date.getFullYear() - child_date.getFullYear();
          if(child_age > 25){
            is_valid = false;
            error_msg= "\nQuotes cannot be provided for children over 25 years old."
          }else{
            /*
             *compare child and parent
             */
            //get parent(s) dates
            var parent_date  = new Date();
            parent_date.setFullYear($F("dob1_yyyy_on"), ($F("dob1_mm_on") - 1), $F("dob1_dd_on"));

            if($F("dob2_yyyy_on") != "" && $F("dob2_mm_on") != "" && $F("dob2_dd_on") != ""){
              var spouse_date  = new Date();
              spouse_date.setFullYear($F("dob2_yyyy_on"), ($F("dob2_mm_on") - 1), $F("dob2_dd_on"));
            }
            //pick youngest parent
            var youngest_parent  = parent_date;
            if(spouse_date){
              var youngest_parent = (spouse_date > parent_date) ? spouse_date : parent_date;
            }

            //younger than the parent
            if(child_date <= youngest_parent){
              is_valid = false;
              error_msg= "\nChildren cannot be older than the parent(s)."
            }
          }
        }
      }
      if(!is_valid){
        $(error_id).innerHTML = error_msg;
        fadeIn(error_id);
      }
    }
    return is_valid;
  }

  /*
   *isValidCoverage(error_id)
   *returns: true/false
   *checks that the date belongs to the month within the given year, and
   *cannot be earlier than the current date
   */
 function isValidCoverage(error_id){
    var is_valid = true;
    is_valid     = isValidDate(error_id);

    if(is_valid){
      var todays_date   = new Date();
      var current_month = todays_date.getMonth() + 1;
      var current_day   = todays_date.getDate();
      var current_year  = todays_date.getFullYear();

      var parent_node   = $(error_id).parentNode;
      var date_fields   = parent_node.getElementsByTagName('SELECT');
      error_msg         = '\nPlease select a valid coverage date.';

      if(date_fields.length == 0){
        var date_fields = parent_node.getElementsByTagName('INPUT');
        error_msg       = '\nPlease enter a valid coverage date.';
      }
      if(  date_fields.length == 3  ){
        var id_mm   = date_fields[0].id;
        var id_dd   = date_fields[1].id;
        var id_yyyy = date_fields[2].id;

        if($(id_yyyy).value < current_year){
      	  is_valid = false;
        }else if($(id_yyyy).value == current_year){
          if($(id_mm).value < current_month){
        	  is_valid = false;
          }else if($(id_mm).value == current_month){
            if($(id_dd).value < current_day){
      	      is_valid = false;
            }
          }
        }
        if(!is_valid){
          $(error_id).innerHTML = "\nPlease select a valid <em>future</em> date less than 3 months from now.";
          fadeIn(error_id);
        }
        if(is_valid){
          /* Now that we know the date is at least a valid format, check to see that the coverage date is within a sensible range */
          var month = $F(date_fields[0]) * 1 - 1;
          var day   = $F(date_fields[1]) * 1;
          var year  = $F(date_fields[2]) * 1;
          var coverage_date = new Date(year, month, day);
          /* not more than 3 months from now  */
          var three_months_from_now = new Date();
          three_months_from_now.setDate(todays_date.getDate() + 90);
          var less_than_three_months_from_now = (coverage_date - three_months_from_now) <= 0;
          if (!less_than_three_months_from_now){
            $(error_id).innerHTML = '\nPlease select a valid future date <em>less than 3 months from now</em>.';
            fadeIn(error_id);
            is_valid = false;
          }
          if(is_valid)
            fadeOut(error_id);
        }
      }
    }
    return is_valid;
 }

  /*
   *isValidDate(error_id)
   *returns: true/false
   *checks that the date belongs to the month within the given year
   */
 function isValidDate(error_id){
    var is_valid         = true;
    if(isDefined(error_id)){
      //error msgs
      var error_msg_mm   = '\nPlease select a valid month.';
      var error_msg_dd   = '\nPlease select a valid day.';
      var error_msg_yyyy = '\nPlease select a valid year.';
      var error_msg_valid= '\nPlease select a valid date.';

      var parent_node    = $(error_id).parentNode;
      var date_fields    = parent_node.getElementsByTagName('SELECT');

      if(date_fields.length == 0){
        var date_fields  = parent_node.getElementsByTagName('INPUT');
        error_msg_mm     = '\nPlease enter a valid month.';
        error_msg_dd     = '\nPlease enter a valid day.';
        error_msg_yyyy   = '\nPlease enter a valid year.';
        error_msg_valid  = '\nPlease enter a valid date.';
      }
      if(  date_fields.length == 3  ){
        var id_mm   = date_fields[0].id;
        var id_dd   = date_fields[1].id;
        var id_yyyy = date_fields[2].id;

        if(isDefined(id_mm) && isDefined(id_dd) && isDefined(id_yyyy) && isDefined(error_id)){
          if(is_valid){
            if ( !/\d{1,2}/.test($F(id_mm)) ){
              $(error_id).innerHTML = error_msg_mm;
              fadeIn(error_id);
              is_valid = false;
            }
            if(is_valid){
              if ( !/\d{1,2}/.test($F(id_dd)) ){
                $(error_id).innerHTML = error_msg_dd;
                fadeIn(error_id);
                is_valid = false;
              }
            }
            if(is_valid){
              if ( !/\d{4}/.test($F(id_yyyy)) || ($F(id_yyyy) < 1911) || ($F(id_yyyy) > 2038) ){
                $(error_id).innerHTML = error_msg_yyyy;
                fadeIn(error_id);
                is_valid = false;
              }
            }
          }
        	//validate if it is a valid date (day is in the month)
          if(is_valid){
            var new_date = new Date();
            var this_mm  = $F(id_mm) - 1;
            new_date.setFullYear( $F(id_yyyy), this_mm, $F(id_dd) );
          	if ( new_date.getMonth() != this_mm ) {
              $(error_id).innerHTML = error_msg_valid;
              fadeIn(error_id);
          	  is_valid = false;
          	}
          }
        }
      }
    }
    return is_valid;
  }