/**
 * Copyright (c) 2009 Completta
 * www.agenciacompletta.com.br
 *
 * Form field validation
 *
 */

$(function($) {
	$.fn.clearForm = function() {
		return this.each(function() {
			var type = this.type, tag = this.tagName.toLowerCase();
			if (tag == 'form')
				return $(':input',this).clearForm();
			if (type == 'text' || type == 'password' || tag == 'textarea')
				this.value = '';
			else if (type == 'checkbox' || type == 'radio')
				this.checked = false;
			else if (tag == 'select')
				this.selectedIndex = -1;
		});
	}
	runMaskValidation();
});


var runMaskValidation = function() {

	var masks = [ // the last will be the first
		'msknotempty',
		'mskcei',
		'mskcep',
		'mskcpf',
		'mskcnpj',
		'mskcpfcnpj',
		'mskemail',
		'mskphone',
		'mskphoneonly',
		'mskdatedmy',
		'msknumeric',
		'mskaccountnumber',
		'mskintegers',
		'mskcurrency',
		'mskuppercase'
	];

	$('form input, form select').each(function(i){
		var len = masks.length;
		var clss = '';
		while(len--) {
			clss = masks[len];
			if ($(this).hasClass(clss)) {
				// keyup
				$(this).bind('keyup', {msk: clss}, function(e){ SetMask(this, e.data.msk); });

				// blur
				$(this).bind('blur', {msk: clss}, function(e){
					var oContainer = $(this).parents('.u').removeClass('msk-error');
					if (!CheckMask(this, e.data.msk)) {
						oContainer.addClass('msk-error');
					}
				});
			}
		}
	});


	// mask
	var SetMask = function(el, msk) {
		var mskcei = function(s) { // 00.000.00000/00
			s=s.replace(/\D/g,'');								// strip non-digits
			s=s.replace(/^(\d{2})(\d)/,'$1.$2');				// 00.0
			s=s.replace(/^(\d{2})\.(\d{3})(\d)/,'$1.$2.$3');	// 00.000.0
			s=s.replace(/\.(\d{5})(\d{1,2})(\d*)/,'.$1/$2');	// 00.000.000/0
			return s;
		}
		var mskcep = function(s) {
			s=s.replace(/\D/g,'');										// strip non-digits
			s=s.replace(/^(\d{2})(\d)/,'$1.$2');						// 00.0
			s=s.replace(/^(\d{2})\.(\d{3})(\d{1,3})(\d*)/,'$1.$2-$3');	// 00.000-000
			return s;
		}
		var mskcpf = function(s) {
			s=s.replace(/\D/g,'');							// strip non-digits
			s=s.replace(/(\d{3})(\d)/,'$1.$2');				// 000.0
			s=s.replace(/(\d{3})(\d)/,'$1.$2');				// 000.000.0
			s=s.replace(/(\d{3})(\d{1,2})(\d*)$/,'$1-$2');	// 000.000.000-00
			return s;
		}
		var mskcnpj = function(s) {
			s=s.replace(/\D/g,'');								// strip non-digits
			s=s.replace(/^(\d{2})(\d)/,'$1.$2');				// 00.0
			s=s.replace(/^(\d{2})\.(\d{3})(\d)/,'$1.$2.$3');	// 00.000.0
			s=s.replace(/\.(\d{3})(\d)/,'.$1/$2');				// 00.000.000/0
			s=s.replace(/(\d{4})(\d{1,2})(\d*)/,'$1-$2');		// 00.000.000/0000-00
			return s;
		}
		var mskcpfcnpj = function(s) {
			// xxx.xxx.xxx-xx (14 chars)
			if (s.length <= 14) return mskcpf(s);
			else return mskcnpj(s);
		}
		var mskdatedmy = function(s) {
			s=s.replace(/[^\/0-9]/g,'');							// strip non-digits
			s=s.replace(/\/+/g,'/');								// strip /
			s=s.replace(/^(\d{1})(\/{1})(\d)/,'0$1$2$3');			// 0/0 > 00/0 (extra zero for day)
			s=s.replace(/^(\d{2})(\d)/,'$1/$2');					// 00/0
			s=s.replace(/^(\d{2}\/{1})(\d{1}\/)(\d)/,'$10$2$3');	// 00/0/0 > 00/00/0  (extra zero for month)
			s=s.replace(/^(\d{2})\/(\d{2})(\d)/,'$1/$2/$3');		// 00/00/0
			s=s.replace(/\/(\d{4})(\d*)/,'/$1');					// 00/00/0000
			return s;
		}
		var mskemail = function(s) {
			return s.toLowerCase();
		}
		var mskphone = function(s) {
			s=s.replace(/\D/g,'');						// strip non-digits
			s=s.replace(/^(\d\d)(\d)/g,'$1 $2');		// 00 0
			s=s.replace(/(\d{4})(\d{4})(\d*)/,'$1-$2');	// 00 0000-0000
			return s;
		}
		var mskphoneonly = function(s) {
			s=s.replace(/\D/g,'');							// strip non-digits
			s=s.replace(/(\d{3,4})(\d{4})(\d*)/,'$1-$2');	// 0000-0000
			return s;
		}
		var msknumeric = function(s) {
			s=s.replace(/\D/g,'');								// strip non-digits
			var rgx = /(\d+)(\d{3})/;
			while (rgx.test(s)) { s=s.replace(rgx, '$1.$2'); }	// insert '.'
			return s;
		}
		var mskaccountnumber = function(s) {
			s=s.replace(/\D/g,'');								// strip non-digits
			s=s.replace(/(\d+)(\d)/, '$1-$2');					// 0-0
			var rgx = /(\d+)(\d{3})/;							// 0.000-0
			while (rgx.test(s)) { s=s.replace(rgx, '$1.$2'); }	// insert '.'
			return s;
		}
		var mskintegers = function(s) {
			return s.replace(/\D/g,'');								// strip non-digits
		}
		var mskcurrency = function(s) {
			s=s.replace(/\D/g,'');											// strip non-digits
			if (s.length <= 2) { return s; }
			var rgx = /^(\d+)(\d{2})$/;
			return msknumeric(s.replace(rgx,'$1')) + s.replace(rgx,',$2');	// strip '.' and ','
		}
		var mskuppercase = function(s) {
			return s.toUpperCase();
		}
		switch(msk) {
			case 'mskcei':
			case 'mskcep':
			case 'mskcpf':
			case 'mskcnpj':
			case 'mskcpfcnpj':
			case 'mskemail':
			case 'mskdatedmy':
			case 'mskphone':
			case 'mskphoneonly':
			case 'msknumeric':
			case 'mskaccountnumber':
			case 'mskintegers':
			case 'mskcurrency':
			case 'mskuppercase':
				var s;
				eval('s = ' + msk + '(el.value)');
				$(el).val(s);
			default: break;
		}
	} // SetMask

	// validation
	var CheckMask = function(el, msk) {
		if (msk != 'msknotempty' && el.value == '') { return true; }

		var CheckMaskCEI = function(el, msk) {
			var cei = el.value.replace(/\D/g, '');
			var len = cei.length;
			if (len != 12) {
				return false;
			}
			var sum = 0;
			var m = [7, 4, 1, 8, 5, 2, 1, 6, 3, 7, 4];
			for (i = 0; i < m.length; i++) {
				sum += cei.charAt(i) * m[i];
			}
			var p = ''+sum;

			len = p.length;
			p = ((1 * p.charAt(len - 2)) + (1 * p.charAt(len - 1))) + '';
			dv = 10 - p.charAt(p.length - 1);

			return (dv == cei.charAt(cei.length - 1));
		}

		var CheckMaskCPF = function(el, msk) {
			var cpf = el.value.replace(/\D/g, '');
			s = (/^(\d{3}\.){2}\d{3}\-\d{2}$/.test(el.value) && !/^(0{11}|1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11})$/.test(cpf));
			if (s) {
				var a = [];
				// 1st
				var b = 0; var c = 10;
				for (i=0; i<9; i++) {
					a[i] = cpf.charAt(i);
					b += a[i] * c--;
				}
				a[9] = ((a[9] = b % 11) < 2) ? 0 : 11 - a[9];
				// 2nd
				b = 0; c = 11;
				for (i=0; i<10; i++) { b += (a[i] * c--); }
				a[10] = ((a[10] = b % 11) < 2) ? 0 : 11 - a[10];
				// return
				s = !((cpf.charAt(9) != a[9]) || (cpf.charAt(10) != a[10]));
			}
			return s;
		}

		var CheckMaskCNPJ = function(el, msk) {
			s = (/^\d{2}(\.\d{3}){2}\/\d{4}\-\d{2}$/.test(el.value));
			if (s) {
				var cnpj = el.value.replace(/\D/g, '');
				var a = [];
				var b = new Number;
				var c = [6,5,4,3,2,9,8,7,6,5,4,3,2];
				for (i=0; i<12; i++){
					a[i] = cnpj.charAt(i);
					b += a[i] * c[i+1];
				}
				if ((x = b % 11) < 2) { a[12] = 0 }
				else { a[12] = 11-x }
				b = 0;
				for (y=0; y<13; y++) { b += (a[y] * c[y]); }
				if ((x = b % 11) < 2) { a[13] = 0; } else { a[13] = 11-x; }
				s = !((cnpj.charAt(12) != a[12]) || (cnpj.charAt(13) != a[13]));
			}
			return s;
		}

		// validate masks
		var s = false;
		if (msk == 'mskcpf') {
			s = CheckMaskCPF(el, msk);
		}
		else if (msk == 'mskcei') {
			s = CheckMaskCEI(el, msk);
		}
		else if (msk == 'mskcnpj') {
			s = CheckMaskCNPJ(el, msk);
		}
		else if (msk == 'mskcpfcnpj') {
			// xxx.xxx.xxx-xx (14 chars)
			s = (el.value.length <= 14) ? CheckMaskCPF(el, msk) : CheckMaskCNPJ(el, msk);
		}
		else if (msk == 'mskdatedmy') {
			s = Date.isValid(el.value, 'd/M/y');
		}
		//else if (msk == 'mskpastdatedmy') {
		//	s = Date.parseString(el.value, 'd/M/y');
		//	s = (s.isBefore(new Date()) && true);
		//}
		else if (msk == 'mskuppercase') {
			s = ($(el).val() == $(el).val().toUpperCase());
		}
		else {
			switch(msk) {
				case 'mskcep':		s = /^\d{2}\.\d{3}\-\d{3}$/; break;
				case 'mskemail': 	s = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; break;
				case 'mskphone':	s = /^\d{2} \d{3,4}\-\d{4}$/; break;
				case 'mskphoneonly':s = /^\d{3,4}\-\d{4}$/; break;
				case 'msknumeric':	s = /^((\d{1,3}\.)*\d{3}|(\d){1,3})$/; break;
				case 'mskintegers':	s = /^(\d+)$/; break;
				case 'mskaccountnumber': s = /^(\d{1,3})?(\.\d{3})*\-(\d+)$/; break;
				case 'msknotempty':	s = /^(.+)$/; break;
				case 'mskcurrency':	s = /^((\d{1,3}\.)*\d{3}|(\d){1,3})(\,\d{2})$/; break;
				default: break;
			}
			s = s.test($(el).val());
		}
		return s;
	} // CheckMask
}
