/* -*- C -*- */

/* --------------------------------------------------------------------
 * Shine: The Become Interactive Client Application Framework
 * @(#) $Id$
 * --------------------------------------------------------------------
 * Copyright (c) 2006 Become Interactive
 * http://www.becomeinteractive.co.uk
 * All rights reserved.
 * --------------------------------------------------------------------
 * This software is the confidential and proprietary information of
 * Become Interactive ("Confidential Information").
 *
 * You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you
 * with the terms of the license agreement you entered into with
 * Become Interactive.
 * --------------------------------------------------------------------
 */

/**
 * com.uk.become.shine.Validators
 *
 * Client-side form validation
 */
com.uk.become.shine.Validators = function()
{
}
com.uk.become.shine.Validators.prototype.validPassword = function(str)
{
	if(str.length <= 3)
	{
		return false;
	}
	return true;
}
com.uk.become.shine.Validators.prototype.validEmail = function(str)
{
	var ap;
	
	ap = str.indexOf('@');
	dp = str.lastIndexOf('.');
	if(ap != -1 && dp != -1 && dp > ap && dp < str.length - 2)
		{
			return true;
		}
	return false;	
}
com.uk.become.shine.Validators.prototype.validName = function(str)
{
	if(str.length > 1 && str.match(/^[^\s\d@:"$_#^&*()|]{2,}$/)) /* " */
	{
		return true;
	}
	return false;
}
/* Length-based validator */
com.uk.become.shine.Validators.prototype.lengthValidator = function(Shine, sender, event, data)
{
	if(event.value.length < data)
		{
			return false;
		}
	return true;
}
/* Name validator */
com.uk.become.shine.Validators.prototype.nameValidator = function(Shine, sender, event, data)
{
	return this.validName(sender.value);
}
/* Simple e-mail address validator */
com.uk.become.shine.Validators.prototype.emailInputValidator = function(Shine, sender, event, data)
{
	if(sender.shineValidatorPair)
	{
		Shine._inputHandler(Shine, sender.shineValidatorPair, event);
	}
	return this.validEmail(event.value);
}
com.uk.become.shine.Validators.prototype._emailCheckLoad = function(Shine, sender, event, data)
{
	if(!data || data._shineValidateRequest != sender)
	{
		return false;
	}
	if(event.responseText == 'nomatch')
	{
		data.shineValidatedOK = true;
	}
	else
	{
		data.shineValidatedOK = false;
		Shine.debug('Validators:', 'E-mail address already exists');
	}
	data.shineValidateInProgress = false;
	data.shineValidatedData = data._shineValidateValue;
	event.value = data._shineValidateValue;
	Shine.validateField(data, event);
}
/* Checking e-mail address validator */
com.uk.become.shine.Validators.prototype.emailCheckValidator = function(Shine, sender, event, data)
{
	var req;
	
	if(sender.shineValidatorPair)
	{
		Shine.validateField(sender.shineValidatorPair, event);
	}
	if(!this.validEmail(event.value))
	{
		sender.shineValidateInProgress = false;
		sender._shineValidateRequest = false;
		return false;
	}
	if(sender.shineValidateInProgress && sender._shineValidateValue == event.value) return false;
	if(!sender.shineValidatedInProgress)
	{
		if(sender.shineValidatedData == event.value)
		{
			if(sender.shineValidatedOK)
			{
				return true;
			}
			return false;
		}
	}
	sender._shineValidateValue = event.value;
	sender.shineValidateInProgress = true;
	req = Shine.createRequest('GET', Shine.rootPath + 'com.uk.become.login.component/emailcheck/?e=' + encodeURIComponent(event.value));
	Shine.addEventHandler(req, 'load', { host: this, handler: this._emailCheckLoad, data: sender })
	sender._shineValidateRequest = req;
	req.open();
	return false;
}
/* E-mail address confirmation */
com.uk.become.shine.Validators.prototype.emailConfirmInputValidator = function(Shine, sender, event, data)
{
	if(!this.validEmail(event.value))
	{
		return false;
	}
	if(!sender.shineValidatorPair && sender.form)
	{
		/* Look for a companion password field and pair with it */
		nodes = Shine.getElementsByClass(sender.form, 'input', 'shine-input-emailcheck');
		if(!nodes.length)
		{
			nodes = Shine.getElementsByClass(sender.form, 'input', 'shine-input-email');
		}
		for(c = 0; c < nodes.length; c++)
		{
			node = nodes[c];
			if(node == sender) continue;
			if(!node.shineValidatorPair)
			{
				node.shineValidatorPair = sender;
				sender.shineValidatorPair = node;
				data = node;
				break;
			}
		}
	}
	if(!sender.shineValidatorPair) return false;
	if(event.value == sender.shineValidatorPair.value)
	{
		return true;
	}
	return false;
}
/* Simple password validator */
com.uk.become.shine.Validators.prototype.passwordInputValidator = function(Shine, sender, event, data)
{
	if(sender.shineValidatorPair)
	{
		Shine.validateField(sender.shineValidatorPair, event);
	}
	return this.validPassword(event.value);
}
/* Simple password confirmation validator (simply compares the value with the first password field) */
com.uk.become.shine.Validators.prototype.passwordConfirmInputValidator = function(Shine, sender, event, data)
{
	var c, nodes, node;
	
	if(!this.validPassword(event.value))
	{
		return false;
	}
	if(!sender.shineValidatorPair && sender.form)
	{
		/* Look for a companion password field and pair with it */
		nodes = Shine.getElementsByClass(sender.form, 'input', 'shine-input-password');
		for(c = 0; c < nodes.length; c++)
		{
			node = nodes[c];
			if(node == sender) continue;
			if(!node.shineValidatorPair)
			{
				node.shineValidatorPair = sender;
				sender.shineValidatorPair = node;
				data = node;
				break;
			}
		}
	}
	if(!sender.shineValidatorPair) return false;
	if(event.value == sender.shineValidatorPair.value)
	{
		return true;
	}
	return false;
}
/* Integer input validator */
com.uk.become.shine.Validators.prototype.integerInputValidator = function(Shine, sender, event, data)
{
	if(event.value.length)
		{
			if(event.value.match(/^[0-9]+$/))
				{					
					return true;
				}
		}
	return false;
}
/* ISO7812 (credit card, smart card, ID card) input validator */
com.uk.become.shine.Validators.prototype.iso7812InputValidator = function(Shine, sender, event, data)
{
	var ccnum, sum, i, digit;
	
	if(event.value.length)
		{
			/* Strip spaces from the number */
			ccnum = event.value.replace(/\s/g, '');
			if(ccnum.length < 9 || !ccnum.match(/^[0-9]+$/))
			{
				return false;
			}
			/* Calculate the Luhn check digit */
			sum = 0;
			parity = ccnum.length % 2;
			for(i = 0; i < ccnum.length; i++) 
			{
			    digit = ccnum.charAt(i);
			    if(i % 2 == parity)
			 	{
					digit *= 2;
				}
				if(digit > 9)
				{
					digit -= 9;
				}
			    sum += parseInt(digit);
			  }
			  return (sum % 10 == 0);
		}
	return false;
}
com.uk.become.shine.Validators.prototype.cv2InputValidator = function(Shine, sender, event, data)
{
	var ccnum, sum, i, digit;
	
	if(event.value.length == 3)
	{
		return event.value.match(/^[0-9]+$/) ? true : false;
	}
	return false;
}
com.uk.become.shine.Validators.prototype.issueInputValidator = function(Shine, sender, event, data)
{
	var ccnum, sum, i, digit;
	
	if(event.value.length == 2)
	{
		return event.value.match(/^[0-9]+$/) ? true : false;
	}
	return false;
}
/* Floating-point input validator */
com.uk.become.shine.Validators.prototype.floatInputValidator = function(Shine, sender, event, data)
{
	if(event.value.length)
		{
			if(event.value.match(/^[0-9]*(\.[0-9]+)?$/))
				{
					return true;
				}
		}
	return false;
}
com.uk.become.shine.Validators.prototype.ondocumentloaded = function(Shine, sender, ev, data)
{
	var nodes, c;

	if(Shine.hasElementClass(Shine.body, 'shine-no-validation'))
		{
			return true;
		}
	nodes = document.getElementsByTagName('input');
	for(c = 0; c < nodes.length; c++)
		{
			if(Shine.hasElementClass(nodes[c], 'shine-input-email'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.emailInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-emailcheck'))			
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.emailInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-emailconfirm'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.emailConfirmInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-simple'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.lengthValidator, data: 1 });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-md5'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.lengthValidator, data: 32 });
				}			
			else if(Shine.hasElementClass(nodes[c], 'shine-input-name'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.nameValidator });
				}			
			else if(Shine.hasElementClass(nodes[c], 'shine-input-password'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.passwordInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-passconfirm'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.passwordConfirmInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-integer'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.integerInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-float'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.floatInputValidator });
				}
			else if(Shine.hasElementClass(nodes[c], 'shine-input-iso7812'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.iso7812InputValidator });
				}			
			else if(Shine.hasElementClass(nodes[c], 'shine-input-cv2'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.cv2InputValidator });
				}			
			else if(Shine.hasElementClass(nodes[c], 'shine-input-issue'))
				{
					Shine.addInputHandler(nodes[c], { host: this, handler: this.issueInputValidator });
				}
		}
	/* Add handlers for the various classes of Shine-enabled form fields */
	nodes = Shine.getElementsByClass(document, 'select', 'shine-input-simple');
	Shine.addInputHandlers(nodes, { host: this, handler: this.lengthValidator, data: 1 });
	nodes = Shine.getElementsByClass(document, 'textarea', 'shine-input-simple');
	Shine.addInputHandlers(nodes, { host: this, handler: this.lengthValidator, data: 1 });
}
var ShineValidators = new com.uk.become.shine.Validators();

Shine.addLoadHandler(ShineValidators);

