// ========================================================================
// FlowBuilder Javascript validation functions
// Needs a browser that accepts regular expressions (IE4 and Netscape4)
// ========================================================================

// JS regular expressions     
// var keyword here crashes Netscape4!
_xsp_reInteger = /^[ ]*[+-]?\d+[ ]*$/;
//_xsp_reDecimal = /^[ ]*[+-]?\d*\.?\d*([eE][+-]?\d+)?[ ]*$/;

// String utilities
function xspTrim(s) {
	if( s!=null ) {
    	while( s.length>0 && s.charAt(0)==' ' ) {
        	s = s.substring(1);
    	}
    	while( s.length>0 && s.charAt(s.length-1)==' ' ) {
        	s = s.substring(0,s.length-1);
    	}
	}
    return s;
}


// Check whether string s is empty.
function xspIsEmpty(s) {
    return ((s == null) || (s.length == 0))
}

// Returns true if string s is an integer
function xspIsInteger(s) {
    return _xsp_reInteger.test(s)
}

// Returns true if string s is an decimal number
function xspIsDecimal(s,decSep,thoSep) {
    // . is always permitted as decimal sep
    var tolerance = "";
    if (decSep!='.') {
        tolerance = "|\\.";
    }    
    // white space is represented by \s in reg expr. 
    if (thoSep==' ') {
        thoSep='s';
    } 
    _xsp_reDecimal = new RegExp("^[ ]*[+-]?[\\d|\\" + thoSep + "]*[\\"+ decSep + tolerance + "]?\\d*([eE][+-]?\\d+)?[ ]*$" );
    return _xsp_reDecimal.test(s)
}

// Returns true if string s is a boolean
function xspIsBoolean(s,vTrue,vFalse) {
    return s==vTrue || s==vFalse;
}

// Returns true if string s is a date according to the java format
function xspIsDateTime(dt,javafmt) {
    dt = dt.toLowerCase();

    // Transform the format from Java specification to 'YMDHNS' simple spec
    if( javafmt==null || javafmt.length==0 ) {
        return false;
    }
    var fmt = "";
    
    // special case for MMMM or MMM
    var i1 = javafmt.indexOf("MMMM");
    if (i1!=-1) {
        javafmt = javafmt.substring(0, i1) + "J" + javafmt.substring(i1+4);
    } else {
        var i2 = javafmt.indexOf("MMM");
        if (i2!=-1) {
            javafmt = javafmt.substring(0, i2) + "j" + javafmt.substring(i1+3);
        }
    }
    
    var hasDate=false; hasTime=false;
    lastch='';
    for( var i=0; i<javafmt.length; i++ ){
        ch=javafmt.charAt(i);
        if( ch!=lastch ) {
            switch(ch) {
                case 'y':           fmt += 'Y'; hasDate=true; break;
                case 'M':           fmt += 'M'; hasDate=true; break;
                case 'J':           fmt += 'J'; hasDate=true; break;
                case 'j':           fmt += 'j'; hasDate=true; break;
                case 'd':           fmt += 'D'; hasDate=true; break;
                case 'h': case 'H': fmt += 'H'; hasTime=true; break;
                case 'm':           fmt += 'N'; hasTime=true; break;
                case 's':           fmt += 'S'; hasTime=true; break;
                case 'z':           fmt += 'Z'; break;
                case '/':
                case '.':
                case '-':           fmt += '/'; break;
                case ':':           fmt += ':'; break;
            }
        }
        lastch=ch;
    }

    // Parse the date content
    var year=-1, month=-1, day=-1, hour=-1, minute=-1, second=-1, ampm=-1;
    var pos = 0;
	var nbCharForYear = 0;
    
    // if short name of month ends with a '.' : should be ignored
    var point = dt.indexOf('.');
    if (point!=-1 && (dt.charAt(point-1)>='a' && dt.charAt(point-1)<='z')) {
        dt = dt.substring(0, point) + dt.substring(point+1);
    }
        
    for( var fmtpos=0; pos<dt.length; ) {
        var nbChar = 0;
		c = dt.charAt(pos++);
		nbChar++;
		
        if( c>='0' && c<='9' ) {
            num = c-'0';
            while( pos<dt.length ) {
                c = dt.charAt(pos);
                if( c>='0' && c<='9' ) {
                    num = num*10 + (c-'0');
                    pos++;
					nbChar++;
                } else {
                    break;
                }
            }
            if( fmtpos<fmt.length ) {
                switch( fmt.charAt(fmtpos) ) {
                    case 'Y':   year   = num; nbCharForYear=nbChar; break;
                    case 'M':   month  = num; break;
                    case 'J':   month  = num; break;
                    case 'j':   month  = num; break;
                    case 'D':   day    = num; break;
                    case 'H':   hour   = num; break;
                    case 'N':   minute = num; break;
                    case 'S':   second = num; break;
                }
                fmtpos++;
            } else {
                return false;
            }
        } else if( xspIsLetter(c) ) {
            ss = c;
            while( pos<dt.length ) {
                c = dt.charAt(pos);
                if( xspIsLetter(c) )  {
                    ss+=c; pos++;
                } else {
                    break;
                }
            }
            if( ss=="am" ) {
                if( ampm>0 ) return false;
                ampm=1;
            } else if( ss=="pm" ) {
                if( ampm>0 ) return false;
                ampm=2;
            } else if( fmtpos<fmt.length && (fmt.charAt(fmtpos)=='J' || fmt.charAt(fmtpos)=='j') ) {
                month = 1; // no interpretation of the month name here : we consider it is correct (january for example) 
                fmtpos++;
            } else if( fmtpos<fmt.length && fmt.charAt(fmtpos)=='Z') {
                fmtpos++;
            } else if( ! mayContainLetter(javafmt) ) {
                return false; 
            } else {
                return true; // in other cases (with letters, example "at" "GMT"), consider ok  
            }
        } else if( c=='/' || c=='.' || c=='-' ) {
            if( fmtpos>=fmt.length || fmt.charAt(fmtpos)!='/' ) {
                return false;
            }
            fmtpos++;
        } else if( c==':' ) {
            if( fmtpos>=fmt.length || fmt.charAt(fmtpos)!=':' ) {
                return false;
            }
            fmtpos++;
        } else if( c==' ' || c==',') {
            // Ignore
        } else {
            return false; // Error!
        }
    }

    // Check the date part
    if( hasDate ) {
        if (nbCharForYear<=2) {
            if( year>=0 && year<=39 ) {
            	year += 2000;
        	} else if( year>39 && year<=99 ) {
            	year += 1900;
        	}
        }
		
        if((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
            maxDay = 30;
        } else if(month == 2) {
            maxDay = (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
        } else {
            maxDay = 31;
        }
        if(    ( fmt.indexOf('D')!=-1 && (day<1 || day>maxDay))
            || ( fmt.indexOf('M')!=-1 && (month<1 || month>12))
            || ( fmt.indexOf('Y')!=-1 && year<=0) ) {
            return false;
        }
    }

    // Check the time part
    if( hasTime ) {
        // Warning about US conventions for hours !!!
        if (ampm==1 && hour==12) {
            hour = 0; // 00:00 (midnight) is coded by 12:00 AM
        } else if (ampm==2 && hour!=12) {
            // no change if hour is 12, because 12:00 (noon) is coded by 12:00 PM
            hour +=12;
        } else if (ampm==-1 && hour==24) {
            hour = 0;
        }
        
       
        if( second==-1 ) second=0;
        if(    ( fmt.indexOf('H')!=-1 && (hour<0 || hour>23) )
            || ( fmt.indexOf('N')!=-1 && (minute<0 || minute>59) )
            || ( fmt.indexOf('S')!=-1 && (second<0 || second>59) )) {
            return false;
        }
    }

    // Valid!
    return true;
}

function xspIsLetter(c) {
    if (c>='a' && c<='z') {
        return true;
    }
    if (c>='A' && c<='Z') {
        return true;
    }
    if (c=='\u00E0' || c=='\u00E2' || c=='\u00E4' || 
        c=='\u00E8' || c=='\u00E9' || c=='\u00EA' ||
        c=='\u00EF' || 
        c=='\u00F4' || c=='\u00F6' ||
        c=='\u00F9' || c=='\u00FB' || c=='\u00FC') {
        // à ä â é è ê ï ô ö ü û ù
        return true;
    }
    return false;
}

// Returns true if a date may contain letters with the given pattern
function mayContainLetter(javafmt) {
    for( var i=0; i<javafmt.length; i++) {
        c = javafmt.charAt(i);
        if ( xspIsLetter(c) && c!='y' && c!='M' && c!='d' && c!='H' && c!='h' && c!='m' && c!='s') {
            return true;
        } 
    }
    return false;
}


// ========================================================================
// Final validation functions
// ========================================================================

function xspCheckEmpty(element,req,reqmsg) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }
    return true;
}

function xspCheckSelect(element,req,reqmsg) {
    var hasValue = false;
    var len = element.options.length;
    for( var i=0; i<len; i++ ) {
        var v = element.options[i].value;
        if( v!=null && v!="" ) {
            hasValue = true; break;
        }
    }                      
    var val = "";
    if( element.selectedIndex>=0 ) {
        var opt = element.options[element.selectedIndex];
        val = hasValue ? opt.value : opt.text;
    }
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Selection cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }
    return true;
}

function xspCheckInteger(element,req,reqmsg,min,max,msg) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }

    if( xspIsInteger(val) ) {
        intVal = parseInt(val);
        if( min!=null && max!=null ) {
            if( intVal<min || intVal>max ) {
                alert( msg!=null ? msg : ("The input should be an integer number between "+min+" and "+max) );
                element.focus();
                return false;
            }
            return true;
        }
        if( min!=null ) {
            if( intVal<min ) {
                alert( msg!=null ? msg : ("The input should be an integer number greater than or equal to "+min) );
                element.focus();
                return false;
            }
            return true;
        }
        if( max!=null ) {
            if( intVal>max ) {
                alert( msg!=null ? msg : ("The input should be an integer number less than or equal to "+max) );
                element.focus();
                return false;
            }
            return true;
        }
        return true;
    } else {
        alert( (msg!=null) ? msg : "The input should be an integer number" );
        element.focus();
        return false;
    }
}

function xspCheckDecimal(element,req,reqmsg,min,max,msg,decSep,thoSep) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }

    if( xspIsDecimal(val,decSep,thoSep) ) {
        fltVal = parseFloat(val);
        if( min!=null && max!=null ) {
            if( fltVal<min || fltVal>max ) {
                alert( msg!=null ? msg : ("The input should be a number between "+min+" and "+max) );
                element.focus();
                return false;
            }
            return true;
        }
        if( min!=null ) {
            if( fltVal<min ) {
                alert( msg!=null ? msg : ("The input should be a number greater than or equal to "+min) );
                element.focus();
                return false;
            }
            return true;
        }
        if( max!=null ) {
            if( fltVal>max ) {
                alert( msg!=null ? msg : ("The input should be a number less than or equal to "+max) );
                element.focus();
                return false;
            }
            return true;
        }
        return true;
    } else {
        alert( msg!=null ? msg : "The input should be a number" );
        element.focus();
        return false;
    }
    return false;
}

function xspCheckString(element,req,reqmsg,regexp,msg) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }

    if( regexp!=null ) {
        if( !regexp.test(val) ) {
            alert( msg!=null ? msg : ("Invalid value") );
            element.focus();
            return false;
        }
        return true;
    }
    return true;
}

function xspCheckBoolean(element,req,reqmsg,tValue,fValue,msg) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }

    if( !xspIsBoolean(val,tValue,fValue) ) {
        alert( msg!=null ? msg : ("The input should be "+tValue+" or "+fValue) );
        element.focus();
        return false;
    }
    return true;
}

function xspCheckDateTime(element,req,reqmsg,javafmt,msg) {
    var val = xspTrim(element.value);
    if( val==null || val=="" ) {
        if( req ) {
            alert( reqmsg!=null ? reqmsg : ("Field cannot be empty") );
            element.focus();
            return false;
        }
        return true;
    }

    if( !xspIsDateTime(val,javafmt) ) {
        alert( msg!=null ? msg : ("Invalid date "+val) );
        element.focus();
        return false;
    }
    return true;
}
