/*
 * setAccountPreferences()
 *  syncLookback
 *  syncFrequencyMins
 *  deleteFromServer
 *  deleteAfterSync
 *  replyTo
 *  signature
 *  realName
 *  useHtml
 *  acctName
 *  defaultAccountFlag
 *
 * setAccountDetails
 *  name - same at acctName?
 *  rootFolder
 *  port
 *  password
 *  smtpLogin
 *  smtpPassword
 *  smtpHost
 *  smtpSsl
 *  smtpPort
 
Copyright 2009 Palm, Inc.  All rights reserved.

*/
var EmailAccount = Class.create({ 
	initialize: function() {
		this.type = "POP3";
		this.address = '';
		
		this.host = '';
		this.login = '';
		this.domain = '';
		this.password = '';
		this.useSsl = false;
		this.port = 0;
		this.encryption = "none";
		
		this.smtpHost = '';
		this.smtpLogin = '';
		this.smtpPassword = '';
		this.useSmtpAuthentication = false;
		this.smtpSsl = false;
		this.smtpPort = 0;
		this.smtpEncryption = "none";
		
		this.syncLookback = 7;
		this.syncFrequencyMins = 0;
		this.useHTML = true;
		this.notify = true;
		this.playSound = true;
		this.proxyPassword = '';
	},

	clone: function(data) {
		Object.extend(this, data);
		if (this.id) {
			this.account = this.id;
		}

		if (this.syncLookback < 0) {
			this.syncLookback = 7;
		}
	},

	storeValueFromField: function(element) {
		this[element.name] = element.value;
	},
	
	setServerPort: function(override) {
		switch (this.type) {
		case "IMAP":
			if (override || !this.port || (this.port == 993 || this.port == 143)) {
				switch (this.encryption) {
					case "SSL": 
						this.port = 993;
						break;
					case "TLS":
						//TLS uses the same port as the one for none-SSL
					default: 
						this.port = 143;
						break;
				}
			}
			break;
		case "POP3":
			if (override || !this.port || (this.port == 995 || this.port == 110)) {
				switch (this.encryption) {
					case "SSL": 
						this.port = 995;
						break;
					case "TLS":
						//TLS uses the same port as the one for none-SSL
					default: 
						this.port = 110;
						break;
				}
			}
			break;
		}
	},

	setSmtpPort: function(override) {
		if (override || !this.smtpPort || (this.smtpPort == 465 || this.smtpPort == 25)) {
				switch (this.smtpEncryption) {
					case "SSL": 
						this.smtpPort = 465;
						break;
					case "TLS":
						//TLS uses the same port as the one for none-SSL
					default: 
						this.smtpPort = 25;
						break;
				}
		}
	},

	setDefaultPortsForServerType: function(override) {
		switch (this.type) {
		case "EAS":
			if (override || !this.port) {
				this.port = 443;
			}
			break;
		case "IMAP":
		case "POP3":
			this.setServerPort(override);
			this.setSmtpPort(override);
			break;
		}
	}
});

EmailAccount.identifier = 'palm://com.palm.mail';

// Error codes from MailService.java
EmailAccount.UNKNOWN_HOST = "1";
EmailAccount.MISSING_PARAMETER = "3";
EmailAccount.ILLEGAL_PARAMETER = "4";
EmailAccount.OBJECT_NOT_FOUND = "5";
EmailAccount.INVALID_EMAIL_ADDRESS = "6";
EmailAccount.INTERNAL_ERROR = "7";
EmailAccount.GENERIC_ERROR = "AcctMgr_Generic_Error";
	/* this account is locked */
EmailAccount.ACCOUNT_LOCKED = "AcctMgr_Account_Locked";
	/* account already exists (was found in the database) */
EmailAccount.ACCOUNT_EXISTS = "AcctMgr_Acct_Already_Exists";
	/* account couldn't be created due to an active record exception */
EmailAccount.ACCOUNT_NOT_CREATED = "AcctMgr_Acct_Not_Created";
	/* account couldn't be found in the database */
EmailAccount.ACCOUNT_NOT_FOUND = "AcctMgr_Account_Not_Found";
	/* folder couldn't be found in the database */
EmailAccount.FOLDER_NOT_FOUND = "AcctMgr_Folder_Not_Found";
	/* no login service exists for this account */
EmailAccount.NO_SETUP_SERVICE = "AcctMgr_No_Setup_Service";

	//AUTHENTICATION ERRORS:
	/* username is bad */
EmailAccount.AUTHENTICATION_BAD_USERNAME = "AcctMgr_Bad_Username";
	/* password is bad */
EmailAccount.AUTHENTICATION_BAD_PASSWORD = "AcctMgr_Bad_Password";
	/* either the username is bad or the password is bad */
EmailAccount.AUTHENTICATION_LOGIN_FAILED = "AcctMgr_Bad_Authentication";
	/* connection couldn't be made */
EmailAccount.AUTHENTICATION_CONNECTION_FAILED = "AcctMgr_Authentication_Connection_Failed";
	/* host name could not be resolved */
EmailAccount.AUTHENTICATION_UNKNOWN_HOST = "AcctMgr_Authentication_Unknown_Host";
	/* no network connection available */
EmailAccount.AUTHENTICATION_NETWORK_FAILED = "AcctMgr_Network_Error";
	/* host did not accept our request */
EmailAccount.AUTHENTICATION_BAD_REQUEST = "AcctMgr_Authentication_Bad_Request";


EmailAccount.getAccounts = function(sceneController, callback, failCallback) {
	sceneController.serviceRequest(Email.identifier, {
			method: 'accountList', // another example, if not done in the URL
			onSuccess: callback,
			onFailure: failCallback
		});
}

EmailAccount.subscribeAccounts = function(callback, failCallback) {
	var request = new Mojo.Service.Request(Email.identifier, {
			method: 'accountList',
	  		parameters: {'subscribe':true},
			onSuccess: callback,
			onFailure: failCallback
		});
	return request;
}

EmailAccount.getAccountDetails = function(sceneController, accountId, callback, failCallback) {
	sceneController.serviceRequest(Email.identifier, {
		method: 'accountDetails',
		parameters: {'account': accountId},
		onSuccess: callback,
		onFailure: failCallback
	});
}

EmailAccount.getAccountPreferences = function(sceneController, accountId, callback, failCallback) {
	sceneController.serviceRequest(Email.identifier, {
		method: 'accountPreferences',
		parameters: {'account': accountId},
		onSuccess: callback,
		onFailure: failCallback
	});
}

EmailAccount.saveAccountDetails = function(sceneController, params, callback, failCallback) {
	sceneController.serviceRequest(Email.identifier, {
		method: 'setAccountDetails',
		parameters: params,
		onSuccess: callback,
		onFailure: failCallback
	});
}

EmailAccount.saveAccountPreferences = function(sceneController, params, callback, failCallback) {
	// This is needed to convert the 'useHTML' property to a boolean because the ListSelector only 
	// uses numeric values in its choices, but the service interface is booleans.
	if (params.useHTML !== undefined) {
		params.useHTML = (params.useHTML > 0);
	}
	sceneController.serviceRequest(Email.identifier, {
	  method: 'setAccountPreferences',
	  parameters: params,
	  onSuccess: callback,
	  onFailure: failCallback
	});
}

EmailAccount.deleteAccount = function(sceneController, accountId, callback, failCallback) {
	Mojo.Log.info("EmailAccount.deleteAccount ", accountId);
	sceneController.serviceRequest('palm://com.palm.accounts', {
		method: 'deleteAccount',
		parameters: {
			service: 'EMAIL',
			accountId: accountId
		},
		onSuccess: callback,
		onFailure: failCallback
	});
}

EmailAccount.setAccountsOrder = function(sceneController, accountList, callback, failCallback) {
	sceneController.serviceRequest(Email.identifier, {
			method: 'accountOrderSet', // another example, if not done in the URL
			parameters: {'accounts': accountList},
			onSuccess: callback,
			onFailure: failCallback
		});
}

EmailAccount.getFullName = function(sceneController, callback) {
	sceneController.serviceRequest('palm://com.palm.systemservice', {
			method: 'getPreferences',
			parameters: {'keys': ['deviceName']},
			onSuccess: callback,
		});
}

EmailAccount.getFirstUseEmailAddress = function(callback) {
	var request = new Mojo.Service.Request('palm://com.palm.accountservices', {
			method: 'getAccountToken', 
			onSuccess: callback,
			onFailure: callback
		});
	return request;
}

EmailAccount.isNotSmartFolders = function(account) {
	return (account.originalLogin && account.originalLogin.length > 0);
}

EmailAccount.addStylingToSig = function(signature){
	// If the signature is empty or already has styling, just return it. Otherwise add the styling
	if (!signature || signature.startsWith('<div style="font-family: arial')) {
		return signature;
	} else {
		return '<div style="font-family: arial, sans-serif; font-size: 12px;color: #999999;">#{signature}</div><br>'.interpolate({
			signature: signature
		});
	}
}

EmailAccount.ErrCodeToString = function(err) {
	switch (err.errorCode) {
	case EmailAccount.UNKNOWN_HOST:
		return $L("Unknown host"); // This is not a fatal error since we can switch to manual mode

	case EmailAccount.MISSING_PARAMETER:
		return $L("One of the following is missing: login, password, host, or type.");

	case EmailAccount.INVALID_EMAIL_ADDRESS:
		return $L("Invalid email address");

	case EmailAccount.ACCOUNT_LOCKED:
		return $L("This account is locked");

	case EmailAccount.ACCOUNT_EXISTS:
		return $L("The account already exists");

	case EmailAccount.ACCOUNT_NOT_FOUND:
		return $L("the account does not yet exist");

	case EmailAccount.AUTHENTICATION_BAD_USERNAME:
		return $L("The login or username is bad");

	case EmailAccount.AUTHENTICATION_BAD_PASSWORD:
		return $L("The password is invalid");

	case EmailAccount.AUTHENTICATION_LOGIN_FAILED:
		return $L("Authentication failed. Check your login and password.");

	case EmailAccount.AUTHENTICATION_CONNECTION_FAILED:
		return $L("Could not connect or connection timed out");

	case EmailAccount.AUTHENTICATION_UNKNOWN_HOST:
		return $L("Host name cannot be resolved");

	case EmailAccount.AUTHENTICATION_NETWORK_FAILED:
		return $L("Network is currently unavailable");

	case EmailAccount.AUTHENTICATION_BAD_REQUEST:
		return $L("The host rejected your request");

	// TODO these should eventually be removed
	case EmailAccount.ILLEGAL_PARAMETER:
		return $L("Internal error: illegal parameter #{errorText}").interpolate(err);
	case EmailAccount.NO_SETUP_SERVICE:
	case EmailAccount.ACCOUNT_NOT_CREATED:
	case EmailAccount.FOLDER_NOT_FOUND:
	case EmailAccount.OBJECT_NOT_FOUND:
	case EmailAccount.INTERNAL_ERROR:
	case EmailAccount.GENERIC_ERROR:
		return $L("Internal error: #{errorText}").interpolate(err);
	
	default:
		return ("Unspecified error: #{errorCode} - #{errorText}").interpolate(err);
	}
}

/* Returns a user-readable SSL error description.
 * Eventually this should switch to using error codes for SSL.
 */
EmailAccount.CertificateErrorToMessage = function(text){
	if (text) {
		var results = text.match("^No name matching (.*) found$");
		
		if (results) {
			var params = {
				domainName: results[1].escapeHTML()
			};
			return $L("The server's security certificate is not valid for #{domainName}.").interpolate(params);
		}
	
		/* The other error strings should match the errors in OpenSSL verify(1) */
		switch (text) {
			case "certificate is not yet valid":
			case "certificate has expired":
				return $L("The server's security certificate has expired.");
				
			case "self signed certificate":
			case "self signed certificate in certificate chain":
			case "unable to get local issuer certificate":
			case "unable to verify the first certificate":
				return $L("The server's security certificate is not a trusted certificate.");
		}
	}
	
	return $L("The server's security certificate is invalid.");
}

/*
 * The error strings returned here correspond to the errors in AccountWizard.java
 */
EmailAccount.DisplayAccountSetupFailure = function(controller, err, serverMsg, isManualSetup, isEAS) {
	var msg = {};
	msg.title = $L("Unable to sign in");
	
	if (!err)
		err = '0';
	switch (parseInt(err)) {
		case 3  :	// Prompt the user to turn on WiFi		
					var params = {type: "data", onSuccess:EmailAccount.HandleWifiEnableResponse.bind(this, controller)};
					ConnectionWidget.connect(params, controller);
					return msg;
					
		case 5  :	// Duplicate account
					msg.title = $L("Duplicate account");
					msg.text = $L("An account using this email address already exists.");
					break;
		
		case 15 :	// SSL Error
					if (isEAS)
						msg.title = $L("Cannot connect to exchange server");
					msg.text = EmailAccount.CertificateErrorToMessage(serverMsg);
					break;
		
		case 50 :	// Wizard unable to validate known ISP (Shown in "Retry" dialog)
					msg.text = $L("Unable to connect to the mail server.  Try again later.");
					msg.retry = true;
					break;
					
		case 51 :	// Wizard unable to auto-detect ISP settings (Shown in "Retry" dialog)
					msg.text = $L("Unable to automatically set up your email account.");
					msg.retry = true;
					break;

		case 100:	// Manual setup login error
		case 101:	// Wizard setup login error
					if (serverMsg && serverMsg.length > 10) {
						msg.text = $L("Could not sign in to account.") + "<br><br>" + $L("The mail server responded:");
						// Format the message from the server
						msg.text += " <span class=\"server-message\">" + serverMsg.gsub(/.*(] |ERR | NO )/, '').escapeHTML() + "</span>";
					}
					else {
						if (err === 100)
							msg.text = $L("Your username or password is not correct.");
						else
							msg.text = $L("Your email address or password is not correct.");						
					}
					break;
					
		case 502:	// EAS Security policy error
					msg.title = $L("Unable to create account");
					msg.text = $L("The mail server requires security policies that are not supported.");
					break;

		default:
			// Must a message be displayed?
			if (isManualSetup) {
				// These message are only displayed if inbound settings failed to validate.  Outbound may or may
				// not be validated.  Regardless, the user needs to fix their inbound settings first
				if (err == 11)
					msg.text = $L("Unable to connect to incoming mail server.");
				else
					msg.text = $L("Unable to validate incoming mail server settings. Check the settings and try again.");
			}
	}
	
	
	if (!msg.text)
		return null;
	if (msg.retry)
		return msg;
	// Display the message now
	controller.showAlertDialog({
//		onChoose: function() {this.emailField.mojo.focus();},
		title: msg.title,
		message: msg.text,
		choices: [{label:$L('OK'), value:'dismiss', type:'dismiss'}]
	});
	
	return msg;
}


EmailAccount.HandleWifiEnableResponse = function(controller, response) {
	// If the user didn't turn on WiFi then show the Network Unavailable Dialog.
	Mojo.Log.info("---- HandleWifiEnableResponse msg=" + response);
	if (response != "WiFi-UserCancelled" && response != "WiFi-Enabled")
		return;
			
	controller.showAlertDialog({
		onChoose: function(value) {
					if (value == 'help') {
						// Launch Help.
						this.controller.serviceRequest("palm://com.palm.applicationManager", {
		 						method: "open",
		 						parameters:  {
  								id: 'com.palm.app.help',
  								params: {target: "no-network"}
								}});
					}
		},
		title: $L("No Internet Connection"),
		message: $L("You need an Internet connection to sign in to an account."),
		choices: [{label:$L('Help'), value:'help', type:'primary'},
				  {label:$L('OK'), value:'dismiss', type:'dismiss'}
				 ]
	});
}


EmailAccount.localizeAccountName = function (accountName) {
	if (!EmailAccount.DO_ACCOUNT_NAME_LOC) {
		return accountName;
	}
	return accountName.gsub(/Gmail/, EmailAccount.GMAIL);
}

// German Google Localization
EmailAccount.GMAIL = $L("Gmail");
EmailAccount.DO_ACCOUNT_NAME_LOC = EmailAccount.GMAIL !== 'Gmail';
