/*
 * NOTE: WizardAssistant is an abstract class, providing common properties and methods. It is 
 * extended by either EditAccountSceneFunctions or CreateAccountSceneFunctions as appropriate.
 
Copyright 2009 Palm, Inc.  All rights reserved.

*/
var WizardAssistant = Class.create({

	initialize: function(params) {
		Mojo.Log.info('------------------------WizardAssistant:initialize:' + Object.toJSON(params));
		this.sceneResults = {};
		this.emailAddress = {value:""};
		this.password = {value:""};
		this.loggingIn = false;
		this.MojoRequest = null;
		this.params = params || {};
		
		if (!this.params.title)
			this.params.title = $L("Add an account");
			
		// Prepopulate the email address, if one was provided
		if (this.params.emailAddress)
			this.emailAddress.value = this.params.emailAddress; 
		if (this.params.noAccounts) {
			this.noAccounts = true; 
		}
	},

	setup: function() {
		Mojo.Log.info('------------------------WizardAssistant:setup');

		this.controller.setupWidget('wizard-email-address', this.emailAddressAttributes, this.emailAddress);
		this.controller.setupWidget('wizard-password', this.passwordAttributes, this.password);
		this.signInButtonModel = {buttonClass:'primary', buttonLabel:$L('Sign In'), disabled:true};
		this.controller.setupWidget('create-account-button', {type: Mojo.Widget.activityButton}, this.signInButtonModel);
		this.manualSetupButtonModel = {buttonClass:'secondary', buttonLabel:$L('Manual Setup'), disabled:false};
		this.controller.setupWidget('manual-setup-button', {}, this.manualSetupButtonModel);
		
		this.controller.listen('create-account-button', Mojo.Event.tap, this.createAccount.bind(this));
		this.controller.listen('manual-setup-button', Mojo.Event.tap, this.manualSetup.bind(this));
		Mojo.Event.listen(this.controller.sceneElement, Mojo.Event.propertyChange, this.handlePropertyChange.bindAsEventListener(this), true);
		this.emailField = this.controller.get('wizard-email-address');
		this.passwordField = this.controller.get('wizard-password');
		this.manualSetupButton = this.controller.get('manual-setup-button');
		this.signInButton = this.controller.get('create-account-button');
		
		// Set the form title
		this.controller.get('header').update(this.params.title);
		if (this.params.protocol)
			this.controller.get('title-icon').addClassName("account-icon " + this.params.protocol.toLowerCase());
		
		// Setup the menu
		this.manualSetupMenuItem = {label:$L('Manual Setup'), command:'email-manual-setup'};
		this.appMenuModel = {items:[this.manualSetupMenuItem]};
		this.controller.setupWidget(Mojo.Menu.appMenu, {}, this.appMenuModel);
	},

	activate: function(result) {
		CreateAssistant.logAccountDetails('------------------------WizardAssistant:activate=', result);
		// {"action": "back"} for back
		// {"action": "create"} for success
		// undefined for launch
		if (result && result.action === "create") {
			// The Manaual Account setup was successful. Tell the AccountManager to use aboutToActivate() and pop this scene
			if (this.params.aboutToActivateCallback !== undefined) {
				this.params.aboutToActivateCallback(true);
			}
			this.controller.stageController.popScene(result);
			return;
		}
		// Show the "Sign in" button without the spinner
		this.setButtonState(false);
		
		// If there is an email address, set the focus on the password field
		if (this.emailAddress.value)
			this.passwordField.mojo.focus();
		else
			this.emailField.mojo.focus();
	},

	deactivate: function() {
		Mojo.Log.info('------------------------WizardAssistant:deactivate');
	},
	
	handlePropertyChange: function(event) {
		// Ignore this event if we're loggin in
		if (this.loggingIn)
			return;

		// A character was entered.  Enable or disable the "Sign In" button based on valid data
		if (this.signInButtonModel.disabled && this.isValidEmailAddress(this.emailAddress.value) && this.password.value.length > 0) {
			this.signInButtonModel.disabled = false;
			this.controller.modelChanged(this.signInButtonModel);
		} 
		else if (!this.signInButtonModel.disabled && (!this.isValidEmailAddress(this.emailAddress.value) || this.password.value.length == 0)) {
			this.signInButtonModel.disabled = true;
			this.controller.modelChanged(this.signInButtonModel);
		} 
		
		// If the password field has focus and Enter is pressed then simulate tapping on "Sign In"
		if (event && Mojo.Char.isEnterKey(event.originalEvent.keyCode)) {
			// If the submit button is enabled then create the account
			if (this.signInButtonModel.disabled == false) {
				this.passwordField.blur();
				this.createAccount();
				Event.stop(event);
			}
			else {
				this.emailField.mojo.focus();
			}
		}
	},

	setButtonState: function(loggingIn) {
		Mojo.Log.info('---- setButtonState: logging in=' + loggingIn);
		this.loggingIn = loggingIn || false;
		if (this.loggingIn) {
			// Button is always disabled when signing in
			this.signInButtonModel.buttonLabel = $L('Signing In...');
			this.signInButtonModel.disabled = true;
			this.controller.modelChanged(this.signInButtonModel);
			this.signInButton.mojo.activate();
			
			// Disable the username and password fields
			this.emailAddress.disabled = true;
			this.controller.modelChanged(this.emailAddress);
			this.password.disabled = true;
			this.controller.modelChanged(this.password);
			
			// Disable the Manual Setup button
			this.manualSetupButtonModel.disabled = true;
			this.controller.modelChanged(this.manualSetupButtonModel);
		}
		else {
			// Button should be enabled only if user name/password are valid
			this.handlePropertyChange(null);
			this.signInButtonModel.buttonLabel = $L('Sign In');
			this.controller.modelChanged(this.signInButtonModel);
			this.signInButton.mojo.deactivate();

			// Enable the username and password fields
			this.emailAddress.disabled = false;
			this.controller.modelChanged(this.emailAddress);
			this.password.disabled = false;
			this.controller.modelChanged(this.password);

			// Enable the Manual Setup button
			this.manualSetupButtonModel.disabled = false;
			this.controller.modelChanged(this.manualSetupButtonModel);
		}
	},
	
	isValidEmailAddress: function(emailAddress) {
//		Mojo.Log.info('---- isValidEmailAddress: ' + emailAddress);
		var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.\@])+\.([A-Za-z]{2,6}) *$/;
		if (reg.test(emailAddress))
			return true;
//		Mojo.Log.info('---- isValidEmailAddress: NOT VALID' + emailAddress);
		return false;
	},

	createAccount: function() {
		Mojo.Log.info("---- createAccount: email=" + this.emailAddress.value);
		
		// If setting up an EAS account, and this isn't a Palm.com account then go straight to the Manual Setup scene
		if (this.params.protocol === "EAS" && !this.emailAddress.value.include('@palm.com')) {
			this.createError({errorCode: 999});
			return;
		}
		
		if (this.loggingIn) {
			// User wants to cancel operation
			this.setButtonState(false);
			// Cancel the service call
			this.MojoRequest.cancel();
			return;
		}

		// Change the button to "Logging In..."
		this.setButtonState(true);

		// Send the information to the Account Wizard
		this.MojoRequest = new Mojo.Service.Request(EmailAccount.identifier, {
			method: 'accountWizard',
			parameters: {email: this.emailAddress.value, password: this.password.value},
			onSuccess: this.createSuccess.bind(this),
			onFailure: this.createError.bind(this),
		});
	},

	createSuccess: function() {
		Mojo.Log.info("---- createSuccess");
		this.sceneResults.action = 'create';
		this.popScene();
	},

	// After setting up EAS security policies, call this to create the account without validating
	// Unfortunately the names don't really match up, so we need to fix them up
	forceEasSetup: function(setupDetails) {
		if(setupDetails.protocol != "EAS") return;
		
		var manualSettings = {}
		manualSettings.dontValidate = true;
		manualSettings.type = setupDetails.protocol;
		manualSettings.host = setupDetails.server;
		
		manualSettings.login = setupDetails.username;
		manualSettings.domain = "";

		manualSettings.password = this.password.value;
		manualSettings.address = this.emailAddress.value;
		
		this.MojoRequest = new Mojo.Service.Request(EmailAccount.identifier, {
			method: 'accountCreateManual',
			parameters: manualSettings,
			onSuccess: this.createSuccess.bind(this),
			onFailure: (function (err) {
				EmailAccount.DisplayAccountSetupFailure(this.controller, err.errorCode, err.errorText, true, (this.accountDetails.type === "EAS"));
			}).bind(this)
		});
	},

	createError: function(err) {
		Mojo.Log.info("---- createError error="+$H(err).inspect());

		// Set the button state to "Sign In"
		this.setButtonState(false);
		
		var settings = err.setupDetails;
		
		if(err.errorCode == 502 && settings && settings.protocol === "EAS") {
			SecuritypolicyAssistant.handlePasswordPolicy(this.controller, this.emailAddress.value, this.forceEasSetup.bind(this, settings), Mojo.doNothing);
			return;
		}

		// Show the error dialog, if this is somthing the user can fix
		var msg = EmailAccount.DisplayAccountSetupFailure(this.controller, err.errorCode, err.errorText, false, false);

		// If the inbound settings worked then save them so that they can be used for Manual Setup
		if (settings && settings.protocol) 
			Object.extend(this.params, settings);

		// Is there a message to be displayed to the user?
		if (msg) {
			// Should the "Retry" dialog be shown?
			if (msg.retry)
				this.showRetryDialog(msg.title, msg.text);

			// Enable the "Manual Setup" button for some failure cases
			switch (parseInt(err.errorCode)) {
				case 15: // SSL Error
				case 50: // Wizard unable to validate known ISP
				case 51: // Wizard unable to auto-detect ISP settings
				case 101: // Wizard setup login error
					this.manualSetupButton.show();
			}
		}
		else {
			// The error isn't something the user can fix.  Send them to the advanced screen
			// If an inbound or outbound server was validated, pass on the validated settings to the account wizard
			this.manualSetup();
		}
	},
	
	manualSetup: function() {
		// The use wants to setup their account manually
		Mojo.Log.info("---- manualSetup");
		if (this.controller.stageController.topScene().sceneName !== 'create') {
			// Pass as much information to the Manual Setup scene as possible
			this.params.edit = false;
			this.params.password = this.password.value,
			this.params.email = this.emailAddress.value
			CreateAssistant.logAccountDetails("---- manualSetup: ", this.params);
			this.controller.stageController.pushScene('create', this.params);
		}
	},

	showRetryDialog: function(title, text) {
		this.controller.showAlertDialog({
			onChoose: function(value) { this.handleRetrySelection(value); },
			title: title,
			preventCancel: true,
			message: text,
			choices: [
				{label: $L("Retry"), value: 'retry',  type: 'affirmative'},
				{label: $L("OK"),   value: 'done', type: 'dismiss'}
			]
		});
	},

	handleRetrySelection: function(value) {
		if (value === 'done') {
			this.emailField.mojo.focus();
		} else {
			// Retry the settings
			Mojo.Log.info("Retrying settings ...");
			this.createAccount();
		}
	},
	
	/*
	 * Handle menu commands
	 */
	handleCommand: function(event) {
		if (event.type == Mojo.Event.commandEnable) {
			if (event.command === Mojo.Menu.helpCmd)
				event.stopPropagation();
		}
		else if (event.type == Mojo.Event.command) {
			switch (event.command) {
				case this.manualSetupMenuItem.command:
					this.manualSetup();
					break;

				case Mojo.Menu.helpCmd:
					MenuController.showHelp();
					break;
			}
		}
		else if(event.type == Mojo.Event.back) {
			event.stop();
			this.sceneResults.action = 'back';
			this.popScene();
		}
	},	
	
	popScene: function() {
		Mojo.Log.info("WizardAssistant results=", $H(this.sceneResults).inspect());
		
		if (this.sceneResults) {
			if (this.sceneResults.action === "back" && this.noAccounts) {
				// nothing to pop to. Minimize the scene.
				Mojo.Controller.getAppController().deactivate();
				return;
			} else if (this.sceneResults.action === "create") {
				if (this.params.aboutToActivateCallback !== undefined) {
					this.params.aboutToActivateCallback(true);
				}
			}
		} 
		this.controller.stageController.popScene(this.sceneResults);
	},

	//
	// Attributes for all of the Mojo widgets
	//
	emailAddressAttributes: {
		textReplacement: false,
		maxLength: 128,
		focus: true,
		acceptBack: true,
		changeOnKeyPress: true,
	},

	passwordAttributes: {
		focusMode: Mojo.Widget.focusSelectMode,
		textReplacement: false,
		maxLength: 64,
		focus: false,
		requiresEnterKey: true,
		acceptBack: true,
		changeOnKeyPress: true,
	},
});



