/**
 * Form utility library
 *
 * @author Andrejs Semovs, "ALT RD" SIA <andrejs@alt.lv>
 * @copyright Copyright &copy; 2004-2007, Andrejs Semovs, "ALT RD" SIA
 * @last_change 2007-07-04
 * Depends on: datetime.js
 */

/* Defining variables & constants */
if(!lng_invalid_field_values) var lng_invalid_field_values = "One or more field values have incorrect data or length!";

if(typeof VR_EMPTY == 'undefined') var VR_EMPTY = 0;
if(typeof VR_VALID == 'undefined') var VR_VALID = 1;
if(typeof VR_INVALID == 'undefined') var VR_INVALID = 2;

var t_int = 1;
var t_str = 2;
var t_float = 3;
var t_date = 4;
var t_select_date = 5;


/* Functions */

function isRadioChecked(el) {
   for(ei = 0; ei < el.length; ei++)
      if(el[ei].checked) return true;

   return false;
}

function isAnyCheckboxChecked(fo, name) {
   for(j = 0; j < fo.elements.length; j++) {
      if(fo.elements[j].type == 'checkbox' && fo.elements[j].name == name && fo.elements[j].checked) {
         return true;
      }
   }
   return false;
}

/* Returns all groups and all elements of the group, where el_name element is located */
function getElementGroupIndexes(el_name, all_groups) {
   var out = [];

   for(var egi = 0; egi < all_groups.length; egi++) {
      for(var egj = 0; egj < all_groups[egi][1].length; egj++) {
         if(all_groups[egi][1][egj] == el_name) {
            out[out.length] = new Array(egi, egj);
         }
      }
   }

   return out.length ? out : false;
}

function validateForm(fo,f_names,f_type,attr,len,groups,handlers,emsg,silent) {
   if(!fo) {
      alert("Fatal error: wrong form object passed!");
      return false;
   }

   var value = "";
   var result = true;
   var this_result = VR_VALID;
   var f_bad = [];   /* Bad fields in form */
   var group = null;
/* Group data is array with following elements:
      0 - group name;
      1 - array of field names, which belong to group;
      2 - group validation result (true - valid; false - invalid);
      3 - group validation options;
      4 - number of validated fields in group;
      5 - number of invalid fields in group;
      6 - number of empty fields in group;
*/
   var indexes = 0;

   /* Attīram laukiem sarkanu fonta krāsu un paslēpjam lauku kļūdu ziņojumus */
   for(var i = 0; i < f_names.length; i++) {
      if(el = document.getElementById(f_names[i])) el.style.color = "#000000";
      if(el = document.getElementById(f_names[i] + "_emsg")) el.style.display = "none";
   }

   /* Initializing group properties */
   for(var i = 0; i < groups.length; i++) {
      groups[i][4] = [];
      groups[i][5] = [];
      groups[i][6] = [];
   }

   /* Izejam cauri visiem ievadlaukiem */
   for(var i = 0; i < f_names.length; i++) {
      result = true;
      this_result = VR_VALID;
      el = fo.elements[f_names[i]];

      indexes = getElementGroupIndexes(f_names[i], groups);

      /* Custom handlers */
      if(handlers[i] != undefined) {
         if(typeof(el) != "undefined") {
            var tmp_res = handlers[i](fo, el, i);
         } else {
            var tmp_res = handlers[i](fo, f_names[i], i);
         }
         if(tmp_res === true) tmp_res = VR_VALID; else if(tmp_res === false) tmp_res = VR_INVALID;

         if(tmp_res == VR_INVALID || (attr[i] == 1 && tmp_res == VR_EMPTY)) {
            if(!indexes) {
//         if(handlers[i] != undefined) alert(el + " : " + f_names[i] + " : " + handlers[i] + "; Tmpres = " + tmp_res);
               result = false;
               f_bad[f_bad.length] = f_names[i];
               this_result = VR_INVALID;

            } else this_result = tmp_res;

         } else this_result = tmp_res;

      } else /* Normal validation */
      if(el != undefined) {
//         alert(i + ") Attr: " + attr[i] + " Type: " + f_type[i] + " Name: " + f_names[i] + " Len: " + len[i] + " El_name: " + el.name + " El_type: " + el.type + " El_value: " + el.value + " Result: " + result + " El: " + el + " Indexes: " + indexes);
         if(el.type == undefined) {
            if(attr[i] == 1 && !isRadioChecked(el)) {
               if(!indexes) {
                  result = false;
                  f_bad[f_bad.length] = f_names[i];
               }
               this_result = VR_EMPTY;
            }

         } else if(attr[i] == 0) el.value = null; /* Ja lauks nav ievadformā, attīram tā vērtību */
         else {
            if(!el.value.length && indexes) this_result = VR_EMPTY;
            else if(attr[i] == 1 && (el.value.length == 0 || el.value == 0 || el.value == "")) { /* Ja lauks ir obligāts un tā garums ir 0, vai vērtība ir 0 vai tukša simbolu virkne, atgriežam kļūdu */

               if(!indexes) {
                  result = false;
                  f_bad[f_bad.length] = f_names[i];
               }
               this_result = VR_INVALID;

            } else {
               if(el.value.length > len[i] && len[i] != 0) { /* Ja garums (simbolos) ir lielāks par atļauto, atgriežam kļūdu */
                  if(!indexes) {
                     result = false;
                     f_bad[f_bad.length] = f_names[i];
                  }
                  this_result = VR_INVALID;

               } else if(el.value.length > 0) {

                  if(f_type[i] == t_int) {
                     if(validInt(el.value) == false) {
                        if(!indexes) {
                           result = false;
                           f_bad[f_bad.length] = f_names[i];
                        }
                        this_result = VR_INVALID;
                     }

                  } else if(f_type[i] == t_float) {
                     if(validFloat(el.value) == false) {
                        if(!indexes) {
                           result = false;
                           f_bad[f_bad.length] = f_names[i];
                        }
                        this_result = VR_INVALID;
                     }

                  } else if(f_type[i] == t_date) {
                     if(validDateFormat(el, 8) == false) {
                        if(!indexes) {
                           result = false;
                           f_bad[f_bad.length] = f_names[i];
                        }
                        this_result = VR_INVALID;
                     }

                  }

               } else if(indexes) this_result = VR_EMPTY;
            }
         }

      } else if(f_type[i] == t_select_date) {
         var tmp_names = [f_names[i] + "_year", f_names[i] + "_month", f_names[i] + "_day"];
         var tmp_values = [0, 0, 0];
         var empty = true;
         var isset = false;

         for(var ti = 0; ti < tmp_names.length; ti++) {
            if(typeof(fo.elements[tmp_names[ti]]) != "undefined") {
               tmp_values[ti] = parseInt(fo.elements[tmp_names[ti]].value);
               if(tmp_values[ti]) {
                  empty = false;
               }
               isset = true;
            }
         }

         if(isset) {
            if(empty && indexes) this_result = VR_EMPTY;
            else if((attr[i] == 1 && empty) || (!checkDate(tmp_values[0], tmp_values[1], tmp_values[2]) && !empty)) {
               if(!indexes) {
                  result = false;
                  f_bad[f_bad.length] = f_names[i];
               }
               this_result = VR_INVALID;
            }
         }
      }

      if(indexes != false) {
         /* Cycle throught all groups, where field is specified and set result */
         for(var iix = 0; iix < indexes.length; iix++) {
            switch(this_result) {
               case VR_EMPTY:
                  groups[indexes[iix][0]][6].push(f_names[i]);
               break;

               case VR_VALID:
                  groups[indexes[iix][0]][4].push(f_names[i]);
               break;

               case VR_INVALID:
                  groups[indexes[iix][0]][5].push(f_names[i]);
               break;
            }
         }
//           if(indexes) alert("Group: " + groups[indexes[iix][0]][0] + "; This result: " + this_result + "; Result: " + result + "; Valid: " + groups[indexes[0]][2] + "; El name: " + f_names[i]);
      }
   }

   var bad_groups = false;

   /* Ja grupas nav validētas, tad ierakstām to grupu laukus f_bad masīvā */
   for(var i = 0; i < groups.length; i++) {
      /* Validating group according to its type */
      var cnt_valid = groups[i][4].length;
      var cnt_invalid = groups[i][5].length;
      var cnt_empty = groups[i][6].length;
//      alert(groups[i] + "\r\n Valid: " + cnt_valid + "; Invalid: " + cnt_invalid + "; Empty: " + cnt_empty);

      if(cnt_invalid > 0) groups[i][2] = false;
      else switch(groups[i][3]) {
         case FG_TYPE_ATLEAST_ONE:
            if(cnt_valid > 0 && cnt_invalid == 0) groups[i][2] = true;
            else groups[i][2] = false;
            break;

         case FG_TYPE_ONLY_ONE:
            if(cnt_valid == 1 && cnt_invalid == 0) groups[i][2] = true;
            else groups[i][2] = false;
            break;

         case FG_TYPE_NONE_OR_ALL:
            if((cnt_empty == 0 || cnt_valid == 0) && cnt_invalid == 0) groups[i][2] = true;
            else groups[i][2] = false;
            break;
      }
//      alert("SUMMARY: Group: " + groups[i][0] + "; Valid: " + groups[i][2] + "; Index: " + groups[i][3] +"; Valid: " + groups[i][4] + "; Invalid: " + groups[i][5] + "; Empty: " + groups[i][6]);
      /* If one or more of group elements is invalid, put them to f_bad array */
      if(groups[i][2] == false) {
         bad_groups = true;
         result = false;

         if(cnt_invalid > 0) f_bad = f_bad.concat(groups[i][5]);
         else if(cnt_empty > 0) f_bad = f_bad.concat(groups[i][6]);
         else if(cnt_valid > 0) f_bad = f_bad.concat(groups[i][4]);
      }
   }
//         alert(f_bad + " Result: " + result);

   if(f_bad.length > 0) result = false;

   /* Reorganizējam nepareizus laukus saskaņā ar lauku secību */
   var f_bad_out = [];
   var f_bad_index = []; /* Indexes of bad fields in f_names array */
//   if(bad_groups) {
      for(i = 0; i < f_names.length; i++) {
         for(j = 0; j < f_bad.length; j++)
            if(f_bad[j] == f_names[i]) {
               f_bad_out[f_bad_out.length] = f_names[i];
               f_bad_index[f_bad_index.length] = i;
               break;
            }
      }
      f_bad.length = 0;
      f_bad = f_bad_out;
//   }

   if(!result) {
      /* Parādam nepareizus laukus ar sarkanu krāsu */
      for(i = 0; i < f_bad.length; i++) {
         if(el = document.getElementById(f_bad[i])) el.style.color = "#FF0000";
         if(el = document.getElementById(f_bad[i] + "_emsg")) {
            el.innerHTML = emsg[f_bad_index[i]];
            el.style.display = "block";
         }
      }
      if(!silent) alert(lng_invalid_field_values);
      el = fo.elements[f_bad[0]];
      if(el != undefined) {
         if(el.type != "hidden") {
            if(el.type != undefined) el.focus();
            else el[0].focus();
         }
      }
   }

   /* Deallocate memory */
   f_bad = null;
   f_bad_index = null;
   f_bad_out = null;

   return result;
}

function validFloat(val) {
   if(val.search(/^[\s]*[-+]?[0-9]+[.]?[0-9]*[\s]*$/) !== -1) return true;
   else return false;
}

function validInt(val) {
   if(val.search(/^[\s]*[-+]?[0-9]+[\s]*$/) !== -1) return true;
   else return false;
}

function validDateFormat(field, minlen) {
   var strDate = field.value;
   var strDateArray;
   var strDay;
   var strMonth;
   var strYear;

   if(strDate.length < minlen){
      field.focus();
      return false;
   }

   if(strDate.length > 0) {
      strDateArray = strDate.split('.');
      if(strDateArray.length != 3) strDateArray = strDate.split('-');  // Mēģinām ar strīpu (ricks)
      if(strDateArray.length != 3) {
         field.focus();
         return false;
      } else {
         strYear = strDateArray[0];
         strMonth = strDateArray[1];
         strDay = strDateArray[2];
      }
      if((isNaN(strDay)) || (isNaN(strMonth)) || (isNaN(strYear))) {
         field.focus();
         return false;
      }
      if((strMonth > 12) || (strDay > 31)  || (strYear < 1900)) {
         field.focus();
         return false;
      }
   }
   return true;
}

function selectOptionByValue(fo, value, select_name) {
   if(!fo.elements[select_name]) return false;

   for(var i = 0; i < fo.elements[select_name].length; i++) {
      if(fo.elements[select_name].options[i].value == value) {
         fo.elements[select_name].selectedIndex = i;
         return true;
      }
   }

   return false;
}


/* CLASSES */

/* FormChangeTracker class allows to determine if form data was changed */
function FormChangeTracker(fo) {
   /* Properties */
   this.form = fo;
   this.changed = false;
   this.ignore = false;
   this.ignore_types = [];
   this.ignore_names = [];

   /* Methods */
   this.isChanged = function() { return this.changed; }
   this.setIgnoreTypes = function(a) { this.ignore_types = a; }
   this.setIgnoreNames = function(a) { this.ignore_names = a; }

   this.addEventListener = function(el, event, handler, capture) {
      if(typeof(el.attachEvent) != "undefined") {
         el.attachEvent("on" + event, handler);
      } else if(typeof(el.addEventListener) != "undefined") {
         el.addEventListener(event, handler, capture);
      } else {
         eval("el.on" + event + " = handler;");
      }
   }

   this.register = function(handler) {
      var local_ignore = false;

      if(typeof this.form != "undefined") {
         for(var i = 0; i < this.form.elements.length; i++) {
            el = this.form.elements[i];

            /* Skip setting event handler for element types which are specified
             * in this.ignore_types array.
             */
            for(var j = 0; j < this.ignore_types.length; j++) {
               if(this.ignore_types[j] == el.type) {
                  local_ignore = true;
                  break;
               }
            }

            /* Skip setting event handler for element names which are specified
             * in this.ignore_names array.
             */
            for(var j = 0; j < this.ignore_names.length; j++) {
               if(this.ignore_names[j] == el.name) {
                  local_ignore = true;
                  break;
               }
            }

            if(!local_ignore) {
               /* Set event handler */
               switch(el.type) {
                  case "radio":
                  case "button":
                  case "checkbox":
                     this.addEventListener(el, 'click', handler, false);
//                     el.onclick = handler;
                  break;

                  case "text":
                  case "select-one":
                  case "select-multiple":
                  case "textarea":
                  case "file":
                     this.addEventListener(el, 'change', handler, false);
//                     el.onchange = handler;
                  break;

               }
            }
            local_ignore = false;
         }
         return true;

      } else return false;
   }

   this.setIgnore = function(val) {
      this.ignore = val ? true : false;
   }

   this.getIgnore = function() {
      return this.ignore;
   }
}
