/**
 * @filename registration.js
 * 
 * @description Handles the displaying of messages during user registration
 * 
 * @author Jason Holmes
 * @email jason.holmes at garmin.com
 *
 * Copyright(c) 2009, Garmin International
 */

RegistrationPage = Class.create({
	initialize : function(config){
	    this.form = $('registration');
	    this.form.focusFirstElement();
	    this.fields = new Array();
	    
	    this.fields.push(new TextField($('registration:fullNameDecoration').down()));
	    this.fields.push(new EmailChecker($('registration:emailDecoration').down()));
	    this.fields.push(new UsernameChecker($('registration:usernameDecoration').down()));
	    this.fields.push(new PasswordChecker($('registration:passwordDecoration').down()));
	    this.fields.push(new PasswordConfirmChecker($('registration:passwordConfirmDecoration').down(),$('registration:passwordDecoration:password')));
	    this.fields = this.fields.concat($$('.createAccountCheckboxWrapper').collect(function(div) {
	    	return new CheckboxField(div);
	    }));
	    
	    var firstField = this.fields.first(); 
	    if(!firstField.field.present()) {
	    	firstField.onFocus();
	    }
	    
	    this.formSubmitted = false;
	    this.form.observe('submit', function(e) {
	    	if(this.formSubmitted || !this.isValid()) {
	    		Event.stop(e);
	    	} else {
	    		this.formSubmitted = true;
	    	}
	    }.bind(this));
	},
	
	isValid: function() {
		return this.fields.all(function(field) {
			var valid = field.validate();
			if(valid) {
				valid = field.checkRequired();
			}
			
			return valid;
		});
	}
});


/**
 * we don't want to mark a field having an error if no 
 * text is present until the user submits the form.
 * 
 * hence the seperation of validate and checkRequired
 */
Field = Class.create({
	initialize: function(wrapperDiv) {
		this.fadeOptions = {duration: 0.3};
		this.appearOptions = {duration: 0.3};
		
		this.minLength = 1;
		this.div = wrapperDiv;
		
		this.field = this.div.getElementsBySelector('input')[0];
		this.field.observe('focus', this.onFocus.bind(this));
		this.field.observe('blur', this.onChange.bind(this));
		
		this.error = this.div.getElementsBySelector('.error')[0];
		this.info = this.div.getElementsBySelector('.info')[0];
		this.reqd = this.div.getElementsBySelector('.reqd')[0];
	},
	
	onFocus: function() {
	},
	
	onChange: function() {
	},
	
	/**
	 * show req'd when somebody tells us to. hide everything else
	 */
	checkRequired: function() {
		var valid = this.field.present();
		if(!valid) {
			this.reqd.show(); // appear won't work 'cause of focus and visible()
			this.field.focus();
		}
		return valid;
	},
	
	/**
	 * check if the form isValid(). if it isn't, display the error
	 */
	validate: function($super) {
		this.info.hide();
		this.reqd.hide();
		var valid = this.isValid();

		if(!valid) {
			this.error.appear(this.appearOptions);
		}
		
		return valid;
	},
	
	/**
	 * is the form valid? per larry, don't display errors if no text is entered!
	 */
	isValid: function() {
		return !this.field.present() || ((this.field.present()) && ($F(this.field).length >= this.minLength));
	}
});

TextField = Class.create(Field, {
	onFocus: function() {
		this.error.hide();
		
		if(!this.reqd.visible()) {
			this.info.appear(this.appearOptions);
		}
	},
	
	onChange: function() {
		this.validate();
	}
});

UsernameChecker = Class.create(TextField, {
	initialize: function($super, wrapperDiv) {
		$super(wrapperDiv);

		this.minLength = 6;
		this.client = new Garmin.service.settingsClient();
		this.ok = this.div.getElementsBySelector('.ok')[0];
		this.checking = this.div.getElementsBySelector('.validating')[0];
	},
	
	onFocus: function($super) {
		$super();
		this.ok.hide();
	},
	
	onChange: function($super) {
		if(this.field.present()) {
			this.checking.show();
			this.info.fade(this.fadeOptions);
			this.reqd.fade(this.fadeOptions);
			this.client.isUsernameAvailable($F(this.field), {
				onSuccess: this.successUsernameResult.bindAsEventListener(this),
				onFailure: this.failUsernameResult.bindAsEventListener(this)
			});
		} else {
			$super();
		}
	},
	
	successUsernameResult: function(response) {
		this.checking.hide();
		
		answer = response.responseText.evalJSON().string;
		if(answer == $F(this.field)) {
			this.ok.show();
			this.error.fade(this.fadeOptions);
		} else {
			this.ok.hide();
			this.error.appear(this.appearOptions).innerHTML = bundle_user_api.registration_username_duplicate;
		}
	},
	
	failUsernameResult: function(response) {
		this.checking.hide();
		this.error.fade(this.fadeOptions);
		this.info.fade(this.fadeOptions);
		this.ok.hide();
		alert(bundle_user_api.registration_myGarmin_down);
	}
});

EmailChecker = Class.create(TextField, {
	initialize: function($super, wrapperDiv) {
		$super(wrapperDiv);
		this.minLength = 3;
		this.pattern = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
	},
	
	/**
	 * if we've got more than one error, we have the email aready taken by user error.
	 * Remove this one, and make the normal error the one to use 
	 */
	onChange: function($super) {
		$super();

		var errors = this.div.getElementsBySelector('.error');
		if(errors.length > 1) {
			this.error = errors[1];
			errors[0].remove();
		}
	},
	
	isValid: function() {
		return !this.field.present() || (this.pattern.test($F(this.field)));
	}
});

PasswordChecker = Class.create(TextField, {
	initialize: function($super, wrapperDiv, passwordField) {
		$super(wrapperDiv);
		this.minLength = 6;
	}
});

PasswordConfirmChecker = Class.create(TextField, {
	initialize: function($super, wrapperDiv, passwordField) {
		$super(wrapperDiv);
		this.passwordField = passwordField;
	},

	isValid: function() {
		return !this.field.present() || ($F(this.field) == $F(this.passwordField));
	}
});

CheckboxField = Class.create(Field, {
	initialize: function($super, wrapperDiv) {
		$super(wrapperDiv);
		this.error = this.div.getElementsBySelector('.createAccountCheckboxMessage')[0];
		this.field.observe('click', this.checkRequired.bind(this));
	},
	
	validate: function() {
		return true;
	},
	
	isValid: function() {
		return true;
	},
	
	checkRequired: function() {
		var valid = this.field.checked;
		if(valid) {
			this.error.removeClassName('checkboxError');
			this.error.innerHTML = "";
		} else {
			this.error.addClassName('checkboxError');
			this.error.innerHTML = bundle_user_api.registration_required;
		}	
		return valid;
	}		
});


Event.observe(window, 'load', function() {
  new RegistrationPage(null);
});
