
// requires jooxbr.js

var JSValidator = function( form )
{
	
	this.attach = function( form )
	{
		form.jsvoldonsubmit = form.onsubmit;
		form.jsvobj = this;
		form.onsubmit = function()
		{
			if( this.jsvoldonsubmit )
			{
				if( this.jsvoldonsubmit() === false )
				{
					return false;
				}
			}
			return this.jsvobj.processForm( this );
		};
	};
	
	this.forceAttach = function( form )
	{
	};

	// constructor {
	if( form != null )
	{
		this.attach( form );
	}
	// }
 
	this.processForm = function( form )
	{
		for( var i = 0; i < form.elements.length; i++ )
		{
			var err = this.processElement( form.elements[ i ] );
			if( err !== true )
			{
				alert( err );
				var ctl = $( form.elements[ i ] );
				ctl.focus();
				if( ctl.selectAll )
				{
					ctl.selectAll();
				}
				return false;
			}
		}
		return true;
	};

	this.processElement = function( elem )
	{
		switch( Aux.getCtlType( elem ) )
		{
			case 'textfield':
				return this.processText( elem );
		}
		return true;
	};

	this.parseAttributes = function( elem )
	{
		return {
			required : elem.getAttribute( 'jsvrequired' ) != null
			, name : elem.getAttribute( 'jsvname' )
			, handler : elem.getAttribute( 'jsvhandler' )
			, type : elem.getAttribute( 'jsvtype' )
			, match : elem.getAttribute( 'jsvmatch' )
			, matchdescription : elem.getAttribute( 'jsvmatchdescription' )
		};
	};

	this.processText = function( elem )
	{
		var ctl = $( elem );
		var attrs = this.parseAttributes( elem );
		var name = attrs.name != null ? attrs.name : ctl._elem.name;
		var errstart = 'Field \'' + name + '\' ';
		if( name == 'Email' )
		{
			var errstart = 'We will send you an e-mail confirmation of your order. Your \'' + name + '\' ';
		}
		if( attrs.required && ctl.isEmpty() )
		{
			return errstart + 'is required!';
		}
		if( attrs.handler != null && window[ attrs.handler ] != null && typeof( window[ attrs.handler ] ) == 'function' )
		{
			return window[ attrs.handler ]( ctl, ctl.gtext() );
		}
		else if( attrs.type != null )
		{
			switch( attrs.type )
			{
				case 'zip':
					attrs.match = '^\\d{5}$';
					attrs.matchdescription = 'five digits';
				break;
			}
		}
		if( attrs.match != null && !ctl.gtext().match( attrs.match ) )
		{
			return errstart + 'doesn\'t match the pattern \'' + ( attrs.matchdescription != null ? attrs.matchdescription : attrs.match ) + '\'!';
		}
		return true;
	};

	this.validateCreditCard = function( ccNum, ccType )
	{
		var errMsgs = {
			  length : 'Incorrect card number length!'
			, prefix : 'Incorrect card number prefix!'
			, notsupported : 'Card type is not supported!'
			, mod10 : 'MOD 10 card number check failed!'
		};
		ccType = ccType.toLowerCase();
		// length & prefix check
		switch( ccType )
		{
			case 'visa':
			case 'delta':
				if( ccNum.length != 13 && ccNum.length != 16 )
				{
					return errMsgs.length;
				}
				if( ccNum.substr( 0, 1 ) != '4' )
				{
					return errMsgs.prefix;
				}
			break;

			case 'mastercard':
				if( ccNum.length != 16 )
				{
					return errMsgs.length;
				}
				if( ccNum.substr( 0, 2 ) != '51' && ccNum.substr( 0, 2 ) != '52' && ccNum.substr( 0, 2 ) != '53' && ccNum.substr( 0, 2 ) != '54' && ccNum.substr( 0, 2 ) != '55' )
				{
					return errMsgs.prefix;
				}
			break;

			case 'discover':
			case 'novus':
				if( ccNum.length != 16 )
				{
					return errMsgs.length;
				}
				if( ccNum.substr( 0, 5 ) != '60110' && ccNum.substr( 0, 5 ) != '60112' && ccNum.substr( 0, 5 ) != '60113' && ccNum.substr( 0, 5 ) != '60114' && ccNum.substr( 0, 5 ) != '60119' )
				{
					return errMsgs.prefix;
				}
			break;
			
			case 'amex':
			case 'american express':
			case 'optima':
				if( ccNum.length != 15 )
				{
					return errMsgs.length;
				}
				if( ccNum.substr( 0, 2 ) != '34' && ccNum.substr( 0, 2 ) != '37'  )
				{
					return errMsgs.prefix;
				}
			break;

			default:
				return errMsgs.notsupported;
		}
		// mod 10 check
		var weight = 2;
		var sum = 0;
		for( var i = ccNum.length - 2; i >=0; i-- )
		{
			var digit = parseInt( ccNum.substr( i, 1 ), 10 ) * weight;
			sum += digit % 10 + Math.floor( digit / 10 );
			weight ^= 3; // toggle 2 -> 1 and 1 -> 2
		}
		if( 10 - sum % 10 != parseInt( ccNum.substr( ccNum.length - 1 ) ) )
		{
			return errMsgs.mod10;
		}
		return true;
	};

};
