(function(jQuery){

    /**
     *Add a timestamp to the value of meta_filename
     */
    jQuery.fn.metaAddCurrentDate = function()
    {
        var item = jQuery( this );
        var oldval = item.val( );
        jQuery.get('http://www.upc.nl/media/2009/6/5/datetime.php', function(data){
            var newval = oldval + data;
            item.val( newval );
        });
    };

    /**
     * jQuery extension
     */
    jQuery.fn.parseUrl = function( options )
    {
      if( typeof options != 'object' ){
         return;
      }

      var myUrl = document.location.href;

      var arrParts = myUrl.split( '?' );

      if( arrParts.length == 2 && arrParts[1] != '' ){
        var myVariables = arrParts[1].split( '&' );
        for( var i in myVariables ){
          var myParameter = myVariables[i].split( '=' );
          if( ArrayKeyExists( myParameter[0], options ) == true ){
            var elems = jQuery( '.' + options[myParameter[0]] );
            var el;
            if( elems.length == 1 ) {
              el = elems[elems.length - 1];
              Preselect( el, myParameter[1], elems );
            } else {
              for( var j = 0; j < elems.length; j++ ) {
                el = elems[j];
                Preselect( el, myParameter[1], elems );
              }
            }
          }
        }
      }
    };

    /**
     * Function for prefilling and preselecting form options
     */
    Preselect = function( el, content, elems )
    { 
        if( el.tagName == 'INPUT' ){
            //setting input options.
            var attrType = el.getAttribute( 'type' );
            if( attrType == 'text' || attrType == 'hidden' ){
                //text option
                el.value = unescape( content.split('+').join(' ') );
            } else if( attrType == 'radio' ){
                //radio button trick
                for( var x=0; x <elems.length; x++ ){
                    if( elems[x].value == unescape( content ) ){
                        elems[x].checked = true;
                        break;
                    }
                }
            } else if( attrType == 'checkbox' ){
                //checkbox trick
                for( var x=0; x<elems.length; x++ ){
                    if( elems[x].value == unescape( content ) ){
                        elems[x].checked =  true;
                    }
                }
            }
        } else if( el.tagName == 'SELECT' ){
            //setting the value of on select object
            el.value = unescape( content );
        } else if( el.tagName == 'TEXTAREA' ){
            //setting textarea
            el.value = unescape( content );
        }else if( el.tagName == 'DIV' || el.tagName == 'SPAN' ){
            //setting textarea
            el.innerHTML = unescape( content.split('+').join(' ') );
        }
    };

    /**
     * Show and the tool-tip components
     */
    jQuery.fn.formToolTip = function()
    {
      return this.each(function() {

        var link = jQuery(this);
		var rel = link.attr( 'rel' );
        /*
         * Add corners and arrow to each tooltip
         */
        var divs = '<div class="arrow"><!-- --></div><div class="tr"><!-- --></div><div class="tl"><!-- --></div><div class="bl"><!-- --></div><div class="br"><!-- --></div>';
        jQuery( '#info_' + rel ).append( divs );
		//jQuery( '#info_' + link.attr( 'rel' ) ).after( divs );

        /*
         * Bind the mouseover / mouseout
         */
        link.mouseover( function( ){
            jQuery( '#info_' + rel ).css( "left", ( ( parseInt( this.offsetLeft ) + 28 ) + "px" ) );
            jQuery( '#info_' + rel ).show();
        }).mouseout(function(){
           jQuery( '#info_' + rel ).hide();
        });
      });
    };

    /**
     * Empty a form field on click, if the initial value has not changed, put it back on blur
     */
    jQuery.fn.emptyOnClick = function()
    {
      return this.each(function() {

        var input = jQuery(this);

        var value = input.val();

        input.bind("focus", function( e ) {
          if( value == input.val() )
            input.val('');
        });

        input.bind("blur", function( e ) {
          if( input.val() == '' )
            input.val( value );
        });

        input.parents('form').bind("submit", function( e ) {
          if( input.val() == value )
            input.val('');
        });
        
      });
    }

    //holder for total error objects
    var errorMsg = [];

    //object holder for the messages corresponding to the fields
    var customMessages = {};

    /**
     * Extend jQuery with the validate function. Function has two parameters.
     * The first is an object, containing the fields which has to be validated.
     *  e.g { email: ['verplicht', 'email' ] }
     *
     * The second is an object, containing the custom error messages.
     *  e.g. { email: 'Choose an valid email address' }
     */
    jQuery.fn.validate = function(options, messages, callback){

        //only set the custom messages if an object is provided
        if( typeof messages == 'object' ){
            customMessages = messages;
        }

        var formid = this.attr('id');

        //bind click event on the submit button, which always have to have an id submit
        jQuery( '#submit' ).click(function(){

            // remove the error classes
            jQuery('.form_error').removeClass('form_error');

            //empty existing errors
            errorMsg = [];

            //loop the named items to be checked.
            for( var i in options ){
                Validate(i, options[i]);
            }
            
            //if there are errorMsg, don't send, show errors, else submit the form
            if( errorMsg.length > 0 ){
                ShowErrors();
            } else { 
                // if there is a callback specified, do it (callback should do the submit)
                if (typeof callback != "undefined" && typeof callback == "function") {
                  jQuery( '#errors' ).fadeOut(); // remove the errors
                  callback( formid );
                } else {
                  jQuery('#' + formid ).submit();
                }                
                return false;
            }

            return false;
        });
    };

    /**
     * Validate function. Function has two paramters. The first is object key/html item
     * to be checked. The second is the check which has to be performed
     * Based on the checked an other function is called
     */
    Validate = function( item, validations )
    {
        for( var x in validations ){
            switch( validations[x] ){
                case 'verplicht':
                    Required( item );
                    break;
                case 'naam':
                    Lastname( item );
                    break;
                case 'initialen':
                    Initials( item );
                    break;
                case 'tussenvoegsel':
                    Surname( item );
                    break;
                case 'postcode':
                    PostalCode( item );
                    break;
                case 'email':
                    Email( item );
                    break;
                case 'telefoonnummer':
                    PhoneNumber( item );
                    break;
                case 'numeriek':
                    Numeric( item );
                    break;
                case 'alfanumeriek':
                    AlphaNumeric( item );
                    break;
                case 'extalfanumeriek':
                    ExtendedAlphaNumeric( item );
                    break;
                case 'datum':
                    DateCheck( item );
                    break;
                case 'leeftijd':
                    AgeCheck( item );
                    break;
                default:
                    //regular expression for min[3] max[7] check
                    // ugly fix because UPC overwrites standard javascript functionality, blegh !
                    var regexp = /^((min|max)\[(\d)*\])$/;
                    var myCallback = regexp.test( validations[x] );

                    if( myCallback == true ) {

                      var minRegexp = /^((min|min)\[(\d)*\])$/;
                      var maxRegexp = /^((max|max)\[(\d)*\])$/;
                      var valString = validations[x].replace(']','');

                      if( minRegexp.test( validations[x] ) ) {
                        valString = valString.replace('min[','');
                        MinChars( item, valString );
                      } else if( maxRegexp.test( validations[x] ) ) {
                        valString = valString.replace('max[','');
                        MaxChars( item, valString );
                      }

                    }

                    if( myCallback != null ){
                        if( myCallback[2] == 'min' ){
                            MinChars( item, myCallback[3] );
                        }else if( myCallback[2] == 'max' ){
                            MaxChars( item, myCallback[3] );
                        }
                    }
                    break;
            }
        }
    };

    /**
     * Perform check to make sure the field is not empty
     * check is a bit different for different elements
     */
    Required = function( item )
    {
        var myItem = jQuery( '.' + item );

        //if we got an array, we will asume an array of radio or checkbox elements
        if( myItem.length > 1 ){
            //don't to the first, can me hidden, for setting a checkbox value
            var e = myItem[ myItem.length - 1 ];
            //switch the element type
            switch( e.getAttribute('type') ){
                case 'radio':
                    var blnChecked = false;
                    for( var i=0; i<myItem.length; i++ ){
                        if( myItem[i].checked === true ){
                            blnChecked = true;
                            break;
                        }
                    }
                    if( blnChecked === false ){
                        errorMsg[errorMsg.length] = item;
                    }
                    break;
                case 'checkbox':
                    var blnChecked = false;
                    for( var i=0; i<myItem.length; i++ ){
                        if( myItem[i].checked === true ){
                            blnChecked = true;
                            break;
                        }
                    }
                    if( blnChecked === false ){
                        errorMsg[errorMsg.length] = item;
                    }
                    break;
            }
        } else {
            //no array, so the element can be input[text], select, textarea
            switch( myItem.attr( 'type' ) ){
                case 'radio':
                    var blnChecked = false;
                    for( var i=0; i<myItem.length; i++ ){
                        if( myItem[i].checked === true ){
                            blnChecked = true;
                            break;
                        }
                    }
                    if( blnChecked === false ){
                        errorMsg[errorMsg.length] = item;
                    }
                    break;
                case 'text':
                    if( myItem.val() == '' ){
                        errorMsg[errorMsg.length] = item;
                    }
                    break;
                default:
                    //this check we will use to check the select and textarea elements, the
                    //other elements are already catched
                    if( myItem.val() == '' ){
                        errorMsg[errorMsg.length] = item;
                    }
                    break;
            }
        }
    };

    /**
     * Dutch Zip code check
     */
    PostalCode = function( item )
    {
        var myVal = jQuery( '.' + item ).val();

        if( myVal == '' ) {
          return;
        }

        if( myVal != '' ){
            var regexp = /^[1-9][0-9]{3}\x20?[a-zA-Z]{2}$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Email check
     */
    Email = function( item )
    {
        var myVal = jQuery( '.' + item ).val();

        if( myVal != '' ){
            var regexp = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
             }
        }
    };

    /**
     * Check for strict numeric values, no white spaces
     */
    Numeric = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
        if( myVal != '' ){
            var regexp = /^[1-9][0-9]*$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Initial specific check
     * Transform characters to uppercase
     */
    Initials = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
        jQuery( '.' + item ).val( myVal.toUpperCase() );

        if( myVal != '' ){
            var regexp = /^[A-Za-z]([\.][A-Za-z]){0,4}[\.]?$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Surname specific check
     * Transforms characters to lowercase
     */
    Surname = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
        jQuery( '.' + item ).val( myVal.toLowerCase() );
        if( myVal != '' ){
            var regexp = /^([A-Za-z\'])+(\s?[A-Za-z\']+)*$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Specific check for lastname.
     * Transforms first character to uppercase
     */
    Lastname = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
        jQuery( '.' + item ).val( myVal.slice(0,1).toUpperCase() + myVal.slice(1) );
        if( myVal != '' ){
            var regexp = /^([A-Za-z\'])+(\s?\-?[A-Za-z\']+)*$/
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Check for strict alphanumeric values, no white spaces
     */
    AlphaNumeric = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
        if( myVal != '' ){
            var regexp = /^[0-9a-zA-Z]+$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * check for extended alphanumeric sequences. No white spaces, but except
     * numbers, characters, also . - _
     */
    ExtendedAlphaNumeric = function( item ){
        var myVal = jQuery( '.' + item ).val();
        if( myVal != '' ){
            var regexp = /^[0-9a-zA-Z.\-_\'\s]*$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Check for dutch telephone numbers
     */
    PhoneNumber = function( item ){
        var myVal = jQuery( '.' + item ).val();
        if( myVal != '' ){
            var regexp = /^(\+31|0)[\-]*([0-9][\-]*){9}$/;
            if( !regexp.test( myVal ) ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Check for a valid date input. Also transform / sign to - sign
     */
    DateCheck = function( item ){
        var myVal = jQuery( '.' + item ).val();
        if( myVal == '' ) {
          return;
        }
        myVal = myVal.replace( /\//g, "-" );
        var regexp = /^[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/;
        if( !regexp.test( myVal ) ){
            if( InArray( item, errorMsg ) == -1 ){
                errorMsg[errorMsg.length] = item;
            }
        } else {
            jQuery( '.' + item ).val( myVal );
        }
    };

    /**
     * Perform an age check. age must be minimal 18
     */
    AgeCheck = function( item )
    {
        var myVal = jQuery( '.' + item ).val();
         if( myVal != '' ){
			
            var myDate = new Date();
            var myToday = new Date();

            regexp = /^([0-9]{2})\-([0-9]{2})\-([0-9]{4})$/;
            var myTempValues = myVal.match(regexp);

			if( myTempValues != null ){
				myDate.setFullYear( myTempValues[3], myTempValues[2] -1 , myTempValues[1]  );
				var calcu = myToday - myDate;

				var minutes = calcu / 1000 / 60;
				var hours = minutes / 60;
				var days = hours / 24;
				var years = days / 365;

				if( parseInt( years ) < 18 ){
					errorMsg[errorMsg.length] = item;
				}
			}
        }
    };

    /**
     * Perform a check on the amount of characters
     * Only when the field is not empty
     * Function got two parameters:
     *      class name of the item to be checked
     *      max number of characters
     */
    MaxChars = function( item, characterCount )
    {
        var myVal = jQuery( '.' + item ).val();
        if( myVal != '' ){
            if( myVal.length > characterCount ){
                errorMsg[errorMsg.length] = item;
            }
        }
    };

    /**
     * Perform a check on the amaount of characters
     * Function always perform the check. verplicht option can be omitted
     * Function got two parameters
     *      class name of the item to be checked
     *      min number of characters
     */
    MinChars = function( item, characterCount )
    {
        var myVal = jQuery( '.' + item ).val();
        if( myVal.length < characterCount ){
            errorMsg[errorMsg.length] = item;
        }
    };

    /**
     * Function that builds and shows the errors
     * uses the customMessages object to see if there are some custom messages set
     */
    ShowErrors = function()
    {
        var errorHTML = '';
        for( var i in errorMsg ){
            jQuery('#field_' + errorMsg[i] ).addClass('form_error');
            if( ArrayKeyExists( errorMsg[i], customMessages ) ){
                errorHTML += customMessages[errorMsg[i]] + '<br />';
            }
        }

        jQuery( '#customformerrors' ).html( errorHTML );
        jQuery( '#errors' ).show();
    };

    /**
     * This function is our port of the PHP in_array function
     * Two parameters:
     *      needle: item to be found in the array
     *      array: array in which we have to search
     * return the key index, or -1 if there's nothing found
     */
    InArray = function( needle, array )
    {
        for( var i=0; i<array.length; i++ ){
            if( array[i] == needle ){
                return i;
            }
        }
        return -1;
    };

    /**
     * Function is our port of the PHP array_key_exists function to JS
     * Two parameters
     *      key: key to be found in the object/array
     *      array: array/ object to search in
     * return true if the key is found. Return false otherwise
     */
    ArrayKeyExists = function(key, array)
    {
        for( var i in array ){
            if( key == i ){
                return true;
            }
        }
        return false;
    };

})(jQuery);

