//Paquetes externos
if (typeof addOnLoad != 'function') alert('No se ha especificado el paquete main');
addOnLoad(initValidForms);


//Constantes
var EMPTY_FIELD   = 0;
var INVALID_EMAIL = 1;
var INVALID_PHONE = 2;
var INVALID_URL   = 3;
var INVALID_PC    = 4;
var NO_ACCEPTED   = 5;

var i18n = {
  emptyField : 'Campo vacio',
  invalidEmail : 'Email invalido',
  invalidPhone : 'Numero de telefono no valido',
  invalidUrl : 'URL no valido',
  invalidPC : 'Codigo postal no valido',
  noAccepted : 'Debes aceptar las condiciones',
  notRecogError : 'Error no reconocido',
  errorInfoDivHead : 'Errores producidos'
}

//Configuracion
var config = {
  noNumStr : 'only-num',              //Clase identificadora de campo NUMERICO
  validateEmailStr : 'valid-email',   //Validar el email
	validatePhoneStr : 'valid-phone',   //Validar el telefono
	validateUrlStr : 'valid-url',       //Validar la url
	validatePCStr : 'valid-pc',         //Validar codigo postal
	acceptConditionStr : 'must-accept', //Aceptar las condiciones
	reqField : 'req',                   //Clase identificadora de campo REQUERIDO
	invalidClass : 'invalid',           //Clase identificadora de campo INVALIDO
	addInvalidToParentFormElem : true,  //Añadir 'invalid' al elemento padre del elemento invalido
	addInvalidToFormElem : true,       //Añadir 'invalid' al propio elemento invalido
	infoErrorValidationDiv : 'info-error-validation',
	noValidFormFunction : function(errors) {
	  var infoDiv = document.getElementById(this.infoErrorValidationDiv);
	  if (infoDiv) {
	    infoDiv.innerHTML = '';
	    //Eliminamos (si habia) los ul
	    delChilds(infoDiv);
	    //Creamos el ul
	    var ul = document.createElement('ul');
	    //Por cada error recogido
	    for (var i in errors) {
	      //Creamos el nodo de texto
	      var text = document.createTextNode(errorName(errors[i].type) + ': ' + errors[i].name);
	      //Creamos el nodo I
	      var li = document.createElement('li');
	      //Establecemos el DOM
	      li.appendChild(text);
	      ul.appendChild(li);
	    }
		var h2 = document.createElement('h2');
		h2.appendChild(document.createTextNode(i18n.errorInfoDivHead));
	    //Establecemos la cabecera
	    infoDiv.appendChild(h2);
	    //Linkamos el ul con el div
	    infoDiv.appendChild(ul);
	  }

	  function errorName (errorType) {
	    switch(errorType) {
	      case EMPTY_FIELD:
	        return i18n.emptyField;
	        break;
	      case INVALID_EMAIL:
	        return i18n.invalidEmail;
	        break;
	      case INVALID_PHONE:
	        return i18n.invalidPhone;
	        break;
	      case INVALID_URL:
	        return i18n.invalidUrl;
	        break;
	      case INVALID_PC:
	        return i18n.invalidPC;
	        break;
	      case NO_ACCEPTED:
	        return i18n.noAccepted;
	      default:
	        return i18n.notRecogError;
	    }
	  }
	  function delChilds (thisDiv) {
	    var childs = thisDiv.getElementsByTagName('*');
	    for (var i = 0; i < childs.length; i++) childs.removeChild(uls[i]);
	  }
	}
};


//Inicializar
function initValidForms () {
	var inputTags = document.getElementsByTagName('input');
	var docForms = document.forms;

	//Todos los tags a validar
	for (var i = 0; i < inputTags.length; i++) {
		connectTagToEvent(inputTags[i]);
	}
	//Todos los formularios a validar (cuando se envien)
	for (var j = 0; j < docForms.length; j++) {
		docForms[j].onsubmit = validateForm;
	}
	return false;
}
//Validar formulario
function validateForm () {
  //Errores
  var errors = new Array();
  //Todo a ido bien
  var allGood = true;
	//Recogemos todos los tags del formulario
	var formTags = this.getElementsByTagName('*');
	for (var i = 0; i < formTags.length; i++) {
	  var error = validateTag(formTags[i]);
		if (error != null) errors.push(error);
	}
	//Lanzamos la funcion de no valido
	if (errors.length > 0) {config.noValidFormFunction(errors); return false;}
	//Seguimos con el formulario o no
	return true;
}

//Validar tag de formulario
function validateTag(thisTag) {
  //Clase del tag
	var tagClass = thisTag.className;
	//Error
	var error = null;
	var valid = true;
	switch (thisTag.tagName) {
		case 'INPUT':
		case 'SELECT':
		case 'TEXTAREA':
			//Si hay que validar el codigo postal
			if (thisTag.value != '' && tagClass.indexOf(config.validatePCStr) != -1) {
			  if (!validPC (thisTag.value)) {
			    valid = false;
			    error = {name : thisTag.name, type : INVALID_PC};
			  }
			}
		  //Si hay que validar email
			if (thisTag.value != '' && tagClass.indexOf(config.validateEmailStr) != -1) {
			  if (!validEmail (thisTag.value)) {
			    valid = false;
			    error = {name : thisTag.name, type : INVALID_EMAIL};
			  }
			}
			//Si hay que validar el telefono
			if (thisTag.value != '' && tagClass.indexOf(config.validatePhoneStr) != -1) {
			  if (!validPhone (thisTag.value)) {
			    valid = false;
			    error = {name : thisTag.name, type : INVALID_PHONE};
			  }
			}
			//Si hay que validar la url
			if (thisTag.value != '' && tagClass.indexOf(config.validateUrlStr) != -1) {
			  if (!validUrl (thisTag.value)) {
			    valid = false;
			    error = {name : thisTag.name, type : INVALID_URL};
			  }
			}
		  //Si el campo es requerido
			if (tagClass.indexOf(config.reqField) != -1) {
			  //Si el tag está vacio
			  if (thisTag.value == '') {
		      valid = false;
		      //Requerido y vacio, RETORNAMOS FALSE
		      error = {name : thisTag.name, type : EMPTY_FIELD};
		    }
			}
			//Si debe aceptar las condiciones
			if (tagClass.indexOf(config.acceptConditionStr) != -1) {
        if (thisTag.checked == false) {
          valid = false;
          error = {name : thisTag.name, type : NO_ACCEPTED};
        }
			}
			break;
		default:
	}
	//Guardamos el estado en el input
	if (!valid) {
	  if (config.addInvalidToFormElem) addInvalid (thisTag);
		if (config.addInvalidToParentFormElem) addInvalid (thisTag.parentNode);
	} else {
	  if (config.addInvalidToFormElem) removeInvalid (thisTag);
		if (config.addInvalidToParentFormElem) removeInvalid (thisTag.parentNode);
	}
	return error;

	function addInvalid (thisTag) {
		  //Si no ha sido invalidado, le añadimos 'invalid'
		  if (thisTag.className.indexOf(config.invalidClass) == -1) {
		    if (thisTag.className == '') thisTag.className = config.invalidClass;
		    else thisTag.className += ' ' + config.invalidClass;
		  }
	}

	function removeInvalid (thisTag) {
	  //Buscamos un 'invalid' y si lo encontramos lo quitamos
	  var invalidIndex = thisTag.className.indexOf(config.invalidClass);
	  if (invalidIndex != -1) {
	    thisTag.className = (invalidIndex == 0) ? '' : thisTag.className.substr(0, invalidIndex);
	  } else {
	    if (thisTag.className == config.invalidClass) thisTag.className = '';
	  }
	}

	function validEmail (email) {
	  var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
	  return re.test(email);
	}

	function validPhone (phone) {
	  var re = /^(\(?\+?\d{2,3}\)?)?\s?(\d{3}[\s-]?\d{3}[\s-]?\d{3}|\d{2}[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}|\d{9})$/;
	  return re.test(phone);
	}

	function validUrl (url) {
	  var re = /^http:\/\/\w+(\.\w+)+(\/[\w\.\-\?\=\&]+)*?$/;
	  return re.test(url);
	}

	function validPC (pc){
    var re = /^\d{5}$/;
    return re.test(pc);
	}
}
//Conectar el input a un evento
function connectTagToEvent(thisTag) {
	var tagClass = thisTag.className;
	//Segun la clase procesamos
	if (tagClass.indexOf(config.noNumStr) != -1) {
		thisTag.onkeypress = checkOnlyNum;
		thisTag.onkeyup = checkOnlyNum;
		thisTag.onkeydown = checkOnlyNum;
		thisTag.onchange = checkOnlyNum;
	}

	//Comprobar que solo haya numeros
	function checkOnlyNum () {
		//Comprobamos solo el ultimo elemento insertado
		var lastChar = this.value [this.value.length - 1];
		//Si no es un numero lo borramos
		if (lastChar < '0' || lastChar > '9') this.value = this.value.substring(0, this.value.length - 1);
	}
}