var	unchecked	= 0 ;
var	advisory	= 1 ;
var	enforced	= 2 ;

var	integer		= 0 ;
var	posint		= 1 ;
var	percent		= 2 ;
var	float		= 3 ;
var	posfloat	= 4 ;

var	controlList	= new Array  () ;
var	controlDict	= new Object () ;
var	pyLib		= new Object () ;

function showhint (hint)
{
	var pyHint = document.getElementById('pyHintField') ;
	if (pyHint)
		pyHint.firstChild.data = hint ;
}

function clearhint ()
{
	showhint ('') ;
}

function showError (object, ctrl, submit, error)
{
	if (!submit)
	{
		var pyError = document.getElementById('pyErrorField') ;
		if (error == null) error = '' ;
		if (pyError)
		{	pyError.firstChild.data = error ;
			return	;
		}
		if (error != '') alert (error) ;
	}
}

function clearError ()
{
	var pyError = document.getElementById('pyErrorField') ;
	if (pyError) pyError.firstChild.data = '' ;
}

function checkOK (error)
{
	return	confirm (error + ": is this correct?") ;
}

pyLib.p_integer		= new RegExp ('^ *([+-]|)[0-9][0-9]* *$') ;
pyLib.p_float		= new RegExp ('^ *([+-]|)[0-9][0-9]*(\.[0-9]*|) *$') ;
pyLib.p_posint		= new RegExp ('^ *[0-9][0-9]* *$') ;
pyLib.p_posfloat	= new RegExp ('^ *[0-9][0-9]*(\.[0-9]*|) *$') ;
pyLib.p_percent		= new RegExp ('^ *[0-9][0-9]*(\.[0-9]*|) *$') ;

pyLib.is_integer = function (value, nullok)
{
	return ((value == '') && nullok) || value.match (pyLib.p_integer ) ;
}

pyLib.is_float = function   (value, nullok)
{
	return ((value == '') && nullok) || value.match (pyLib.p_float   ) ;
}

pyLib.is_posint = function  (value, nullok)
{
	return ((value == '') && nullok) || value.match (pyLib.p_posint  ) ;
}

pyLib.is_posfloat = function(value, nullok)
{
	return ((value == '') && nullok) || value.match (pyLib.p_posfloat) ;
}

pyLib.is_percent = function (value, nullok)
{
	return ((value == '') && nullok) || value.match (pyLib.p_percent ) ;
}

pyLib.is_date = function (value, nullok)
{
	return (((value == '') && nullok) || (pyLib.checkDate(value) != null)) ;
}

pyLib.checkDate = function (value, wrap)
{
	var	checkstr 	= "0123456789"	;
	var	DateValue 	= value		;
 	var	DateTemp 	= ""	;
	var	seperator 	= "/"	;
	var	day		;
	var	month		;
	var	year		;
	var	leap		= 0	;
	var	errorCode	= 0	;

	if (!wrap) wrap = 0 ;

	//  Delete all chars except 0..9
	//
	for (var i = 0 ; i < DateValue.length ; i += 1)
		if (checkstr.indexOf(DateValue.substr(i,1)) >= 0)
			DateTemp += DateValue.substr(i,1) ;

	DateValue = DateTemp	;
   
	//  Always change date to 8 digits string. If year is
	//  entered as 2-digit, assume 20xx or 19xx depending on
	//  the year wrap value.
	//
	if (DateValue.length == 6)
	{
		year = DateValue.substr(4,2) ;
		if (year < wrap)
			DateValue = DateValue.substr(0,4) + '20' + DateValue.substr(4,2) ;
		else	DateValue = DateValue.substr(0,4) + '19' + DateValue.substr(4,2) ;
	}

	if (DateValue.length != 8) errorCode = 19 ; 

	year  = DateValue.substr(4,4) ;
	month = DateValue.substr(2,2) ;
	day   = DateValue.substr(0,2) ;

	if (year == 0		       ) errorCode = 20 ;
   	if ((month < 1) || (month > 12)) errorCode = 21 ; 
   	if (day  < 1		       ) errorCode = 22 ;
   
	if	(year % 400 == 0) leap = true	;
	else if	(year % 100 == 0) leap = true	;
	else if (year %   4 == 0) leap = true	;
	else			  leap = false	;
   
	if ((month == 2) &&  leap && (day > 29)) errorCode = 23 ;
	if ((month == 2) && !leap && (day > 28)) errorCode = 24 ;
   
	if ((day > 31) && ((month == "01") || (month == "03") || (month == "05") || (month == "07") || (month == "08") || (month == "10") || (month == "12"))) errorCode = 25 ;
	if ((day > 30) && ((month == "04") || (month == "06") || (month == "09") || (month == "11")							    )) errorCode = 26 ;

	if (errorCode == 0)
		return	[ null, day, month, year.substr(2,2), year ] ;

	return	null ;
}

function getError (error, object, text)
{
	return	error == '' ? object.m_legend + ' ' + text : error ;
}

pyLib.setupBase = function (object, name, legend, hint)
{
	object.m_name	= name		;
	object.m_legend	= legend	;
	object.m_hint	= hint		;

	object.showError = function (ctrl, submit, error)
		{
			showError (this, ctrl, submit, error) ;
		}

	object.notNullOpt = function ()
		{
			if (this.m_notnull[2] && !controlDict[this.m_notnull[2]].isSet())
				return	unchecked ;
			return	this.m_notnull[0] ;
		}

	object.isSet = function ()
		{
			return	document.getElementById(this.m_name).value != '' ;
		}

	controlList[controlList.length] = object ;
	controlDict[object.m_name     ] = object ;
}

pyLib.setupInput = function (object, name, legend, hint)
{
	pyLib.setupBase (object, name, legend, hint) ;

	object.notnull_force = function (ctrl, submit, prior)
		{
			if (!this.m_notnull[2] || controlDict[this.m_notnull[2]].isSet())
				if ((ctrl.value == '') || (ctrl.value == null))
				{	var error = getError (this.m_notnull[1], this, "must be set") ;
					if (!prior) this.showError (ctrl, submit, error) ;
					return error ;
				}
			if (!prior) clearError () ;
			return	null	;
		}

	object.notnull_allow = function (ctrl, submit, prior)
		{
			if (!submit)
				if ((ctrl.value == '') || (ctrl.value == null))
				{	var error = this.m_legend + " is not set" ;
					if (!checkOK(error)) return error ;
				}
			if (!prior) clearError () ;
			return	null	;
		}

	object.regexp_force = function (ctrl, submit, prior)
		{
		        if (!ctrl.value.match(this.m_regExp[1]))
		        {   var error = getError (this.m_regExp[2], this, "is not valid") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	object.regexp_allow = function (ctrl, submit, prior)
		{
		        if (!ctrl.value.match(this.m_regExp[1]))
		        {   var error = getError (this.m_regExp[2], this, "is not valid") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}
}

pyLib.pyInput = function (name, legend, hint)
{
	pyLib.setupInput (this, name, legend, hint) ;

	this.range_force = function (ctrl, submit, prior)
		{
		        if ((this.m_nullopt == enforced) || (ctrl.value != ''))
		            if ((ctrl.value < this.m_range[1]) || (ctrl.value > this.m_range[2]))
		            {   var error = getError (this.m_range[3], this, "out of range (" + this.m_range[1] + " ... " + this.m_range[2] + ")") ;
		                if (!prior) this.showError (ctrl, submit, error) ;
		                return error ;
		            }
			if (!prior) clearError () ;
			return	null ;
		}

	this.range_allow = function (ctrl, submit, prior)
		{
		        if (!submit)
		            if ((this.m_nullopt == enforced) || (ctrl.value != ''))
		                if ((ctrl.value < this.m_range[1]) || (ctrl.value > this.m_range[2]))
		                {   var error = getError (this.m_range[3], this, "out of range (" + this.m_range[1] + " ... " + this.m_range[2] + ")") ;
		                    if (!checkOK(error)) return error ;
				}
			if (!prior) clearError () ;
			return	null ;
		}

	this.type_integer = function (ctrl, submit, prior)
		{
		        if (!pyLib.is_integer (ctrl.value, this.notNullOpt() != enforced))
		        {   var error = getError (this.m_type[2], this, "is not a whole number") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.type_posint = function (ctrl, submit, prior)
		{
		        if (!pyLib.is_posint  (ctrl.value, this.notNullOpt() != enforced))
		        {
		            var error = getError (this.m_type[2], this, "is not a positive number") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.type_float = function (ctrl, submit, prior)
		{
		        if (!pyLib.is_float (ctrl.value, this.notNullOpt() != enforced))
		        {   var error = getError (this.m_type[2], this, "is not a number") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.type_posfloat = function (ctrl, submit, prior)
		{
		        if (!pyLib.is_posfloat (ctrl.value, this.notNullOpt() != enforced))
		        {   var error = getError (this.m_type[2], this, "is not a positive number") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.type_percent - function (ctrl, submit, prior)
		{
		        if (!pyLib.is_percent (ctrl.value, this.notNullOpt() != enforced))
		        {   var error = getError (this.m_type[2], this, "is not a percentage") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.verify	= function (ctrl, submit, prior)
		{
			var error ;

			if (this.notNullOpt() == advisory)
			    if ((error = this.notnull_allow (ctrl, submit, prior)) != null)
				return error ;

			if (this.notNullOpt() == enforced)
			    if ((error = this.notnull_force (ctrl, submit, prior)) != null)
				return error ;

			if (this.m_type[0] != unchecked)
			{
			    if (this.m_type[1] == integer)
				if ((error = this.type_integer (ctrl, submit, prior)) != null)
					return error ;
				else	return null  ;
			    if (this.m_type[1] == posint)
				if ((error = this.type_posint (ctrl, submit, prior)) != null)
					return error ;
				else	return null  ;
			    if (this.m_type[1] == percent)
				if ((error = this.type_percent (ctrl, submit, prior)) != null)
					return error ;
				else	return null  ;
			    if (this.m_type[1] == float)
				if ((error = this.type_float (ctrl, submit, prior)) != null)
					return error ;
				else	return null  ;
			    if (this.m_type[1] == posfloat)
				if ((error = this.type_posfloat (ctrl, submit, prior)) != null)
					return error ;
				else	return null  ;
			    return null ;
			}


			if (this.m_range[0] == advisory)
			    if ((error = this.range_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_range[0] == enforced)
			    if ((error = this.range_force (ctrl, submit, prior)) != null)
				return error ;

			if (this.m_regExp[0] == advisory)
			    if ((error = this.regexp_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_regExp[0] == enforced)
			    if ((error = this.regexp_force (ctrl, submit, prior)) != null)
				return error ;

			return	null ;
		}

	this.onchange = function (ctrl)
		{
			if (this.f_onchange)
				this.f_onchange (this, ctrl) ;

			return	this.verify (ctrl, 0, null) == null ;
		}

	this.onkeypress = function (ctrl, event)
		{
			if (this.f_onkeypress)
				this.f_onkeypress (this, ctrl, event) ;

			return	true ;
		}
}

pyLib.pyChoice = function (name, legend, hint)
{
	pyLib.setupBase (this, name, legend, hint) ;

	this.notnull_force = function (ctrl, submit, prior)
		{
			if (!this.m_notnull[2] || controlDict[this.m_notnull[2]].isSet())
			        if (ctrl.selectedIndex == 0)
			        {   var error = getError (this.m_notnull[1], this, "must be specified") ;
			            if (!prior) this.showError (ctrl, submit, error) ;
		        	    return error ;
		        	}
			if (!prior) clearError () ;
			return	null ;
		}

	this.notnull_allow = function (ctrl, submit, prior)
		{
		        if (!submit)
		            if (ctrl.selectedIndex == 0)
		            {   var error = getError (this.m_notnull[1], this, "is not specified") ;
		                if (!checkOK(error)) return error ;
			    }
			if (!prior) clearError () ;
			return	null ;
		}

	this.verify	= function (ctrl, submit, prior)
		{
			if (this.m_notnull[0] == advisory)
			    if ((error = this.notnull_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_notnull[0] == enforced)
			    if ((error = this.notnull_force (ctrl, submit, prior)) != null)
				return error ;
		
			return	null ;
		}

	this.onchange = function (ctrl)
		{
			if (this.f_onchange)
				this.f_onchange (this, ctrl) ;

			return	this.verify (ctrl, 0, null) == null ;
		}

	this.isSet = function ()
		{
			return	document.getElementById(this.m_name).selectedIndex > 0 ;
		}
}

pyLib.pyCheck = function (name, legend, hint)
{
	pyLib.setupBase (this, name, legend, hint) ;

	this.notnull_force = function (ctrl, submit, prior)
		{
		        if (!ctrl.checked)
		        {   var error = getError (this.m_notnull[1], this, "must be checked") ;
		            if (!prior) this.showError (ctrl, submit, error) ;
		            return error ;
		        }
			if (!prior) clearError () ;
			return	null ;
		}

	this.notnull_allow = function (ctrl, submit, prior)
		{
		        if (!submit)
		            if (!ctrl.checked)
		            {   var error = getError (this.m_notnull[1], this, "is not checked") ;
		                if (!checkOK(error)) return error ;
			    }
			if (!prior) clearError () ;
			return	null ;
		}

	this.verify	= function (ctrl, submit, prior)
		{
			var error ;

			if (this.m_notnull[0] == advisory)
			    if ((error = this.notnull_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_notnull[0] == enforced)
			    if ((error = this.notnull_force (ctrl, submit, prior)) != null)
				return error ;

			return	null ;
		}

	this.onchange = function (ctrl)
		{
			if (this.f_onchange)
				this.f_onchange (this, ctrl) ;

			return	this.verify (ctrl, 0, null) == null ;
		}

	this.isSet = function ()
		{
			return	document.getElementById(this.m_name).checked ;
		}

}

pyLib.pyTextArea = function (name, legend, hint)
{
	pyLib.setupInput (this, name, legend, hint) ;

	this.verify	= function (ctrl, submit, prior)
		{
			var error ;

			if (this.notNullOpt() == advisory)
			    if ((error = this.notnull_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.notNullOpt() == enforced)
			    if ((error = this.notnull_force (ctrl, submit, prior)) != null)
				return error ;

			if (this.m_regExp[0] == advisory)
			    if ((error = this.regexp_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_regExp[0] == enforced)
			    if ((error = this.regexp_force (ctrl, submit, prior)) != null)
				return error ;

			return	null ;
		}

	this.onchange = function (ctrl)
		{
			if (this.f_onchange)
				this.f_onchange (this, ctrl) ;

			return	this.verify (ctrl, 0, null) == null ;
		}
}

pyLib.pyDate = function (name, legend, hint)
{
	pyLib.setupInput (this, name, legend, hint) ;

	this.type_date = function (ctrl, submit, prior)
		{
		        if (!pyLib.is_date (ctrl.value, true))
		        {
				var error = getError  (this.m_cs[1], this, "is not a date") ;
				if (!prior) this.showError (ctrl, submit, error) ;
				return error ;
		        }

			var res = pyLib.checkDate(ctrl.value, this.m_wrap);  
			if (res != null)
				ctrl.value = res[1] + '/' + res[2] + '/' + res[4] ;

			if (!prior) clearError (ctrl) ;
			return	null ;
		}

	this.verify	= function (ctrl, submit, prior)
		{
			var error ;

			if (this.notNullOpt() == advisory)
			    if ((error = this.notnull_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.notNullOpt() == enforced)
			    if ((error = this.notnull_force (ctrl, submit, prior)) != null)
				return error ;

			if (this.m_regExp[0] == advisory)
			    if ((error = this.regexp_allow (ctrl, submit, prior)) != null)
				return error ;
			if (this.m_regExp[0] == enforced)
			    if ((error = this.regexp_force (ctrl, submit, prior)) != null)
				return error ;

			if (this.m_cs[0] != unchecked)
				if ((error = this.type_date  (ctrl, submit, prior)) != null)
					return error ;

			return	null ;
		}

	this.onchange = function ()
		{
			ctrl = document.getElementById(this.m_name);
			if (this.f_onchange)
				this.f_onchange (this, ctrl) ;

			return	this.verify (ctrl, 0, null) == null ;
		}
}


pyLib.pyStack = function (name)
{
	this.m_name	= name		;
}

pyLib.checkControls = function ()
{
	var elist = new Array() ;

	for (var idx in controlList)
	{
		var ctrl = controlList[idx] ;

		if (ctrl.verify == null)
			continue ;

		var err  = ctrl.verify(document.getElementById([ctrl.m_name]), 1) ;
		if (err == null)
			continue ;

		elist[elist.length] = err ;
	}

	return	elist	;
}

function onSubmit()
{
	var elist = pyLib.checkControls () ;
	if (elist.length > 0)
	{
		alert	('Some fields are not correct:\n     ' + elist.join('\n     ')) ;
		return	false	;
	}
	return	true	;
}

