/**
 * Uniform module
 */
UniForm = function() {
  
  /**
   * Counter used for form ID generation
   *
   * @var integer
   */
  var form_counter = 0;
  
  /**
   * Forms that are initialized
   *
   * @var Object
   */
  var forms = {};
  
  /**
   * Supported validators
   *
   * @var Object
   */
  var validators = {
    
    /**
     * Check if value of specific field is present
     *
     * @param jQuery field
     * @param string caption
     */
    required : function(field, caption, language) {

       

		// Caso radio button
		if (field.is('input[@type=radio]')) {
			var fieldName = field.attr('name');
			if (jQuery('input[@name=' + fieldName + ']:checked').length > 0) {
				return true;
			} 
		} else {
			if(field.val() != '') {
				return true;
			}
		}
		// Si llega hasta aqui es q no esta informado
		if (language == 'es') {return 'El campo es obligatorio';}
		else if (language == 'en') {return 'Field value is required';}
		else {return /*caption +*/ 'Camp requerit';}

      

     
    },
    
    /**
     * Validate is value of given field is shorter than supported
     *
     * @param jQuery field
     * @param sting caption
     */
    validate_minlength : function(field, caption, language) {
      var min_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_minlength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            min_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((min_length > 0) && (field.val().length < min_length)) {
		if (language == 'es') {return 'La longitud m\u00ednima del campo debe ser de ' + min_length + ' car\u00e1cteres';}
		else if (language == 'en') {return 'Field value should be at least ' + min_length + ' characters long';}
		else {return 'La longitud m\u00ednima del camp ha de ser de ' + min_length + ' car\u00e0cters';} 
      } else {
        return true;
      } // if
    },
    
    /**
     * Validate if field value is longer than allowed
     *
     * @param jQuery field
     * @param string caption
     */
    validate_maxlength : function(field, caption, language) {
      var max_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_maxlength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            max_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((max_length > 0) && (field.val().length > max_length)) {
		if (language == 'es') {return 'La longitud m\u00e1xima del campo debe ser de ' + max_length + ' car\u00e1cteres';}
		else if (language == 'en') {return 'Field value should not be longer than ' + max_length + ' characters';}
		else {return 'La longitud m\u00e0xima del camp ha de ser de ' + max_length + ' car\u00e0cters';}         
      } else {
        return true;
      } // if
    },
    
    /**
     * Make sure that field has same value as the value of target field
     *
     * @param jQuery field
     * @param string caption
     */
    validate_same_as : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      var classes = field.attr('class').split(' ');
      var target_field_name = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_same_as') {
          if(classes[i + 1] != 'undefined') {
            target_field_name = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      if(target_field_name) {
        var target_field = jQuery('#' + target_field_name);
        if(target_field.length > 0) {
          var target_field_caption = field_caption(field);
          
          if(target_field.val() != field.val()) {
			if (language == 'es') {return 'El valor del campo debe ser igual al del campo ' + target_field_caption;}
			else if (language == 'en') {return 'Field value is expected to be same as value of ' + target_field_caption + ' field';}
			else {return 'El valor del camp ha de ser igual al del camp ' + target_field_caption;}         
          } // if
        } // if
      } // if
      
      return true;
    },
    
    /**
     * Validate if provided value is valid email address
     *
     * @param jQuery field
     * @param string caption
     */
    validate_email : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
        return true;
      } else {
		if (language == 'es') {return 'El valor del campo no es una direcci\u00f3n de correo electr\u00f3nico v\u00e1lida';}
		else if (language == 'en') {return 'Field value is not a valid email address';}
		else {return 'El valor del camp no \u00e9s una direcci\u00f3 de correu electr\u00f2nic v\u00e0lida';}         
      }
    },
    
    /**
     * Validate if provided value is valid nif
     *
     * @param jQuery field
     * @param string caption
     */
    validate_nif : function(field, caption, language) {
    	if (field.val().length == 0) return true;
		var nif = field.val().toUpperCase();
		var NIF_STRING_ASOCIATION = "TRWAGMYFPDXBNJZSQVHLCKET";
		// Probamos nif		
        if (nif.match(/^[0-9]{8}[A-Z]$/)) {
        	var sNif = nif.charAt(8);
            var dni = parseInt(nif.substring(0,8));
            var character = NIF_STRING_ASOCIATION.charAt(dni % 23);
            if (character == sNif) {
                return true;// Es un nif correcto
            }
        }
        // No es un nif, probamos nie
        if (nif.match(/^[XT][0-9]{7}[A-Z]$/)) {
        	var sNie = nif.charAt(8);
            var dni = parseInt(nif.substring(1,8));
            var character = NIF_STRING_ASOCIATION.charAt(dni % 23);
            if (character == sNie) {
                return true;// Es un nie correcto
            }
        }        	
		// No es nif ni nie, mensaje        
		if (language == 'es') {return 'El valor del campo no es un nif v\u00e1lido';}
		else if (language == 'en') {return 'Field value is not a valid nif';}
		else {return 'El valor del camp no \u00e9s un nif v\u00e0lid';}         
    },    
    
    /**
     * Validate if provided value is valid cif
     *
     * @param jQuery field
     * @param string caption
     */
    validate_cif : function(field, caption, language) {
    	if (field.val().length == 0) return true;
		var pares = 0;var impares = 0;
		var suma;var ultima;var unumero;
		var uletra = new Array("J", "A", "B", "C", "D", "E", "F", "G", "H", "I");
		var xxx;
		
		var texto = field.val().toUpperCase();

		var regular = new RegExp(/^[ABCDEFGHKLMNPQS]\d\d\d\d\d\d\d[0-9,A-J]$/g);
		if (regular.exec(texto)) {
			 ultima = texto.substr(8,1);
			
			 for (var cont = 1 ; cont < 7 ; cont ++){
			     xxx = (2 * parseInt(texto.substr(cont++,1))).toString() + "0";
			     impares += parseInt(xxx.substr(0,1)) + parseInt(xxx.substr(1,1));
			     pares += parseInt(texto.substr(cont,1));
			 }
			 xxx = (2 * parseInt(texto.substr(cont,1))).toString() + "0";
			 impares += parseInt(xxx.substr(0,1)) + parseInt(xxx.substr(1,1));
			 
			 suma = (pares + impares).toString();
			 unumero = parseInt(suma.substr(suma.length - 1, 1));
			 unumero = (10 - unumero).toString();
			 if(unumero == 10) unumero = 0;

			if ((ultima == unumero) || (ultima == uletra[unumero])) {
				return true;// cif valido
			}
		}
     
		// No es un cif valido, mensaje
		if (language == 'es') {return 'El valor del campo no es un cif v\u00e1lido';}
		else if (language == 'en') {return 'Field value is not a valid cif';}
		else {return 'El valor del camp no \u00e9s un cif v\u00e0lid';}         
    },   
        
    /**
     * Validate if provided value is valid nif or cif
     *
     * @param jQuery field
     * @param string caption
     */
    validate_nifcif : function(field, caption, language) {
    	if (field.val().length == 0) return true;
		var validation_result = this.validate_cif(field, caption, language);
		if(typeof(validation_result) != 'string') {
			return true;// Es un cif
		}
		validation_result = this.validate_nif(field, caption, language);
    	if(typeof(validation_result) != 'string') {
			return true;// Es un nif    	
    	}
    	// No es ni un nif ni un cif, mensaje
		if (language == 'es') {return 'El valor del campo no es un nif o cif v\u00e1lido';}
		else if (language == 'en') {return 'Field value is not a valid nif o cif';}
		else {return 'El valor del camp no \u00e9s un nif o cif v\u00e0lid';}         
    },         
        
    /**
     * Validate if provided value is valid date
     *
     * @param jQuery field
     * @param string caption
     */
    validate_date : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/^(\d{1,2}\/\d{1,2}\/\d{4})$/i)) {
        return true;
      } else {
		if (language == 'es') {return 'El formato de fecha debe ser dd/mm/aaaa';}
		else if (language == 'en') {return 'Date value should be dd/mm/yyyy';}
		else {return 'El format de data ha de ser dd/mm/aaaa';}         
      }
    },          
        
    /**
     * Validate if provided value is valid URL
     *
     * @param jQuery field
     * @param string caption
     */
    validate_url : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i)) {
        return true;
      } else {
		if (language == 'es') {return 'El valor del campo no es una direcci\u00f3n web v\u00e1lida';}
		else if (language == 'en') {return 'Field value is not a valid URL';}
		else {return 'El valor del camp no \u00e9s una direcci\u00f3 web v\u00e0lida';}          
      }
    }, 
    
    /**
     * Number is only valid value (integers and floats)
     *
     * @param jQuery field
     * @param string caption
     */
    validate_number : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/)) {
        return true;
      } else {
		if (language == 'es') {return 'El valor del campo debe ser num\u00e8rico';}
		else if (language == 'en') {return 'Field value need to be a number';}
		else {return 'El valor del camp ha de ser num\u00e8ric';}           
      }
    },
    
    /**
     * Whole numbers are allowed
     *
     * @param jQuery field
     * @param string caption
     */
    validate_integer : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/(^-?\d\d*$)/)) {
        return true;
      } else {
		if (language == 'es') {return 'El valor del campo debe ser un n\u00famero entero';}
		else if (language == 'en') {return 'Field value need to be a whole number';}
		else {return 'El valor del camp ha de ser un nombre enter';}        
      }
    },
    
    /**
     * Letters only
     *
     * @param jQuery field
     * @param string caption
     */
    validate_alpha : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/^[a-zA-Z]+$/)) {
        return true;
      } else {
		if (language == 'es') {return 'El valor del campo solo debe contener letras (sin car\u00e1cteres especiales o n\u00fameros)';}
		else if (language == 'en') {return 'Field value should contain only letters (without special characters or numbers)';}
		else {return 'El valor del camp nom\u00e9s ha de contenir lletres (sense car\u00e0cters especials o nombres)';}
      }
    },
    
    /**
     * Letters and numbers
     *
     * @param jQuery field
     * @param string caption
     */
    validate_alphanum : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/\W/)) {
		if (language == 'es') {return 'El valor del campo solo debe contener letras y n\u00fameros (sin car\u00e1cteres especiales)';}
		else if (language == 'en') {return 'Field value should contain only numbers and letters (without special characters)';}
		else {return 'El valor del camp nom\u00e9s ha de contenir lletres i nombres (sense car\u00e0cters especials)';}        
      } else {
        return true;
      }
    },
    
    /**
     * Letters and numbers
     *
     * @param jQuery field
     * @param string caption
     */
    validate_apostrophe : function(field, caption, language) {
    	if (field.val().length == 0) return true;
      if(field.val().match(/\'/)) {
		if (language == 'es') {return 'El valor del campo no debe contener apostrofes';}
		else if (language == 'en') {return 'Field value should not contain apostrophes ';}
		else {return 'El valor del camp no pot contenir apostrofs';}        
      } else {
        return true;
      }
    },
    
    /**
     * Callback validator
     *
     * Lets you define your own validators. Usage:
     *
     * <input name="myinput" class="validate_callback my_callback" />
     *
     * This will result in UniForm searching for window.my_callback funciton and 
     * executing it with field and caption arguments. Sample implementation:
     *
     * window.my_callback = function(field, caption) {
     *   if(field.val() == 'A51') {
     *     return true;
     *   } else {
     *     return caption + ' value should be "A51"!';
     *   }
     * }
     *
     * @param jQuery field
     * @param caption
     */
    validate_callback : function(field, caption, language) {
      var classes = field.attr('class').split(' ');
      var callback_function = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_callback') {
          if(classes[i + 1] != 'undefined') {
            callback_function = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      //tiny_value_present
      
      if(window[callback_function] != 'undefined' && (typeof window[callback_function] == 'function')) {
        return window[callback_function](field, caption, language);
      } // if
      
      return 'Failed to validate ' + caption + ' field. Validator function (' + callback_function + ') is not defined!';
    }
    
  };
  
  /**
   * Go through form fields and validate their values
   *
   * @param jQuery for_form
   * @param boolean all_fields If true all fields will be validated. If not only 
   *   fields user focused will be validated
   * @param boolean
   */
  var validate_form = function(for_form, all_fields) {
    var result = true;
    // Cojemos el idioma del themeDisplay definido por liferay
    var language = themeDisplay.getLanguageId();
    if (language) language = language.substring(0,2);
    if(typeof(forms[for_form.attr('id')]['validation']) == 'object') {
      for(var field_name in forms[for_form.attr('id')]['validation']) {
      
        if(all_fields || forms[for_form.attr('id')]['focused_fields'][field_name]) {
          var field = forms[for_form.attr('id')]['validation'][field_name]['field'];
          // Trim del campo si es de texto
          if (field.is("input[@type=text]")) {field.val(jQuery.trim(field.val()));}
          var field_caption = forms[for_form.attr('id')]['validation'][field_name]['caption'];
          var field_validators = forms[for_form.attr('id')]['validation'][field_name]['validators'];
          
          for(var validator in field_validators) {
            var validation_result = validators[validator](field, field_caption, language, for_form);
            var padre="#div_"+field_name; //si el campo está escondido, no nos interesan las validaciones
            if(typeof(validation_result) == 'string' && !jQuery(padre).is(":hidden")) {
              set_field_error(field, validation_result);
              result = false;
              break;
            } else {
              remove_field_error(field);
            } // if
          } // for


        } // if
        
      }  // if
    } // if
    
    return result;
  };
  
  /**
   * Set field error
   *
   * @param jQuery for_field
   * @param string error_message
   * @return void
   */
  var set_field_error = function(for_field, error_message) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    
    holder.removeClass('error').find('.portlet-msg-error').remove();
    holder.addClass('error').prepend('<span class="errorField portlet-msg-error"><strong>' + error_message + '</strong></span>');
  };

  /**
   * Remove error div for a given field
   *
   * @param jQuery for_field
   * @return void
   */
  var remove_field_error = function(for_field) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    holder.removeClass('error').find('.portlet-msg-error').remove();
  };
  
  /**
   * Return holder DIV for a given field
   *
   * @param jQuery for_field
   * @return jQuery or false if holder is not found
   */
  var find_field_holder = function(for_field) {
    var parent = for_field.parent();
      
    while(typeof(parent) == 'object') {
      if(parent[0].nodeName == 'FORM') {
        return;
      } // if
      if(parent[0].className.indexOf('ctrl-holder') >= 0) {
        return parent;
      } // if
      parent = jQuery(parent.parent());
    } // while
    
    return false;
  };
  
  /**
   * Mark a specific field as forcused
   *
   * @param jQuery for_form
   * @param jQuery for_field
   * @return void
   */
  var mark_as_focused = function(for_form, for_field) {
    if(typeof(forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')]) == 'undefined') {
      forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')] = true;
    } // if
    
    var holder = find_field_holder(for_field);
    if(typeof(holder) == 'object') {
      if(holder.attr('class').indexOf('focused') == -1) {
        for_form.find('.' + 'focused').removeClass('focused'); // everything else should lose focus
        holder.addClass('focused'); // and we should focus this element
      } // if
    } // if
  };
  
  /**
   * Get caption for a given field (extract it from label)
   *
   * @param jQuery for_field
   * @return string
   */
  var field_caption = function(for_field) {
    var field_id = for_field.attr('id');
    if(field_id) {
      var label = jQuery('label[@for=' + field_id + ']');
      if(typeof(label) == 'object') {
        var text = label.text();
        if(text.substr(0, 1) == '*') {
          return text.substring(2);
        } else if(text.substr(text.length - 2, text.length - 1) == '*') {
          return text.substring(0, text.length - 2);
        } else {
          return text;
        } // if
      } // if
    } // if
    // No lo ha encontrado, devuelve un literal por defecto
    // Cojemos el idioma del themeDisplay definido por liferay
    var language = themeDisplay.getLanguageId();
    if (language) language = language.substring(0,2);
    if (language == 'es') {return 'Campo';}
    else if (language == 'en') {return 'Field';}
    else {return 'Camp';}
  };
  
  /**
   * Prepare form ID for a given form if it is not already set by the user
   *
   * @param jQuery for_form
   * @return string
   */
  var get_form_id = function(for_form) {
    var form_id = for_form.attr('id');
      
    if(!form_id) {
      form_counter++;
      form_id = 'uniform_form_' + form_counter;
      for_form.attr('id', form_id);
    } // if
    
    return form_id;
  };
  
  /**
   * Attach onunload event that will show confirmation dialog if something is 
   * changed in the form
   *
   * @param jQuery for_form
   * @return void
   */
  var ask_on_leave = function(for_form) {
    var func = function() {
      if(!forms[for_form.attr('id')]['ok_to_submit']) {
        if(for_form.formSerialize() != forms[for_form.attr('id')]['initial_data']) {
          return 'All changes you have made to this page will be lost!';
        } // if
      } // if
    };
    
    var oldOnBeforeUnload = window.onbeforeunload;
    if(typeof(window.onbeforeunload) != 'function') {
      window.onbeforeunload = func;
    } else {
      window.onbeforeunload = function() {
        oldOnBeforeUnload();
        func();
      } // function
    } // if
  };
  
  /**
   * Public interface
   */
  return {
    
    /**
     * Initialize form
     *
     * @param jQuery form
     * @return void
     */
    init : function(form, settings) {
      var fields = form.find(settings.field_selector);
      var form_id = get_form_id(form);
      
      // Register form
      forms[form_id] = {
        'form'           : form,
        'fields'         : fields,
        'settings'       : settings,
        'initial_data'   : form.formSerialize(),
        'validation'     : {},
        'focused_fields' : {},
        'ok_to_submit'   : false
      };
      
      // Attach on unload behavior
      if(form.attr('class').indexOf('askOnLeave') != -1) {
        ask_on_leave(form);
      } // if
      
      // Walk through defined validators and maku sure that they do their trick
      for(validator in validators) {
        form.find('.' + validator).each(function() {
          var field = jQuery(this);
          var field_name = field.attr('name');
          
          if(typeof forms[form_id]['validation'][field_name] != 'object') {
            forms[form_id]['validation'][field_name] = {
              'field'      : field,
              'caption'    : field_caption(field),
              'validators' : {}
            };
          } // if
          
          forms[form_id]['validation'][field_name]['validators'][validator] = validators[validator];
        });
      } // for
      
      fields.focus(function() {
        mark_as_focused(form, jQuery(this));
      }).blur(function() {
        validate_form(form, false);
      });
      
      

      // Form submission handler
      form.submit(function() {
        var is_valid = validate_form(form, true);
        if(is_valid) {
          forms[form.attr('id')]['ok_to_submit'] = true;
          return true;
        } else {
          return false;

        } // if
      });
      
    } // init
    
  };
  
}();

/**
 * Register jQuery plugin
 */
jQuery.fn.uniform = function(settings) {
  settings = jQuery.extend({
    valid_class    : 'valid',
    invalid_class  : 'invalid',
    focused_class  : 'focused',
    holder_class   : 'ctrl-holder',
    field_selector : 'input, select, textarea'
  }, settings);
  
  return this.each(function() {
    UniForm.init(jQuery(this), settings);
  });
  
} // uniform
                      
