/* Copyright 2009 Palm, Inc.  All rights reserved. */


function AppAssistant(appController) {
	// This is primarily to load the email depot so it doesn't need to be loaded later
	this.depot = EmailAppDepot.getDepot();
	// Send list of localized strings to the service.
	ServiceStrings.sendLocalizedStrings();
	// Startup NotificationAssistant
	this.notificationAssistant = new NotificationAssistant(appController);

	// this is used to debounce the launch requests in case the user impatiently
	// taps on a banner notification
	this.debounceIds = {};

	MenuController.setupTextColorMenu();
}


AppAssistant.openEmailStage = function openEmailStage(f, splashImageName) {
	Mojo.Menu.prefsItem.label = $L("Preferences & Accounts");
	Mojo.Controller.getAppController().createStageWithCallback({name: "email", lightweight: Mojo.Controller.appInfo.lwStages, splashBackgroundName: splashImageName}, f);
};

AppAssistant.focusEmailStage = function focusEmailStage() {
	var emailStageController = Mojo.Controller.appController.getStageController("email");
	if (emailStageController) {
		emailStageController.activate();
	}
};

AppAssistant.composeStageId = 0;
AppAssistant.openComposeStage = function openComposeStage(email, composeReadyFunc) {
	// Ensure the stage name is unique for each compose stage
	var createStage = function(stageName) {
		// "nocache:true" tells sysmanager to not use the card caching strategy on compose cards
		var params = {
			name: stageName,
			htmlFileName: 'compose',
			lightweight: Mojo.Controller.appInfo.lwStages,
			nocache: true,
			splashBackgroundName: 'images/splash-email-compose.png'
		};
		var callback = function(stageController) {
			stageController.pushScene('compose', email, stageName, composeReadyFunc);
		};
		Mojo.Controller.getAppController().createStageWithCallback(params, callback);
	};
	AppAssistant.composeStageId++;
	createStage("compose"+AppAssistant.composeStageId);
};

AppAssistant.prototype.clearDebounce = function(debounce) {
	if (debounce) {
		delete this.debounceIds[debounce];
	} else {
		Mojo.Log.error("AppAssistant.clearDebounce got debounce=", debounce);
	}
};

AppAssistant.prototype.handleLaunch = function(params) {
	var launchHandler;
	// Complain if the params claim to be a string
	if (!params) {
		params = {};
	} else if (Object.isString(params) && params.length > 0) {
		Mojo.Log.error("WARNING: received string params \"" + params + "\". Attempting conversion.");
		try {
			params = params.toJSON();		
		} catch (e) {
			Mojo.Log.error("couldn't convert params to JSON, ignoring params");
			params = {};
		}
	}
	Mojo.Log.info("email handleLaunch with params " + Object.toJSON(params));

	// this is the boot-time launch--no ui requested--so just return
	if (params.launchedAtBoot === true) {
		return;
	}

	if (params.debounce !== undefined) {
		if (this.debounceIds[params.debounce]) {
			//Mojo.Log.error("Ingoring", params.debounce, "because it happened already");
			return;
		} else {
			this.debounceIds[params.debounce] = params.debounce;
		}
	}

	if (this.depot.isFirstUseComplete() !== true) {
		launchHandler = new FirstUseLaunchHandler(this, params);
	} else {
		launchHandler = new LaunchHandler(this, params);
	}
	launchHandler.handleLaunch();
};

LaunchHandler = Class.create({
	initialize: function(appAssistant, launchParameters) {
		this.appAssistant = appAssistant;
		this.notificationAssistant = appAssistant.notificationAssistant;		
		this.launchParameters = launchParameters;
	},
	
	isCompose: function() {
		var params = this.launchParameters;
		return (params.uri || params.target || params.recipients || params.summary || params.text || params.attachments);
	},
	
	handleLaunch: function() {
		var params = this.launchParameters;
		if (params.securityPolicyError) {
			this.handleSecurityPolicyError(params);
		} else if (params.certificateError) {
			this.handleCertificateError(params);
		} else if (params.emailId) {
			this.handleShowMessage();
		} else if (params.folderInfo) {
			this.handleShowFolder();
		} else if (this.isCompose()) {
			this.handleCompose();
		} else if (params.draftId) {
			this.handleShowDraft();
		} else if (params.editAccount && params.account) {
			this.handleEditAccount();
		} else if (params.reminderPersonId) { 
			this.handleContact(params);
		} else if (params.carrierSignature) {
			this.handleSetCarrierSignature(params);
		} else {
			this.handleDefault();
		}
	},
	
	handleCompose: function() {
		var params = this.launchParameters;
		var email = new Email();
		if (params.uri) {
			email.evalMailto(params.uri);
			email.highlightBody = true;
		} else if (params.target) {
			email.evalMailto(params.target);
			email.highlightBody = true;
		} else {
			email.evalParams(params);
			if (email.recipients && email.recipients.length > 0) {
				// Since there are recipients, set selection to email body
				email.highlightBody = true;
				email.recipients.each(function(r) {
					if (!r.type) {
						Mojo.Log.warn("WARNING: email recipient has no 'type', using 'email'");
						r.type = 'email';
					}
					if (r.role == undefined) {
						Mojo.Log.warn("WARNING: email recipient has no 'role', using roleTo");
						r.role = EmailRecipient.roleTo;
					}
				});
			}
		}

		AppAssistant.openComposeStage(email);
	},
	
	handleCertificateError : function(resp) {
		var showCertificateError = function (stageController) {
			var sceneController = stageController.topScene();
			var message = $L("#{error}<br><br>Contact your IT department or email provider to fix this issue.").interpolate({
				error: EmailAccount.CertificateErrorToMessage(resp.reason)});
			
			sceneController.showAlertDialog({
				title: $L("SSL certificate error"),
				message: message,
				choices: [{ label: $L('OK'), value: 'dismiss', type: 'dismiss' }]
			});
		}
		
		var emailStageController = Mojo.Controller.appController.getStageController("email");
		
		if(emailStageController) {
			showCertificateError(emailStageController);
			emailStageController.activate();
		} else {
			f = function(stageController) {
				Mojo.Log.breadcrumb("Stage controller is " + stageController);
				stageController.pushScene('accounts');
				showCertificateError.delay(1, stageController);
			};
			
			AppAssistant.openEmailStage(f);
		};
	},
	
	handleSecurityPolicyError: function(params) {
		var showDialogFunc = function(stageController) {
			var controller = stageController.topScene();
			controller.showAlertDialog({
				title:$L('Security policy error'),
				message:$L('The account #{accountName} is disabled because security policies cannot be set.').interpolate(params),
				choices:[
					{label:$L("Leave it disabled"), value:'cancel', type:'secondary'},
					{label:$L("Remove account"), value:'remove'}
				],
				onChoose: function(value) {
					//TODO: this is not a great user experience, but will get the job done given the time constraints.
					// A preferable solution would be to add a spinner while the account is being deleted or send the
					//  user to the accountpreferences assistant and invoke the Remove Account button.
					if (value === 'remove') {
						EmailAccount.deleteAccount(controller, params.account, Mojo.doNothing, Mojo.doNothing);
						Mojo.Controller.getAppController().assistant.notificationAssistant.clear(params.account);
				
						var sceneStack = stageController.getScenes();
						if (sceneStack) {
							var stackSize = sceneStack.size();
							for (var stackIndex = 0; stackIndex < stackSize; stackIndex++) {
								var scene = sceneStack[stackIndex];
								if (scene.assistant.accountDeletedNotification !== undefined) {
									scene.assistant.accountDeletedNotification(params.account);
								}
							}
						}
					}
				}
			});
		}

		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (emailStageController) {
			showDialogFunc(emailStageController);
			emailStageController.activate();
		} else {
			f = function(stageController) {
				stageController.pushScene('accounts');
				showDialogFunc.delay(1, stageController);
			};
			AppAssistant.openEmailStage(f);
		}

	},
	
	handleShowMessage: function() {
		var f;
		var params = this.launchParameters;
		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (emailStageController) {
			// Don't want the accounts scene's activate method to clear all notifications
			// just because it was temporarily popped to.
			this.notificationAssistant.setIgnoreClears(true);
			emailStageController.popScenesTo('accounts', true);
			this.notificationAssistant.setIgnoreClears(false);

			// push the folder scene if it was specified and indicate it should delay list setup
			// because the message scene is being pushed on top of it.
			if (params.folderInfo) {
				emailStageController.pushScene('list', params.folderInfo, true);
			}
			// Tell the message scene to focus the stage once it is activated
			emailStageController.pushScene('message', params.emailId, undefined, true);
		} else {
			f = function(stageController) {
				stageController.pushScene('accounts');
				// push the folder scene if it was specified and indicate it should delay list setup
				// because the message scene is being pushed on top of it.
				if (params.folderInfo) {
					stageController.pushScene('list', params.folderInfo, true);
				}
				stageController.pushScene('message', params.emailId);
			};
			AppAssistant.openEmailStage(f, 'images/splash-email-message.png');
		}
	},
	
	handleShowFolder: function() {
		var f;
		var params = this.launchParameters;
		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (emailStageController) {
			// Don't want the accounts scene's activate method to clear all notifications
			this.notificationAssistant.setIgnoreClears(true);
			emailStageController.popScenesTo('accounts', true);
			this.notificationAssistant.setIgnoreClears(false);
			emailStageController.pushScene('list', params.folderInfo);
			// Delayed by 500ms to allow the scene to setup before switch to email app
			AppAssistant.focusEmailStage.delay(0.5);
		} else {
			f = function(stageController) {
				stageController.pushScene('accounts');
				stageController.pushScene('list', params.folderInfo);
			};
			AppAssistant.openEmailStage(f, 'images/splash-email-list.png');
		}	
	},
	
	handleShowDraft: function() {
		var params = this.launchParameters;
		var appAssistant = this.appAssistant, launchRequest;
		var openDraftMessage = function(response) {
			EmailRecipient.addAddressPickerFields(response.recipients);
			// needs to escape summary's HTML because compose scene unescape 
			// summary. 
			response.summary = response.summary.escapeHTML();
			// load email text from text URI 
			response.text = palmGetResource(response.text);
			appAssistant.handleLaunch(response);
			launchRequest = undefined;
		}
		launchRequest = new Mojo.Service.Request(Message.identifier, {
			method: 'messageDetail',
			parameters: { 'message':params.draftId },
			onSuccess: openDraftMessage
		});
	},

	handleEditAccount: function() {
		var f;
		var params = this.launchParameters;
		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (emailStageController) {
			emailStageController.pushScene('create', { edit:true, id:params.account, type:"email" });
			emailStageController.activate();
		} else {
			f = function(stageController) {
				stageController.pushScene('accounts');
				stageController.pushScene('create', { edit:true, id:params.account, type:"email" });
			};
			AppAssistant.openEmailStage(f);
		}
	},
	
	handleContact: function(params) {
		Mojo.Log.info("handleContact params=%j", params);
		new Mojo.Service.Request("palm://com.palm.applicationManager", {
			method: "open",
			parameters: {
				id: "com.palm.app.contacts",
				params: {
					launchType: "reminder",
					personId: params.reminderPersonId
				}
			}
		});
		this.appAssistant.controller.closeStage(params.stageName);
	},
	
	handleSetCarrierSignature: function(params) {
		Mojo.Log.breadcrumb("Setting carrier signature with params=%j", params);
		var depot = EmailAppDepot.getDepot();
		depot.setDefaultSignature(params.carrierSignature);
		ServiceStrings.sendLocalizedStrings();
	},

	handleDefault: function() {
		var f;
		var params = this.launchParameters;
		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (emailStageController) {
			// If debounce property is set then this was a dashboard launch so
			// go to the main scene.
			if (params.debounce !== undefined) {
				emailStageController.popScenesTo('accounts');
			}
			emailStageController.activate();
		} else {
			f = function(stageController) {
				stageController.pushScene('accounts');
			};
			AppAssistant.openEmailStage(f);
		}
		
	}
});

FirstUseLaunchHandler = Class.create(LaunchHandler, {
	handleCompose: function($super) {
		var depot = EmailAppDepot.getDepot();
		if (depot.accounts !== undefined &&
		    depot.accounts.list !== undefined &&
		    depot.accounts.list.length > 0) {
			$super();
		} else {
			this.handleDefault();
		}
	},
	
	_showFirstUse: function() {
		var emailStageController = this.appAssistant.controller.getStageController("email");
		if (emailStageController) {
			emailStageController.activate();
		} else {
			var f = this._getFirstUseFunction(emailStageController);
			AppAssistant.openEmailStage(f);
		}
	},

	handleShowMessage: function() {
		this._showFirstUse();
	},
	handleShowFolder: function() {
		this._showFirstUse();
	},
	handleShowDraft: function() {
		Mojo.Log.error("FirstUseLaunchHandler.handleShowDraft invoked. How is that possible?");
		this._showFirstUse();
	},
	handleEditAccount: function() {
		this._showFirstUse();
	},

	handleDefault: function($super) {
		var f;
		var params;
		var appController = this.appAssistant.controller;
		var emailStageController = appController.getStageController("email");
		if (this.isCompose()) {
			params = this.launchParameters;
		}
		
		if (emailStageController) {
			if  (params && this.isCompose()) {
				emailStageController.delegateToSceneAssistant("handleCompose", params);
			}
			emailStageController.activate();
		} else {
			f = this._getFirstUseFunction(emailStageController, params);
			AppAssistant.openEmailStage(f);
		}
	},
	
	_getFirstUseFunction: function(controller, params) {
		var firstUseAttrs = {
			sceneName: 'email_firstlaunch',
			title: $L("Your Email Accounts"),
			iconClass:"first-launch-icon email",
			assistant: new FirstUseAssistant(params),
			hideAccountTypesList: true
		};
		var firstUseModel = {};
		
		var f = function(controller) {
			controller.showFirstLaunchScene(firstUseAttrs, firstUseModel);
		};
		return f;
	}
	
});

/*
 * Utility method to get a scene assistant within the email app.
 * If the assistant requested has not been initialized, the method
 * will reuturn null.
 */
AppAssistant.getSceneAssistant = function(sceneName){
	if (!sceneName) {
		return undefined;
	}
	var emailStageController = Mojo.Controller.getAppController().getStageController("email");
	if (!emailStageController) {
		return undefined;
	} 
    var scenes = emailStageController.getScenes();
    for (var i = 0; i < scenes.length; ++i) {
        if (scenes[i].sceneName === sceneName) {
            return scenes[i].assistant;
        }
    }    
    return undefined;
};

Mojo.Log.breadcrumb = function(m) {
	// Want these to log out at the same level as error so for now.
	// Not technically errors, so prefix with "(not an error)"
	Mojo.Log.error("(not an error) " + m);
};

/** method to allow setup of a widget after a scene's setup method has completed.
 * Note that in order to use, the target div must not have any 'x-mojo-element' 
 * attribute defined.
 * @param {Object} controller scene controller to use
 * @param {Object} id - div id for widget
 * @param {Object} widgetType - x-mojo-element type. ie: 'List'
 * @param {Object} attributes - json obj of editable attributes for widget
 * @param {Object} model - background model for use by widget
 */ 
AppAssistant.lazySetupWidget = function (controller, id, widgetType, attributes, model) {
	var w = controller.get(id);
	w.setAttribute("x-mojo-element", widgetType);
	controller.setupWidget(id, attributes, model);
	controller.instantiateChildWidgets(w.parentNode);
}; 

