/**
 * Base Object
 */

var TrueWizard = window.Twd = function()
{
};

/**
 * Constants Definition
 */

TrueWizard.FIELD_TYPE_TEXT     = 0;
TrueWizard.FIELD_TYPE_HIDDEN   = 1;
TrueWizard.FIELD_TYPE_RADIO    = 2;
TrueWizard.FIELD_TYPE_CHECKBOX = 3;
TrueWizard.FIELD_TYPE_SELECT   = 4;
TrueWizard.FIELD_TYPE_CALENDAR = 5;
TrueWizard.FIELD_TYPE_PHONE    = 6;
TrueWizard.FIELD_TYPE_EMAIL    = 7;
TrueWizard.FIELD_TYPE_IP       = 8;
TrueWizard.FIELD_TYPE_TEXTAREA = 9;
TrueWizard.FIELD_TYPE_AGE      = 10;
// CAIVIS(LDS) 3/27/09
TrueWizard.FIELD_TYPE_CUSTOM_START_DATE      	= 11;

if ( typeof Array.prototype.indexOf != 'function' ) {
    /**
     * Extend the Array object if the method is not native indexOf (for Internet Explorer)
     */
    Array.prototype.indexOf = function( item )
    {
        for ( var i = this.length; i >= 0 && item != this[ --i ]; );
        return i;
    };
}

/**
 * Returns a new instance of TrueWizard.Element
 *
 * @param  mixed String or HTMLElement = The element that will be manipulated
 * @return Object TrueWizard.Element
 */
TrueWizard.$ = function( element )
{
    return new TrueWizard.Element( element );
};

/**
 * Create a class that can be instantiated
 *
 * @param  Function Class = the object will return the properties and methods of analysis
 * @return Object Construct
 */
TrueWizard.Class = function( Class )
{
    var Prototype = new Class;

    // contructor of the class, called to initialize the same
    // passing the arguments received when it was instantiated
    // using the newly created instance
    var Construct = function()
    {
        if ( this instanceof Class ) {
            return this.init.apply( this, arguments );
        }
    };

    Construct.prototype = Prototype;

    return Construct;
};


/**
 * Changes the action of the form.
 *
 * @param  String formId = the unique identifier of the form
 * @return Object fields
 *
 * CAIVIS(LDS) 1-14-09
 */

TrueWizard.formAction = function( formId )
{
	var action = '/thank-you-confirmation';
	// Use the querystring in case you need to add it for whatever reason
	var querystring = '';
	var url = action + querystring;
	
  document.getElementById( formId ).action = url;
	return false;
};



/**
 * Submits Form 2 to redirect user to a confirmation page.
 *
 * @param  String formId = the unique identifier of the form
 * @return Object fields
 *
 * CAIVIS(LDS) 1-13-09
 */

TrueWizard.formSubmit = function( formId )
{
  var form   = document.getElementById( formId );
  form.submit();
	return false;
};


TrueWizard.captureUserData = function(close)
{
			
	if (close == true) {
		
		if (document.getElementById("postBailOutPoint").value != FinalFormNumber && document.getElementById("postBailOutPoint").value != 1) {
						
			var FinalFormStep = "form-step" + FinalFormNumber;
	
			// Capture all user data so far
			document.getElementById("postEmail").value = document.getElementById("email").value;
			document.getElementById("postFirstname").value = document.getElementById("firstName").value;
			document.getElementById("postLastname").value = document.getElementById("lastName").value;
			document.getElementById("postMailing").value = document.getElementById("mailing").value;
			document.getElementById("postCountry").value = document.getElementById("country").value;
			document.getElementById("postState").value = document.getElementById("state").value;
			document.getElementById("postCustomState").value = document.getElementById("customState").value;
			document.getElementById("postCity").value = document.getElementById("city").value;
			document.getElementById("postZip").value = document.getElementById("zip").value;
			document.getElementById("postMajor").value = document.getElementById("interested").value;
			document.getElementById("postDegree").value = document.getElementById("degree").value;
			
			// Gets the fields of the 2 forms, from Step 1 and 2, and given json format
			var data  = Twd.collectFields( FinalFormStep );
			
			// if nothing is stored in name - do nothing
			// CAIVIS(LDS) 2/17/09
			if(document.getElementById("postFirstname").value == "" && document.getElementById("postLastname").value == "") {
			} else {
				// Makes a request using the method POST
		  	Twd.Ajax.Post( '/learning_wizard/StoreUserData.php', data, function (){} );
			}

		}
	}
	return false;
};


/**
 * This method takes the user to the next step
 *
 * @param  HTMLElement object   = specifies the object 
 * @param  Integer    iCurrentStep	= specifies the current step number
 * @param  Integer    iFieldGroup  	= the fieldgroup the current step will display or call
 * @return false
 * CAIVIS(LDS) - 2/11/09
 */

TrueWizard.LearningWizardNextStep = function(iCurrentStep, iFieldGroup) {
	
	var sFieldGroupFile = "/learning_wizard/FieldGroups.php/" + iFieldGroup + "/";		

	var lineStep = "line-step";
	var sCurrentErrors = "step" + iCurrentStep + "-errors";
	var sCurrentGoogleTracker = "wizardStep" + iCurrentStep;
	var sCurrentStep = "step" + iCurrentStep;
	var sCurrentSubmit = "step" + iCurrentStep + "-submit";
	var sCurrentWizardStep = "wizard-step" + iCurrentStep; 							
	
	var iNextStep = iCurrentStep + 1;
	var sNextFormStep = "form-step" + iNextStep;
	var sNextStepSubmit = "step" + iNextStep + "-submit"; 							
	var sNextWizardStep = "wizard-step" + iNextStep;										

	var nextForm = document.getElementById(sNextFormStep);
	
	Twd.$( sCurrentSubmit ).addEvent('click', function( event ) {
	

		if( iCurrentStep == GenericGroupCount ) {
			
			// CAIVIS(LDS) 2/17/09 - swapped var check with email criteria
			var check   = [
	        { field : 'email',       message : 'Email is required' },
	        { field : 'email',       message : 'Please enter a valid email address', expr: /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(aero|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|us|ca|ae|sa|bh|kw|qa|om|lb)(\.[a-z]{2})?$/i }
	    ];

			var errors = TrueWizard.Validate( check );

			if ( errors.length > 0 ){
				TrueWizard.Errors( errors, sCurrentStep );
				return false;
			}
			
			TrueWizard.$( sCurrentErrors ).remove();
		
			// CAIVIS(LDS) 2/11/09  Move all data to final form before submitting
			document.getElementById("postEmail").value = document.getElementById("email").value;
			document.getElementById("postFirstname").value = document.getElementById("firstName").value;
			document.getElementById("postLastname").value = document.getElementById("lastName").value;
			document.getElementById("postMailing").value = document.getElementById("mailing").value;
			document.getElementById("postCountry").value = document.getElementById("country").value;
			document.getElementById("postState").value = document.getElementById("state").value;
			document.getElementById("postCustomState").value = document.getElementById("customState").value;
			document.getElementById("postCity").value = document.getElementById("city").value;
			document.getElementById("postZip").value = document.getElementById("zip").value;
			document.getElementById("postMajor").value = document.getElementById("interested").value;
			document.getElementById("postDegree").value = document.getElementById("degree").value;
			
		} else {
			
			if ( this.element.isActive ) {
				return false;
			}

			// Performs validations of the second step
			if ( eval("checkStep" + iCurrentStep + ".length") > 0 ) {
			    var errors = TrueWizard.Validate( eval("checkStep" + iCurrentStep + "") );
			    if ( errors.length > 0 ) {
			        TrueWizard.Errors( errors, sCurrentStep );
			        return false;
			    }
			}
			
			TrueWizard.$( sCurrentErrors ).remove();

		}
		
		// Gets the form fields with their respective values
		var data = Twd.collectFields( FinalFormNumberString );
		
		// google tracking for clicking to step 2 from the wizard
		// pageTracker._trackPageview( sCurrentGoogleTracker );
		
		// Change the bailout point to the next step
		document.getElementById("postBailOutPoint").value = iNextStep;
		
		
    // Makes a request using the method POST
    Twd.Ajax.Post( sFieldGroupFile, data, function( response )
    {		
				
				// CAIVIS(LDS) 2/11/09
        Twd.$( lineStep ).width( IncrementWidth * iNextStep, function()
        {

					if ( response.error == true ) {

					    Twd.$( sNextFormStep ).empty().append( Twd.Create('h3', {'class':'error'}, response.errors[ 0 ] ) );
					    Twd.$( sNextStepSubmit ).addClass( 'hidden' );

					} else {
						
						
						// CAIVIS(LDS) 2/19/09
						stepInterest = document.getElementById("interested").value;
						stepDegree = document.getElementById("degree").value;
						previousInterest = document.getElementById("previousInterest").value;
						previousDegree = document.getElementById("previousDegree").value;
						
						// alert("Current Degree = " + stepInterest + "\n" + "Old Degree = " + previousInterest + "\n\n" + "Current Degree Level= " + stepDegree + "\n" + "Old Degree Level = " + previousDegree + "\n");
												
						// CAIVIS(LDS) 2/19/09
						// This if statement checks to see if the next form has already been built
						if(stepInterest != previousInterest || stepDegree != previousDegree || nextForm.length == 0) {
												   					
					 		var empty = true;

					    // Check if there is a title to show
					    // If exists, create the element and adds it to Form
					    if ( response.title ) {
					        Twd.$( sNextFormStep ).empty().append( Twd.Create('h3', null, response.title ) );
					        empty = false;
					    }

					    // Text of Universities
					    if ( response.unis ) {
					        for ( var i = 0, len = response.unis.length; i < len; i++ ){

					            var message = response.unis[ i ];

					            if ( typeof response.degree[ i ] != 'undefined' && response.degree[ i ].length > 0 ) {
					                message += ' - ' + response.degree[ i ];
					            }

					            Twd.$( sNextFormStep ).append( Twd.Create('h4', null, message ) );
					        }
					        empty = false;
					    }

					    // Second Title
					    if ( response.title2 ) {
					        Twd.$( sNextFormStep ).append( Twd.Create('h3', null, response.title2 ) );
					        empty = false;
					    }

					    if ( response.fields instanceof Object ) {
					        // Create fields from the object returned by the server
									
					        var fields = new Twd.Fields( response.fields );
					            fields.toForm( sNextFormStep, empty, iCurrentStep );

					        eval("checkStep" + iNextStep +" = Twd.getFieldsValidations( response.fields );");
					    }
					
						}

					    // Shows the button "Submit" if this is hidden
					    Twd.$( sNextStepSubmit ).removeClass( 'hidden' );
					}

					 // Hide step 1
					Twd.$( sCurrentWizardStep ).addClass( 'hidden' );

					// Shows Step 2
					Twd.$( sNextWizardStep ).removeClass( 'hidden' );
					
					// CAIVIS(LDS) 2/13/09
					var delayedFunctionCall = setTimeout("formfocus('" + sNextFormStep + "')", 1200);

          this.parent().addClass('active');

        });
    });

    // Break the event
    return false;
	});
};



/**
 * This method takes the user to the previous step
 *
 * @param  Integer    iCurrentStep	= specifies the current step number
 * @return false
 *
 * CAIVIS(LDS) - 2/11/09
 */

TrueWizard.LearningWizardStepBack = function(iCurrentStep) {
	
	var slineStep = "line-step";
	
	var sCurrentStepBack = "step" + iCurrentStep + "-back";
	var sCurrentStepErrors = "step" + iCurrentStep + "-errors";
	var sCurrentStepSubmit = "step" + iCurrentStep + "-submit";
	var sCurrentWizardStep = "wizard-step" + iCurrentStep;
	
	var iPreviousStep = iCurrentStep - 1;
	var sPreviousStepErrors = "step" + ( iCurrentStep - 1 ) + "-errors";
	var sPreviousWizardStep = "wizard-step" + ( iCurrentStep - 1 );
	
	
	Twd.$( sCurrentStepBack ).addEvent('click', function() {
		
    // Aborts the current request
    Twd.Ajax.Post.abort();

		// Change bailout point to previous step
		document.getElementById("postBailOutPoint").value = iPreviousStep;
		
		// CAIVIS(LDS) 2/19/09
		document.getElementById("previousInterest").value = document.getElementById("interested").value;
		document.getElementById("previousDegree").value = document.getElementById("degree").value;
		
    // shrinking the line stepper
    Twd.$( slineStep ).width( IncrementWidth * iPreviousStep , function()
    {
        // returns the text of "Step 2" to gray
        this.parent().removeClass('active');

        // Removes indicator of activity ajax
        var submit = Twd.$( sCurrentStepSubmit );
            submit.element.isActive = false;
            submit.removeClass('wait').first().empty().append('Next ').append( Twd.Create('strong', null, 'ª') );
						
				// Remove errors
				TrueWizard.$( sCurrentStepErrors ).remove();
				TrueWizard.$( sPreviousStepErrors ).remove();

        // Switch View States
        Twd.$( sCurrentWizardStep ).addClass( 'hidden' );
        Twd.$( sPreviousWizardStep ).removeClass( 'hidden' );
    });

    return false;
	});
};


// CAIVIS(LDS) 2/23/09
// BEGIN
TrueWizard.LearningWizardStepBackFromError = function(iCurrentStep) {
		
	var sCurrentStepBack = "step" + iCurrentStep + "-back";
	var sCurrentWizardStep = "wizard-step" + iCurrentStep;
	
	var iPreviousStep = iCurrentStep - 1;
	var sPreviousStepErrors = "step" + ( iCurrentStep - 1 ) + "-errors";
	var sPreviousWizardStep = "wizard-step" + ( iCurrentStep - 1 );
	var sPreviousStepSubmit = "step" + iPreviousStep + "-submit";
	
	
	Twd.$( sCurrentStepBack ).addEvent('click', function() {
		
    // Aborts the current request
    Twd.Ajax.Post.abort();

		// Change bailout point to previous step
		document.getElementById("postBailOutPoint").value = iPreviousStep;
		
		// Removes indicator of activity ajax
		var submit = Twd.$( sPreviousStepSubmit );
		submit.element.isActive = false;
		submit.removeClass('wait').first().empty().append('Submit ').append( Twd.Create('strong', null, 'ª') );
		
		
    // returns the text of "Step 2" to gray
    this.parent().removeClass('active');

		// Switch View States
		Twd.$( sCurrentWizardStep ).addClass( 'hidden' );
		Twd.$( sPreviousWizardStep ).removeClass( 'hidden' );

    return false;
	});
};
// END


/**
 * This method submits all of Learning Wizard
 *
 * @param  HTMLElement object   = specifies the object 
 * @param  Integer    iCurrentStep		= specifies the current step number
 * @param  Integer    FinalFormNumber	= this is the hidden form that holds other metadata for the confirmation page
 * @return false
 * CAIVIS(LDS) - 2/11/09
 *
 *
 * A lot of the code in this method is not dynamic yet, the had coded strings will need to 
 * be replaced with variables.
 */

TrueWizard.LearningWizardSubmit = function(iCurrentStep, FinalFormNumber) {
	
	// Variables
	var sCurrentStepSubmit = "step" + iCurrentStep + "-submit";
	var sCurrentLineStep = "line-step";
	var sCurrentGoogleTracker = "wizardStep" + iCurrentStep;
	
	var iNextStep = iCurrentStep + 1;
	var sNextForm = "form-step" + iNextStep;
	var sNextSubmit = "step" + iNextStep + "-submit";
	
		
	Twd.$( sCurrentStepSubmit ).addEvent('click', function() {
		
		// shrinking the line stepper
		Twd.$( sCurrentLineStep ).width( IncrementWidth * FinalFormNumber , function(){ return false; });
		
		// Set Bail Out Point CAIVIS(LDS) 2-9-09
		document.getElementById("postBailOutPoint").value = ( iCurrentStep + 1 );
    
		if ( this.element.isActive ) { return false; }

    // Performs validations of the second step
    if ( checkStep7.length > 0 ) {
        var errors = TrueWizard.Validate( checkStep7 );
        if ( errors.length > 0 ) {
            TrueWizard.Errors( errors, 'step7' );
            return false;
        }
    }

    // google tracking
    // pageTracker._trackPageview( sCurrentGoogleTracker );

    // Add indicator of ajax activity
    this.first().empty().append( Twd.Create('img', { 'src' : '/learning_wizard/css/images/ajax-loader.gif', 'alt' : '' }) ).parent().addClass('wait');
    this.element.isActive = true;

    var submit = this;

    // Gets the fields
		var step1  = Twd.collectFields( 'form-step1' );
		var step2  = Twd.collectFields( 'form-step2' );
		var step3  = Twd.collectFields( 'form-step3' );
		var step4  = Twd.collectFields( 'form-step4' );
		var step5  = Twd.collectFields( 'form-step5' );
		var step6  = Twd.collectFields( 'form-step6' );
		var step7  = Twd.collectFields( 'form-step7' );
		// var step8  = Twd.collectFields( 'form-step8' );
		// var step9  = Twd.collectFields( 'form-step9' );
		var data   = Twd.jsonEncode({ step1:step1, step2:step2, step3:step3, step4:step4, step5:step5, step6:step6, step7:step7 });
		var errors = [];

    // CAIVIS(LDS) 7/2/09
		function gup( name )
    {
      name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
      var regexS = "[\\?&]"+name+"=([^&#]*)";
      var regex = new RegExp( regexS );
      var results = regex.exec( window.location.href );
      if( results == null )
        return "";
      else
        return results[1];
    }

		// CAIVIS(LDS) 2/23/09
    // Ajax makes the request by sending all the data of the 2 forms
    // CAIVIS(LDS) 7/2/09
    // Added the keyword and path parameters	
		// BEGIN
    Twd.Ajax.Post( '/learning_wizard/process.php', {json:data, keyword:gup('keyword'), path:gup('referrer_path'), source:gup('source')}, function( response )
    {
        if ( response.error == false ) {
	
					// Set Bail Out Point CAIVIS(LDS) 2-9-09
					document.getElementById("postBailOutPoint").value = ( iCurrentStep + 1 );
					
					// CAIVIS(LDS) 3/20/09
					if(response.PostStatus == "failed") {
												
						var PostStatusFailedTextArray = response.PostStatusFailedText.split("|");
						var FailedTextMessagesCount = PostStatusFailedTextArray.length;
						
						showUserErrors = true;
						
						// if( PostStatusFailedTextArray.length > 2 ) {
						// 	showUserErrors = true;
						// } else {
						// 	showUserErrors = false;
						// }
						
					} else {
												
						showUserErrors = false;
					}
					
					//alert(showUserErrors);
					
					// Set number of error messages to check if showing or not showing the error page
				 if( showUserErrors ) {

						var lineStep = "line-step";
						var sCurrentErrors = "step" + iCurrentStep + "-errors";
						var sCurrentGoogleTracker = "wizardStep" + iCurrentStep;
						var sCurrentStep = "step" + iCurrentStep;
						var sCurrentSubmit = "step" + iCurrentStep + "-submit";
						var sCurrentWizardStep = "wizard-step" + iCurrentStep; 							

						var sNextFormStep = "form-step" + iNextStep;
						var sNextStepSubmit = "step" + iNextStep + "-submit"; 							
						var sNextWizardStep = "wizard-step" + iNextStep;										

						var nextForm = document.getElementById(sNextFormStep);

						// google tracking for clicking to step 2 from the wizard
						// pageTracker._trackPageview( sCurrentGoogleTracker );

						// Change the bailout point to the next step
						document.getElementById("postBailOutPoint").value = iNextStep;

						Twd.$( sNextFormStep ).empty().append( Twd.Create('h3', null, "Ooops! Looks like there were a few errors!" ) );
						
						for(var count = 0; count < FailedTextMessagesCount; count++) {
							if (PostStatusFailedTextArray[count]) {
								Twd.$( sNextFormStep ).append( Twd.Create('h4', null, PostStatusFailedTextArray[count] ) );
							}
						}

						Twd.$( sNextStepSubmit ).addClass( 'hidden' );

						// Hide step 1
						Twd.$( sCurrentWizardStep ).addClass( 'hidden' );

						// Shows Step 2
						Twd.$( sNextWizardStep ).removeClass( 'hidden' );

					} else {
						
						// Set Bail Out Point CAIVIS(LDS) 2-9-09
						document.getElementById("postBailOutPoint").value = ( iCurrentStep + 2 );
						
						// Change Form Action
						var action = Twd.formAction( FinalFormNumberString );
						if (action) {return false;}
	          // Submit Form
	    			var submit = Twd.formSubmit( FinalFormNumberString );
	    			if (submit) {return false;}
					
					};
					


	
        } else if ( response.error == true && response.errors instanceof Object ) {

            // Removes the class labels that error to find any error had previously
            for ( var i = 0, len = errors.length; i < len; i++ ) {
                Twd.$( 'lbl-' + errors[ i ].field ).removeClass( 'error' );
            }

            // Shows the new errors
            TrueWizard.Errors( ( errors = response.errors ), 'step7' );
        }
    });
		// END

    return false;
	});

	
};



/**
 * This method triggers the specified event to the supplied object
 *
 * @param  HTMLElement object   = specifies the object 
 * @param  String      type     = specifies the event to attach
 * @param  String    	 keyCode  = passes the key code of the pressed key
 * @return false
 * CAIVIS(LDS) - 1/29/09
 */

TrueWizard.trigger = function( object, type, keyCode )
{	
	var fireOnThis = document.getElementById(object);

	if (navigator.appName == "Microsoft Internet Explorer"){ //test for MSIE x.x;
		fireOnThis.fireEvent("on"+type);
		return true;
	} else {
  var evObj = document.createEvent('MouseEvent');
  evObj.initEvent( type, true, false );
  fireOnThis.dispatchEvent(evObj);
	return true;
	}
};



/**
 * This method assigns the specified event to the supplied object
 * and invokes the callback function when the event takes place
 *
 * @param  HTMLElement object   = specifies the object 
 * @param  String      type     = specifies the event to attach
 * @param  Function    callback = specifies the callback function that gets executed when the event takes place
 * @return void
 */

TrueWizard.addEvent = function( object, type, callback )
{
    if ( object.addEventListener ) {
        object.addEventListener( type, callback, false );
    }
    else if ( object.attachEvent ) {
        object.attachEvent('on' + type, function( event )
        {
            if ( !event ) {
                event = window.event;
            }
            callback.call( this, event );
        });
    }
};


/**
 * Pulls all the elements of a form with their respective values
 * and returns associative array with the field name and its value respecito
 *
 * @param  String formId = the unique identifier of the form
 * @return Object fields
 */

TrueWizard.collectFields = function( formId )
{
    var form   = document.getElementById( formId );

    if ( null != form ) {

        var fields  = {};
        var special = {};

        for ( var i = 0; i < form.elements.length; i++  ){

            var element = form.elements[ i ];

            var name    = element.getAttribute('name');
            var value   = this.collectFields.getValue( element );

            if ( 'field' in element && !( 'items' in element ) ) {

                var realName = name.substr( 0, name.lastIndexOf('-') );

                if ( !( realName in special ) ) {
                    var separator = '-';

                    switch( element.field ) {
                        case TrueWizard.FIELD_TYPE_PHONE:
                            separator = '';
                        break;
                    }

                    special[ realName ] = [ separator ];
                }

                special[ realName ].push( value );
            }
            else {
                fields[ name ] = value;
            }
        }

        for ( var name in special ) {
            var separator  = special[ name ].shift();
            fields[ name ] = special[ name ].join( separator );
        }
    }

    return fields;
};

/**
 * Gets the value of the element depending on the type that is
 *
 * @param  HTMLElement element = element to evaluate
 * @return String value
 */

TrueWizard.collectFields.getValue = function( element )
{
    var value = '';

    switch( element.tagName.toLowerCase() ) {
        case 'input':
            switch( element.getAttribute('type').toLowerCase() ) {
                case 'text':
                case 'hidden':
                    value = element.value;
                break;
                case 'checkbox':
                    if ( element.checked ) {
                        value = element.value;
                    }
                break;
            }
        break;
        case 'textarea':
            value = element.value;
        break;
        case 'select':
            if ( -1 != element.selectedIndex ) {
                value = element.options[ element.selectedIndex ].value;
            }
        break;
    }

    return value;
};

/**
 * Gets the CSS class to be applied to the container campo
 *
 * @param  int type = The type of field
 * @return String
 */

TrueWizard.getClassByType = function( type )
{
    var clsTypes = {};
				clsTypes[ TrueWizard.FIELD_TYPE_TEXT ]     = 'text';
				clsTypes[ TrueWizard.FIELD_TYPE_HIDDEN ]   = 'hidden';
				clsTypes[ TrueWizard.FIELD_TYPE_RADIO ]    = 'radio';
				clsTypes[ TrueWizard.FIELD_TYPE_CHECKBOX ] = 'checkbox';
				clsTypes[ TrueWizard.FIELD_TYPE_SELECT ]   = 'select';
				clsTypes[ TrueWizard.FIELD_TYPE_CALENDAR ] = 'calendar';
				clsTypes[ TrueWizard.FIELD_TYPE_PHONE ]    = 'phone';
				clsTypes[ TrueWizard.FIELD_TYPE_EMAIL ]    = 'text';
				clsTypes[ TrueWizard.FIELD_TYPE_IP ]       = 'hidden';
				clsTypes[ TrueWizard.FIELD_TYPE_TEXTAREA ] = 'text';
				clsTypes[ TrueWizard.FIELD_TYPE_AGE ]      = 'calendar';
				// CAIVIS(LDS) 3/27/09
				clsTypes[ TrueWizard.FIELD_TYPE_CUSTOM_START_DATE ] = 'custom_start_date';

    if ( type in clsTypes ) {
    	return clsTypes[ type ];
    }

    return '';
};

/**
 * Create an HTML element, it creates and applies the attributes that you specify
 *
 * @param  String tag        = The HTML tag of the element
 * @param  Object attributes = associative array of attributes to be applied to the element
 * @param  String value      = textNode value
 * @return HTMLElement
 */

TrueWizard.Create = function( tag, attributes, value )
{
    if ( document.all ) {
        var elementAttr = [];

        if ( typeof attributes != 'undefined' && attributes instanceof Object ) {
            for ( var name in attributes ) {
                elementAttr.push( name + '="' + attributes[ name ] + '"' );
            }
        }

        var element = document.createElement( '<' + tag + ' ' + elementAttr.join(' ') + '>' );
    }
    else {
        var element = document.createElement( tag );

        if ( typeof attributes != 'undefined' && attributes instanceof Object ) {
            for ( var name in attributes ) {
                var attr = document.createAttribute( name );
                    attr.nodeValue = attributes[ name ];
                element.setAttributeNode( attr );
            }
        }
    }

    if ( typeof value != 'undefined' ) {
        element.appendChild( document.createTextNode( value ) );
    }

    return element;
};

/**
 * Convert an object to a string json
 *
 * @param  Object object = the object that will be converted
 * @return String
 */

TrueWizard.jsonEncode = function( object )
{
    // Part of this script is based on http://www.JSON.org/json.js

    var cx         = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var meta       = {
        '\b' : '\\b',
        '\t' : '\\t',
        '\n' : '\\n',
        '\f' : '\\f',
        '\r' : '\\r',
        '"'  : '\\"',
        '\\' : '\\\\',
        '\/' : '\\/'
    };

    var escapeString = function( string )
    {
        escapeable.lastIndex = 0;

        if ( escapeable.test( string ) ) {

            string = string.replace( escapeable, function( a )
            {
                return '\\u' + ( '0000' + ( + ( a.charCodeAt(0) ) ).toString( 16 ) ).slice( -4 );
            });
        }

        for ( var key in meta ) {
            string = string.replace(key, meta[ key ]);
        }

        return '"' + string + '"';
    };

    var json   = [];

    for ( var key in object ){
        switch ( typeof object[ key ] ) {
            case 'string':
            case 'number':
                json.push('"' + key + '":' + escapeString( object[ key ] ));
            break;
            case 'boolean':
                json.push('"' + key + '":' + object[ key ] );
            break;
            case 'object':
                json.push('"' + key + '":' + this.jsonEncode( object[ key ] ));
            break;
        }
    }

    return '{' + json.join(',') + '}';
};


/**
 * Performs validation and returns an array with the errors found
 *
 * @param  Array check = fields that will be checked
 * @return Array errors
 */
TrueWizard.Validate = function( check )
{
    var errors  = [];
    var checked = [];

    for ( var i = 0, len = check.length; i < len; i++ ) {

        if ( -1 == checked.indexOf( check[ i ].field ) ) {

            var element = Twd.$( check[ i ].field );
            var value   = element.value();

            if ( check[ i ].type == TrueWizard.FIELD_TYPE_PHONE ) {
                value = '';

                var items = ( check[ i ].items ) ? check[ i ].items : [ null, 1, 2, 3 ];

                for ( var x = 1; x <= 3; x++ ) {
                    value += Twd.$( check[ i ].field + '-' + items[ x ] ).value();
                }
            }

            if ( check[ i ].type == TrueWizard.FIELD_TYPE_CALENDAR || check[ i ].type == TrueWizard.FIELD_TYPE_AGE ) {
                var d = Twd.$( check[ i ].field + '-d' ).value();
                var m = Twd.$( check[ i ].field + '-m' ).value();
                var Y = Twd.$( check[ i ].field + '-Y' ).value();
								
								// CAIVIS(LDS) 12-23-08 Added the Radix Argument to the parseInt() function
								// Without the radix argument - values '08' and '09' broke the function and returned 0
                if ( parseInt(d, 10) > 0 && parseInt(m, 10) > 0 && parseInt(Y, 10) > 0  ) {
                    value = d + '-' + m + '-' + Y;
                }
            }

            if ( check[ i ].type == TrueWizard.FIELD_TYPE_SELECT && value == '-1' ) {
                value = '';
            }

            if ( typeof check[ i ].validate == 'function' ) {
                if ( check[ i ].validate.call( element, value ) === false ) {
                    Twd.$( 'lbl-' + check[ i ].field ).removeClass( 'error' );
                    continue;
                }
            }

            if ( value == '' ||
               ( check[ i ].expr && !check[ i ].expr.test( value ) ) ||    // verifies if there is a regular expression and tests
               ( check[ i ].equals && check[ i ].equals != value ) ||      // verifies if the value should be equal to
               ( check[ i ].length && check[ i ].length != value.length )  // verifies that the number of characters is equal to
               ) {
                errors .push( check[ i ] );
                checked.push( check[ i ].field )
            }
            else {
                Twd.$( 'lbl-' + check[ i ].field ).removeClass( 'error' );
            }
        }
    }

    return errors;
}

/**
 * Function which is responsible for handling errors in the forms
 *
 * @param  Object errors = errors that will be shown
 * @param  String   step = Specifies that step should be displayed errors
 * @return void
 */

TrueWizard.Errors = function( errors, step )
{
    // if there remove existing errors
    // in the event of continued mistakes will be re-generate
    TrueWizard.$( step + '-errors' ).remove();

    var ul = Twd.Create('ul', { 'class' : 'errors', 'id' : step + '-errors' });

    if ( document.all ) {
        Twd.$( ul ).addClass( 'IE' );
    }

    for ( var i = 0, len = errors.length; i < len; i++ ) {

        // It gives the red color to the labels of the fields that contain errors
        Twd.$( 'lbl-' + errors[ i ].field ).addClass( 'error' );

        // Create the element of the list and that will contain the error message
        var li    = Twd.Create('li');
        var extra = '';

        if ( 'type' in errors[ i ] && errors[ i ].type == TrueWizard.FIELD_TYPE_PHONE ) {
            extra = ( errors[ i ].items ) ? '-' + errors[ i ].items[ 1 ] : '-1';
        }

        if ( 'type' in errors[ i ] && ( errors[ i ].type == TrueWizard.FIELD_TYPE_CALENDAR || errors[ i ].type == TrueWizard.FIELD_TYPE_AGE ) ) {
            extra = '-' + errors[ i ].dateFormat.substr(0, 1);
        }

        var label = Twd.Create('label', { 'for' : errors[ i ].field + '' + extra }, errors[ i ].message );

        // Only for Enternet Explorer 6
        // Js is added from the mouseover events and the label mouseout
        // because from css property is not supported "hover" for this element
        if ( document.all && !window.XMLHttpRequest ) {
            Twd.$( label ).addEvent( 'mouseover', function(){
                this.element.style.textDecoration = 'underline';
            })
            .addEvent('mouseout', function(){
                this.element.style.textDecoration = 'none';
            });
        }

        li.appendChild( label );
        ul.appendChild( li );
    }

    // I add the list of errors to form
    Twd.$( 'wizard-' + step ).append( ul, Twd.$( step + '-control' ).element );
}

/**
 * Extends an object and returns it
 *
 * @param  Object destination = Object that will be extended
 * @param  Object source      = Object with properties and / or methods to be extended
 * @return Object destination
 */

TrueWizard.extend = function( destination, source )
{
    for ( var property in source ) {
        destination[ property ] = source[ property ];
    }

    return destination;
};

/**
 * Clone an object without modifying the original
 *
 * @param  Object object = Object to be cloned
 * @return Object
 */

TrueWizard.clone = function( object )
{
    var clon = {};

    for ( var key in object ) {
        if ( typeof object[ key ] == 'object' && !( object[ key ] instanceof Array ) ) {
            clon[ key ] = this.clone( object[ key ] );
        }
        else {
            clon[ key ] = object[ key ];
        }
    }

    return clon;
}

/**
 * Gets the fields to be validated in the second step
 *
 * @param  Object field = Generic object fields
 * @return Array
 */

TrueWizard.getFieldsValidations = function( fields )
{
    var allowToCheck = [
        TrueWizard.FIELD_TYPE_TEXT,
        TrueWizard.FIELD_TYPE_CHECKBOX,
        TrueWizard.FIELD_TYPE_SELECT,
        TrueWizard.FIELD_TYPE_CALENDAR,
        TrueWizard.FIELD_TYPE_EMAIL,
        TrueWizard.FIELD_TYPE_PHONE,
        TrueWizard.FIELD_TYPE_AGE
    ];

    var check = [];

    for ( var i = 0, len = fields.length; i < len; i++ ) {

        if ( fields[ i ] instanceof Array ) {
            var checkGoup = this.getFieldsValidations( fields[ i ] );
            for ( var x = 0, length = checkGoup.length; x < length; x++ ) {
                check.push( checkGoup[ x ] );
            }
            continue;
        }

        if ( fields[ i ].required && -1 != allowToCheck.indexOf( fields[ i ].type )  ) {

            var validate = {
                type    : fields[ i ].type,
                field   : fields[ i ].name
            };

            if ( fields[ i ].dateFormat ) {
                validate.dateFormat = fields[ i ].dateFormat;
            }
            
            if ( fields[ i ].type == TrueWizard.FIELD_TYPE_PHONE && fields[ i ].items ) {
                validate.items = fields[ i ].items;
            }

            // As in all js is passed by reference, the object clone "validate"
            // so validations of each field will not interfere with the next prize validation

            check.push( TrueWizard.extend( TrueWizard.clone( validate ), {
                message : fields[ i ].label + ' is required'
            }));

            if ( fields[ i ].type == TrueWizard.FIELD_TYPE_EMAIL ) {
                check.push( TrueWizard.extend( TrueWizard.clone( validate ), {
                    expr    : /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(aero|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|us|ca|ae|sa|bh|kw|qa|om|lb)(\.[a-z]{2})?$/i,
                    message : 'Please enter a valid ' + fields[ i ].label
                }));
            }

            if ( fields[ i ].equals ) {
                check.push( TrueWizard.extend( TrueWizard.clone( validate ), {
                    equals  : fields[ i ].equals,
                    message : fields[ i ].label + ' must be equal to ' + fields[ i ].equals
                }));
            }

            if ( fields[ i ].min && fields[ i ].max && fields[ i ].min == fields[ i ].max ) {
                check.push( TrueWizard.extend( TrueWizard.clone( validate ), {
                    length  : fields[ i ].max,
                    message : fields[ i ].label + ' must be ' + fields[ i ].max + ' characters long'
                }));
            }
        }
    }

    return check;
};
