/*
 * Messaging App Launch Parameters:
 * parameters : {
 *   personId : the personId that you want to open a chat with
 *   contactPointId : contact Point id (which profile or transport)
 *   messageText : the text of the message to be pre-populated
 *   composeAddress : the phone number to pre-populate the compose view addressing widget
 *                    TODO: this needs to be expanded to support multiple addresses and different address types
 *   attachment : the URL of the image file to be pre-populated in the view
 *   chatThreadId : the chat thread ID to launch the chat view with (used in notifications)
 * }
 
Copyright 2009 Palm, Inc.  All rights reserved.

*/
var MainStageName = "messaging";
var DashboardMessageStageName = "messaging-message-dashboard";
var DashboardErrorStageName = "messaging-error-dashboard";
var DashboardSendErrorStageName = "messaging-send-error-dashboard";
var DashboardReminderStageName = "messaging-reminder-dashboard";
var DashboardClass0StageName = "messaging-class0Alert-dashboard";
var Class0AlertStageName = "messaging-class0Alert-stage";

var AppAssistant = Class.create({
	initialize: function(appController){
		this.appController = appController;
		this.appController.Messaging = new Messaging();
		this.appController.notificationAssistant = new NotificationAssistant(appController); // start the notification assistant
		this.serviceRequestHelper = new ServiceRequestHelper();
		this.appController.serviceRequest = this.serviceRequestHelper.serviceRequest.bind(this.serviceRequestHelper);
		
		this.considerForNotification = appController.notificationAssistant.considerForNotification.bind(appController.notificationAssistant);
			
	},
	
	handleLaunch: function(param){
		Mojo.Log.info("*** Messaging App handleLaunch");
		var launchParams = {};
		try {
			launchParams = PalmSystem.launchParams.evalJSON(true);
		} catch (err) {
			Mojo.Log.info("Messaging App: No launch params");
		}
		// suppress launch the first time this is called (headless window on boot)
		if (launchParams.launchedAtBoot) {
			return;
		}

		var stageController = this.controller.getStageController(MainStageName);
		
		if (launchParams.clearBanner) {
			PalmSystem.clearBannerMessages();
		}
		if (launchParams.clearErrorDashboard) {
			Mojo.Controller.appController.notificationAssistant.clearErrorDashboard();
		}
		if (launchParams.clearSentMessageErrorDashboard) {
			Mojo.Controller.appController.notificationAssistant.clearSendErrorDashboard();
		}
		
		// Launching chatview with a chatThreadId (Messaging notification -> messaging)
		if (launchParams.chatThreadId) {
			this.launchChatWithId(stageController, launchParams.chatThreadId);			
	 	// Launching chatview with an address (phone number)
		} else if (!launchParams.personId && launchParams.address) {
			this.launchChatWithAddress(stageController,launchParams.address, launchParams.serviceName); // serviceName is only required for IM
 		// Launching chatview with a person ID + contactPointId (Contacts -> Messaging)
		} else if (launchParams.personId && launchParams.contactPointId) {
			this.launchChatWithPerson(stageController,launchParams.personId, launchParams.contactPointId, launchParams.address, launchParams.type, launchParams.serviceName);
 		// Launching composeview with message/attachment/composeAddress
		} else if (launchParams.messageText || launchParams.attachment || launchParams.composeAddress || (launchParams.composeRecipients && launchParams.composeRecipients.length)) {
			
			this.launchCompose(stageController,launchParams);
		// Launch listview - make sure the listview is the current scene, don't just focus the window
		} else if (launchParams.launchListView) {
			this.launchListView(stageController,launchParams.forceListView);
		/*
		 * <reminder code>
		 */
		} else if (launchParams.reminderPersonId) {
			this.handleReminder(launchParams.reminderPersonId);
		/*
		 * </reminder code>
		 */	
		} else if (launchParams.target !== undefined) {
			this.handleTargetParam(launchParams.target, stageController);
		} else {
			this.launchMessaging(stageController);
		}		
	},
	
	launchChatWithId: function(stageController, chatThreadId) {
		if (stageController) {			
			// Don't pop/push if the chat we want is already open
			if (this.isChatOpenAndWillFocusOnly(stageController, chatThreadId)) {
				return;
			}
			
			var params = {
				focusWindow: true
			};			
			this.addListViewClearBadgeForChatFnToParams(params,chatThreadId);				
			stageController.popScenesTo("listview");
			stageController.pushScene("chatview", chatThreadId, params);
		} else {
			var afterCreate = function(stageController){
				stageController.pushScene("chatview", chatThreadId, {
					focusWindow: true
				});
			};
			this.createWindow(afterCreate, 'images/splash-messaging-chatview.png');
		}		
	},
	
	launchChatWithAddress: function(stageController, address, serviceName) {
		this.createChatForAddressRequest = MessagingMojoService.createChatForAddress(address, serviceName, function(resp){
			if (stageController) {					
				// Don't pop/push if the chat we want is already open
				// Passing the contactPointId will cause the transport picker to be re-rendered					
				if (this.isChatOpenAndWillFocusOnly(stageController, resp.chatThreadId)) 
					return;
					
				var params = {
					focusWindow: true
				};
				this.addListViewClearBadgeForChatFnToParams(params, resp.chatThreadId);				
				stageController.popScenesTo("listview", {});
				stageController.pushScene("chatview", resp.chatThreadId, params);				
			} else {
				var afterCreate = function(stageController){
					stageController.pushScene("chatview", resp.chatThreadId, {
						focusWindow: true
					});
				};
				this.createWindow(afterCreate, 'images/splash-messaging-chatview.png');
			}
		}.bind(this));		
	},
	
	launchChatWithPerson: function(stageController, personId, contactPointId, address, type, serviceName) {
		Mojo.Log.info("launchChatWithPerson '%s', '%s', '%s', '%s', '%s'", personId, contactPointId, address, type, serviceName)
		var listviewParams = {};
		// if launching to an IM address, check to make sure we support that IM type
		// and that we have an account for that type
		if (type && serviceName) {
			type = type.toLowerCase();
			serviceName = serviceName.toLowerCase();
			if (type == "im") {
				var isSupported = this.appController.Messaging.isIMAccountTypeSupported(serviceName);
				if (!isSupported.returnValue) {
					var errorMessage = '';
					if (!isSupported.isSupportedType) {
						errorMessage = $L("The specified IM type is not supported.");
					} else if (!isSupported.hasAccount) {
						errorMessage = $L("You have not set up an IM account of this type.");
					}
					
					listviewParams.showDialog = {
						title: $L("Unable to launch chat"),
						message: errorMessage
					};
					if (!stageController) {
						this.pushListViewWithChunk(null,listviewParams);
					} else {
						listviewParams.focusWindow = true;
						stageController.activate();
						// Show the error dialog on whichever scene is on top
						stageController.topScene().showAlertDialog({
							title: listviewParams.showDialog.title,
							message: listviewParams.showDialog.message,
							choices: [{ label: $L("Close"), value: 'Close' }],
							onChoose: Mojo.doNothing
						});
					}
					return; // end here since we are not going to a chat anymore
				}
			}
		}
		this.getChatThreadIdRequest = MessagingMojoService.getChatThreadId(personId, contactPointId, this.handleGetChatThreadIdAndLaunchChat.bind(this, stageController, contactPointId, address, serviceName));		
	},
	
	handleGetChatThreadIdAndLaunchChat: function(stageController, contactPointId, address, serviceName, result) {
		var cleanAddress = MessagingUtils.cleanPhoneNumber(address);
		if (stageController) {
			// Don't pop/push if the chat we want is already open
			// Passing the contactPointId will cause the transport picker to be re-rendered
			if (this.isChatOpenAndWillFocusOnly(stageController, result.chatThreadId, contactPointId, cleanAddress, serviceName)) 
				return;
				
			var params = {
				contactPointId: contactPointId,
				address: cleanAddress,
				focusWindow: true
			};
			this.addListViewClearBadgeForChatFnToParams(params,result.chatThreadId);			
			stageController.popScenesTo("listview", {});
			stageController.pushScene("chatview", result.chatThreadId, params);
		} else {
			var afterCreate = function(stageController){
				stageController.pushScene("chatview", result.chatThreadId, {
					contactPointId: contactPointId,
					address: cleanAddress,
					focusWindow: true
				});
			};
			this.createWindow(afterCreate, 'images/splash-messaging-chatview.png');
		}
	},	
	
	handleTargetParam: function(uri, stageController) {
		var launchParams = MessagingUtils.parseTargetUri(uri);
		if (launchParams) {
			this.launchCompose(stageController, launchParams);
		}
	},
	
	/**
	 * 
	 * @param {Object} stageController
	 * @param {Object} messageText		// simple string
	 * @param {Object} attachment		// attachment path
	 * @param {Object} composeAddress 	// DEPRECATED
	 * @param {Object} serviceName		// DEPRECATED
	 * @param {Object} composeRecipients - expects the following:
	 *  [
	 *  	{
	 *  		"address": <phone number or IM>,
	 *  		"serviceName": <serviceName or domain> // only required for IM addresses
	 *  	}, ...
	 *  ]
	 */	

	launchCompose: function(stageController, composeParams) {
		composeParams.focusWindow =  true;
		
		if (stageController) {
			stageController.popScenesTo("listview", {});
			stageController.pushScene("compose", composeParams);
		} else {
			var afterCreate = function(stageController){
				stageController.pushScene("compose", composeParams);
			};
			this.createWindow(afterCreate, 'images/splash-messaging-chatview.png');
		}		
	},
	
	launchListView: function(stageController, forceListView) {
		if (stageController) {
			var listviewParams = {
				forceListView: forceListView,
				focusWindow: true 
			};		
			
			// List view is in the scene stack
			if(MessagingUtils.sceneExistsInStack(stageController,"listview")) {
				// check if the list view is already the current scene in the stack to avoid reloading it
				var topScene = stageController.topScene();
				if (topScene && topScene.sceneName == "listview") {
					var f = topScene.assistant.handleLaunchParams;
					if (f) {
						f.apply(topScene.assistant, [listviewParams]);
					}
				} else {
					stageController.popScenesTo("listview", listviewParams);
				}		
			} else { // have window, but listview does not exist in the scene stack
				this.getListChunk(this.appController, this.handlePushListViewWhenWindowExists.bind(this,stageController), forceListView);				
			}
		} else { 
			this.pushListViewWithChunk();
		}		
	},
	
	handlePushListViewWhenWindowExists: function(stageController, forceListView, result) {
		stageController.popScenesTo('listview');
		stageController.pushScene('listview',{forceListView:forceListView, listDataChunk:result});	
	},
	
	showFirstLaunch: function(stageController) {
		var firstLaunchAssistant = new PrefsFirstLaunchAssistant();
		var firstLaunchAttributes = {
			sceneName: 'firstLaunchScene',
			iconPath: 'icon.png',
			title: $L("Your Messaging accounts"),
			assistant: firstLaunchAssistant,
			accountTypes: this.appController.Messaging.transports.data,
			dividerFunction: function(itemModel) {
				return itemModel.divider || $L("Instant messaging");
			}
		};
		var firstLaunchModel = {
			accounts: firstLaunchAssistant.updateModel(this.appController.Messaging.IMAccounts.data)
		};
		stageController.showFirstLaunchScene(firstLaunchAttributes, firstLaunchModel);
	},

	launchMessaging: function(stageController) {
		if (stageController) {
			var listviewSceneAssistant = this.appController.Messaging.listviewSceneAssistant;
			if (listviewSceneAssistant) {
				listviewSceneAssistant.handleLaunchParams({focusWindow:true});
			}
			stageController.activate();
		} else {
			// If the app does not exist, then determine if this is first launch
			var isFirstLaunch = this.appController.Messaging.messagingPrefs.firstUseMode;
			if (isFirstLaunch) {
				this.createWindow(this.showFirstLaunch.bind(this));
			}
			else {
				// We will create the window after the top of the list is retrieved
				this.pushListViewWithChunk();
			}
		}		
	},
	
	/*
	 * <reminder code>
	 */
	handleReminder: function(personId) {
        this.controller.serviceRequest("palm://com.palm.applicationManager", {
            method: "open",
            parameters: {
                id: "com.palm.app.contacts",
                params: {
                    launchType: "reminder",
                    personId: personId
                }
            }
        });
		
		this.appController.notificationAssistant.clearReminderForPersonId(personId);
	},
	/*
	 * <reminder code>
	 */	
	
	pushListViewWithChunk: function(forceListView, params) {
		if(!params) {
			params = {};
		}
		if ((forceListView && forceListView == this.appController.Messaging.Views.BUDDY) || 
			(!forceListView && !this.appController.Messaging.messagingPrefs.isHistoryViewSelected && this.appController.Messaging.IMAccounts.data.count)) {
			this.getBuddyListChunk(this.appController,this.handleListDataAndPushListView.bind(this, this.appController.Messaging.Views.BUDDY, params));
		} else {
			this.getHistoryListChunk(this.appController,this.handleListDataAndPushListView.bind(this, this.appController.Messaging.Views.HISTORY, params));	
		}
	},
	
	// Used when popping the chat/compose views when no listview exists in the stack
	getListChunk: function(controller, callback, forceListView) {
		//if (!this.appController.Messaging.messagingPrefs.isHistoryViewSelected && this.appController.Messaging.IMAccounts.data.count) {
		if ((forceListView && forceListView == this.appController.Messaging.Views.BUDDY) || 
			(!forceListView && !this.appController.Messaging.messagingPrefs.isHistoryViewSelected && this.appController.Messaging.IMAccounts.data.count)) {		
			this.getBuddyListChunk(controller,callback.curry(this.appController.Messaging.Views.BUDDY));
		} else {
			this.getHistoryListChunk(controller,callback.curry(this.appController.Messaging.Views.HISTORY));	
		}		
	},
	
	getBuddyListChunk: function(controller, callback) {
		this.topListRequest = MessagingMojoService.getBuddyList(controller, null, callback, false, null, false, 0, 7);
	},
	
	getHistoryListChunk: function(controller, callback) {
		MessagingMojoService.getConversationList(controller, null, callback, false, null, false, 0, 7);
	},
	
	handleListDataAndPushListView: function(forceListView, params, result) {
		params.forceListView = forceListView;
		params.listDataChunk = result;
		var afterCreate = function(stageController){
			stageController.pushScene({
				name: 'listview',
				id: CONSTANTS.SCENE_ID_LISTVIEW
			}, params);
		};
		this.createWindow(afterCreate, 'images/splash-messaging-listview.png');		
	},
	
	// adds the clearListBadgeFn to the passed in params argument
	addListViewClearBadgeForChatFnToParams: function(params,chatThreadId) {
		var listviewSceneAssistant = this.appController.Messaging.listviewSceneAssistant;
		if (listviewSceneAssistant) {
			var clearListBadgeFn = listviewSceneAssistant.clearListBadgeForChatThreadId;
			if (clearListBadgeFn) {
				params.clearListBadgeFn = clearListBadgeFn.bind(listviewSceneAssistant,chatThreadId);
			}
		}
	},	
	
	createWindow: function(afterCreateWindowFn, imageName){
		Mojo.requireDefined(afterCreateWindowFn, "createWindow requires a callback function");
		var params = {
			name: MainStageName,
			lightweight: true,
			splashBackgroundName: imageName
		};
		this.controller.createStageWithCallback(params, afterCreateWindowFn);
	},		
		
	/**
	 * This calls considerForChatLaunch on the top scene in the stack.  If the current
	 * scene is the chatview and it is the same chat that we are trying to open, return true
	 * and focus the window.
	 * @param {Object} stageController
	 * @param {Object} chatThreadId
	 * @param {Object} contactPointId - specified when being launched to a specific transport
	 */
	isChatOpenAndWillFocusOnly: function(stageController, chatThreadId, contactPointId, address, serviceName){
		if (stageController && chatThreadId) {
			var topScene = stageController.topScene();
			if (topScene) {
				var f = topScene.assistant.considerForChatLaunch; // the chatview implements this method
				if (f) {
					var shouldLaunchChat = f.apply(topScene.assistant, [chatThreadId, contactPointId, address, serviceName]);
					// just focus the window if the chat is already visible
					if (!shouldLaunchChat) {
						stageController.activate();
						return true;
					}
				}
			}
		}
		return false;
	},

	handleCommand: function(event){	
		if (event.type == Mojo.Event.commandEnable) {
			if (event.command == Mojo.Menu.helpCmd) {
				event.stopPropagation();
			}
		}
		if (event.type == Mojo.Event.command) {
			if (event.command === Mojo.Menu.helpCmd) {
				MessagingMojoService.launchHelp(Mojo.Controller.appController.Messaging.helpUrl);
				event.stop();
			}
		}
	}	
});

// This function inspected by Mr. Stankypants
function StageAssistant(stageController){
}
