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

var AnnouncerAssistant = Class.create({
	
	initialize: function(appAssistant) {
	    QDLogger.log( "AnnouncerAssistant::initialize");
		this.missed = {};
		this.notifyCounter = 0;
		this.appControl = Mojo.Controller.getAppController();
		this.ignoreMissedAnnounce = false;
		this.smallCallStage = "smallcall";
		this.incomingPostponed = false;
		// ugh
		this.appAssistant = appAssistant;

		this.contacts = this.appAssistant.contacts; 
		
		this.lastIncomingStageName = "";
	},
	
	announce: function(windowName, smallIcon, single, icon, itemcount, title, message, iconCallback, messageCallback, timestamp) {
		QDLogger.log( "announce", windowName , icon , message);
		
		var stageProxy = this.appControl.getStageProxy(windowName);
		
		// if the window already exists, update message
		if (stageProxy !== undefined) {
			QDLogger.log( "announce", "window exists");
			stageProxy.delegateToSceneAssistant("updateMessage", title, message, itemcount, timestamp);
		// otherwise create a new one
		} else {
			QDLogger.log( "announce", "window does not exist");
			if (smallIcon === undefined || smallIcon === "") {
				smallIcon = "notification-small-ignored.png";
			}
			
			this.appControl.createStageWithCallback({
					lightweight: true,
					name: windowName,
					icon: "images/" + smallIcon,
					soundclass: "notifications"
					
				},
				this.onAnnounceCreated.bind(this, windowName, single, icon, itemcount, title, message, iconCallback, messageCallback, timestamp),
				'dashboard');
		}
	},

	onAnnounceCreated: function(windowName, single, icon, itemcount, title, message, iconCallback, messageCallback, timestamp, stagecontrol) {
		QDLogger.log( "onAnnounceCreated");
	
		stagecontrol.pushScene({"name": "dashannounce"}, 
			windowName, single, icon, itemcount, title, message, iconCallback, messageCallback, timestamp);
	},

	announceClear: function(windowName) {
		QDLogger.log( "announceClear", windowName);
	 	var stageProxy = this.appControl.getStageProxy(windowName);
		// if the window already exists, kill it
		if (stageProxy !== undefined) {
			this.appControl.closeStage(windowName);
		} 
	},
	
	announceUpdate: function(windowName, title, message, itemcount, timestamp) {
		var stageProxy = this.appControl.getStageProxy(windowName);
		
		// if the window already exists, update message
		if (stageProxy !== undefined) {
			QDLogger.log( "announce", "window exists");
			stageProxy.delegateToSceneAssistant("updateMessage", title, message, itemcount, timestamp);
		}
	},

	announceVoicemail: function(count, high){
		QDLogger.log( "announceVoicemail", count,high);
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;
		
		if (count > 0) {
			
			var message = Mojo.Format.formatChoice(count, Messages.voicemailMessage, { 
				"count": count, 
				"high": (high ? Messages.voicemailHigh : "") 
			});
			
			// turn display on
			TelephonyCommands.displayOn();
			this.appControl.showBanner(
				{
					icon: "images/notification-small-voicemail.png",
					messageText: message,
					soundClass: 'notifications'
				}, 
				{
					action: "voicemail"
				}, 
				'voicemail'
			);
			
			if (count = this.kUnknownVoicemailCount) {
				count = Messages.newVoicemailUnknownCount;
			}
			
			this.announce("voicemail", "notification-small-voicemail.png", 
				true, "voicemail", count, Messages.voicemailTitle,  
	 			message,
				function() {
					this.appAssistant.launchVoicemail();
				}.bind(this));
		} else {
			this.announceClear("voicemail");
		}
		
	},

	announceServiceMsg: function(message){
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;

		
		// turn display on
		TelephonyCommands.displayOn();
		
		// increment notification number
		var counter = this.notifyCounter++;
		
		// add dashboard pane
		this.announce("svcmsg" + counter, "", true, "", "", 
			Messages.serviceMessageTitle, message, function() {
				this.announceServiceMsgPopup(counter, message);	
		}.bind(this));
		
		// show banner for message
		this.appControl.showBanner(
			{
				messageText: Messages.serviceMessageNew,
				soundClass: 'notifications'
			}, 
			{ 
				"action":"servicemessage",
				"message":message,
				"counter":counter
			},
			'networkMessage'
		);
	},

	announceServiceMsgPopup: function(counter, message) {
		// pull banner message down
		this.appControl.removeBanner('networkMessage');
					
		// close dashboard for this, if it isn't already closed
		var dashStageName = "svcmsg"+ counter;
		var dashStageProxy = this.appControl.getStageProxy(dashStageName);
		if (dashStageProxy !== undefined) {
			QDLogger.log( "announceServiceMsgPopup", "window exists " + dashStageName);
			this.appControl.closeStage(dashStageName);
		} 
		
		// and close existing popup if there's one
		var stageName = "servicemessage";
		var stageProxy = this.appControl.getStageProxy(stageName);
		if (stageProxy !== undefined){
			this.appControl.closeStage(stageName);
		}
		
		// turn display on
		TelephonyCommands.displayOn();
	
		var height = 208;
		QDLogger.log( "announceServiceMsgPopup", "creating window of height " , height);
		this.appControl.createStageWithCallback({
				lightweight: true,
				name: stageName,
				height: height,
				soundclass: "none"
			},
			this.onAnnounceServiceMsgPopupCreated.bind(this, message),
			'popupalert'
		);
	},
	
	onAnnounceServiceMsgPopupCreated: function(message, stagecontrol) {
		QDLogger.log( "onAnnounceServiceMsgPopupCreated", message);
	
		stagecontrol.pushScene({"name": "servicemessage"}, 
			message);
	},

	announceBasebandMsg: function(message){
		this.announce("svcmsg" + this.notifyCounter++, "", true, "", "", 
			Messages.basebandDebugMessageTitle, message, undefined);
			
		this.appControl.showBanner(
			{
				messageText: Messages.basebandDebugMessageTitle + ": " + message,
				soundClass: 'notifications'
			}, 
			{}
		);
	},


	announceOtasp: function(message){
		
		// If in firstuse, send the update to active call assistant to show the message in the notification area.
		if (PalmSystem.isMinimal) {
			var stageProxy = this.appControl.getStageProxy("PhoneApp");
			if(stageProxy) {
				stageProxy.delegateToSceneAssistant('handleOTASPNotification',message);
			}
			return;
		}			
		// turn display on
		TelephonyCommands.displayOn();
		
		// play sound if necessary
		switch (message) {
			case 'programmingfailed':
			case 'programmingsucceeded':
				this.appControl.playSoundNotification("alerts");
				break;
			default:
				break;
		}
		
		// get localized message
		var bannerMessage = Messages.otaspNotifications[message] || message.unescapeHTML();
		
		// pull down old banner
		this.appControl.removeBanner('otasp');
		
		// show in banner
		this.appControl.showBanner(
			{
				messageText: bannerMessage,
				soundClass: 'none'
			}, 
			{ 
				
			},
			'otasp'
		);
		
		var dashboardTranslation = Messages.otaspNotificationsDashboardTranslations[message];
		var dashboardTitle = (dashboardTranslation ? dashboardTranslation[0] : Messages.otaspMessageTitle);
		var dashboardMessage = (dashboardTranslation ? dashboardTranslation[1] : bannerMessage);
		
		// show in dashboard
		this.announce("otasp", "", true, "", "", dashboardTitle, dashboardMessage);
	},

	announceMissed: function(number, contact, timeStamp) {
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;
			
		QDLogger.log( "announceMissed", number);
		
		// get contact info
		var name = this.getDisplayNameFromContact(contact);
		
		// if on a call, go straight to dashboard and don't show popup
		if (this.appAssistant.telephonyEventListener.callExists()) {
			if (!name)
				name = FormatPhoneNumber(number);
				
			var message = Messages.callMissedBanner;
			message = new Template(message).evaluate({"contact":name});
		
			this.appControl.showBanner(
				{
					icon: "images/notification-small-missed.png",
					messageText: message,
					soundClass: 'notifications'
				}, 
				{
					action: "missed"
					/*
					"name": name,
					"number": number,
					"contact": contact,
					*/
				}
			);
			this.announceMissedDashboard(number, contact, timeStamp);
			return;
		}

		var stageName = "missed";
		
		var stageProxy = this.appControl.getStageProxy("missed");
		
		var picture = "";
		
		if (contact !== undefined) { 
			picture = contact.pictureLoc;
		}
	
		// turn display on
		TelephonyCommands.displayOn();

		// if the window already exists, abandon ship
		if (stageProxy !== undefined) {
			QDLogger.log( "announceMissed", "window exists");
			return;
		// otherwise create a new one
		} else {			
			var height = (picture ? 195 : 195);
			QDLogger.log( "announceMissed", "creating window of height " , height);
			this.appControl.createStageWithCallback({
					lightweight: true,
					name: stageName, 
					"height": height, 
				}, 
				this.onAnnounceMissedCreated.bind(this, name, number, picture, contact, Messages.missedMessage, timeStamp),
				'popupalert');
		}

	},

	onAnnounceMissedCreated: function(name, number, picture, contact, message, timeStamp, stagecontrol) {
		QDLogger.log( "onAnnounceMissedCreated", name,number,message);
	
    stagecontrol.pushScene({"name": "missedcall"}, 
     name, number, picture, contact, message, timeStamp);						
	},
		
	announceMissedDashboard: function(number, contact, timeStamp) {
		QDLogger.log( "announceMissedDashboard", number);
		if (this.displayStatusListener == undefined) {
			this.displayStatusListener = this.displayStatusChangeCallback.bind(this); 
			this.appAssistant.telephonyEventListener.displayStateRegisterCallback(this.displayStatusListener);
		}
		var stageProxy = this.appControl.getStageProxy("misseddash");

		var d = new Date(parseInt(timeStamp));
		var call = {};
		call.displayName = this.getDisplayNameFromContact(contact);
		if (!(call.displayName)) {
			call.displayName = FormatPhoneNumber(number);
		} else if (contact.labelFormatted) {
			var message = Messages.contactWithLabel;
			call.displayName = new Template(message).evaluate({"contact":call.displayName, "label":contact.labelFormatted});	
		}
		
		call.message = Messages.missedCallLabel 
			+ Mojo.Format.formatRelativeDate(d, {date:'short'})
			+ " " + Mojo.Format.formatDate(d, {time:'short'});
		
		call.number = number;
		call.timestamp = timeStamp;
		// if we have a missed call stage then append
		if (stageProxy !== undefined && this.missed) {
			this.missed.push(call);
		// otherwise make a new array of missed calls 
		} else {
			this.missed = [call];
		}
		
		var count = this.missed.length;
		
		// tapping the icon brings up the call log and clears the dashboard
		var iconCallback = function() {
			this.appAssistant.launchMissed();
			this.announceMissedDashboardClear();
		}.bind(this);
		
		// tapping the message calls that number back and decrements the missed count
		var messageCallback = function() {
			var call = this.missed.pop();
			this.appAssistant.launchDial(call.number);
			var count = this.missed.length
			if (count === 0) {
				this.announceMissedDashboardClear();
			} else {
				var lastCall = this.missed[count-1];
				this.announceUpdate("misseddash",lastCall.displayName, lastCall.message, count,lastCall.timestamp);
			}
		}.bind(this);
		
		this.announce("misseddash", "notification-small-missed.png", false, "missed", 
			count, call.displayName, call.message, iconCallback, messageCallback, timeStamp);
	},
	
	announceMissedDashboardClear: function() {
		QDLogger.log( "announceMissedDashboardClear");
		
	 	var stageName = "misseddash";
		var stageProxy = this.appControl.getStageProxy(stageName);
		if (stageProxy !== undefined) {
			QDLogger.log( "announceMissedDashboardClear", "window exists");
			this.appControl.closeStage(stageName);
		}
	},
	
	getDisplayNameFromContact: function(contact) {
		var displayName = "";
		if (contact.name !== undefined) {
			displayName = contact.name;
			QDLogger.log( "getDisplayNameFromContact", "name:" , contact.name);
		} else if (contact.cnapName !== undefined && contact.cnapName !== "unknown") {
			displayName = contact.cnapName;
			QDLogger.log( "getDisplayNameFromContact", "cnapname:" , contact.cnapName);
		} 
		
		return displayName;
	},

	announceIgnored: function(name, number, callTime, picture, contact, fromContacts) {
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;
		
		QDLogger.log( "announceIgnored", name, number  , fromContacts);
		
		
		// get contact info
		var caller = this.getDisplayNameFromContact(contact);

		if (!caller) {
			caller = FormatPhoneNumber(number);
		}
		
		var message = Messages.callIgnoredBanner;
			message = new Template(message).evaluate({"contact":caller});
		
		// turn display on
		TelephonyCommands.displayOn();

		this.appControl.showBanner(
			{
				"messageText": message,
				"soundClass": 'notifications'
			}, 
			
			{
				"action": "ignored", 
				"name": name,
				"number": number,
				"callTime": callTime,
				"picture": picture,
				"contact": contact,
				"fromContacts" : fromContacts
			}
		);
	},
	
	getIncomingActiveStage: function() {
		return this.appControl.getStageProxy(this.lastIncomingStageName);
	},
	
	// checks if the incoming call stage is currently announcing an incoming call
	// relies on the stage being visible as an indication
	isAnnounceIncomingActive: function() {
		return this.appAssistant.telephonyEventListener.incomingCallExists();
	},
	
	// pass data via callback-driven lookup instead?
	announceIncoming: function(id, number, contact, fromContacts, existingCall, update) {
		QDLogger.log( "announceIncoming", id  , number) 
		QDLogger.log( "announceIncoming", existingCall);
		
		// don't proceed if the incoming call has gone away
		if (!(this.appAssistant.telephonyEventListener.incomingCallExists())) {
			QDLogger.error( "announceIncoming: call went away");
			return;
		} 
				
		var stageName = (fromContacts ? "incoming-known" : "incoming-unknown");
	 	var stageProxy = this.appControl.getStageProxy(stageName);
		
		// if we know it's an update, do it if we have a window or wait around for one
		if (update) {
			stageProxy.delegateToSceneAssistant("updateDisplay", number, contact, fromContacts);
			return;
		}
		
		// if known contact: 240; otherwise, 100
		var height = (fromContacts ? 240 : 100);
		
		this.lastIncomingStageName = stageName;
		
		// soundclass defaults to ringtone.  if there's already a call: on gsm, use
		// alarm; on CDMA, use none, since network plays in-band tone.
		var soundclass = (existingCall ? 
							(PlatformType.isGSM() ? "alarm" : "none")  
								: "ringtones");
		
		/* TODO if you want to override the ringer switch when a charger connected, 
			(puck or USB) comment out the code above and replace it with this.
			
		var listener = this.appAssistant.telephonyEventListener;
		var chargerConnected = listener.usbConnected || listener.puckConnected
		var defaultSoundClass = 
			( chargerConnected ? "alarm" : "ringtones")
		
		var soundclass = (existingCall ? 
							(PlatformType.isGSM() ? "alerts" : "none")  
								: defaultSoundClass);
		*/
		
		var soundfile = undefined;						
		if (!existingCall && contact && contact.ringtoneLoc) {
			soundfile = contact.ringtoneLoc;
		} else if (existingCall && PlatformType.isGSM()) {
			soundfile = AnnouncerAssistant.kDefaultCallOnCallSound;
		}
		
		if (!PalmSystem.isMinimal) {
			// if the stage already exists, update message
			// unless we need a different height; then close and remake stage
			if (stageProxy !== undefined) {
				QDLogger.log( "announceIncoming", "window exists");
				stageProxy.delegateToSceneAssistant("showAlert", id, number, contact, fromContacts, soundclass, soundfile);
			} else {
				QDLogger.log( "announceIncoming", "creating window of height " , height);
				var winParams = {
						lightweight: true,
						name: stageName, 
						"height": height, 
						"landscapeheight": 83,
						// if there's an existing call: on CDMA, do nothing (in-band tone suffices)
						// on GSM, play alert tone
						"soundclass": soundclass
				};
				
				if (soundfile)
					winParams.sound = soundfile;
					
				this.appControl.createStageWithCallback(winParams, 
					this.onAnnounceIncomingCreated.bind(this, id, number, contact, fromContacts, soundclass, soundfile),
					'popupalert');
			}
		}
		
		// stash parameters in case we have to reopen on transition to emergency mode
		this.lastIncomingSceneParameters = {
			"id": id, 
			"number": number, 
			"contact": contact, 
			"fromContacts": fromContacts, 
			"soundclass": soundclass, 
			"soundfile": soundfile
		}
			
		// also show as an emergency mode/first use dialog, if we have one
		if (this.appAssistant.emergencyMode === true || PalmSystem.isMinimal) {
			this.announceIncomingInRemoteDialog(); //id, number, contact, fromContacts, soundclass, soundfile);
		}
	},
	
	onAnnounceIncomingCreated: function(id, number, contact, fromContacts, soundclass, soundfile, stagecontrol) {
		QDLogger.log( "onAnnounceIncomingCreated", name,number);
		stagecontrol.pushScene({"name": "incomingcall"}, 
			id, number, contact, fromContacts, soundclass, soundfile);
	},
	
	dupeIncomingPopupToDialog: function() {
		var p = this.lastIncomingSceneParameters;
		
		this.openRemoteIncomingDialog(p.id, p.number, p.contact, p.fromContacts, p.soundclass, p.soundfile);
	},
	
	announceIncomingInRemoteDialog: function() {
		// turn display on, since dialog boxes won't trigger it like popups do
		TelephonyCommands.displayOn();
	
		var sc = this.appControl.getStageController("emergency")
		if (!sc && PalmSystem.isMinimal){
			sc = this.appControl.getStageController("PhoneApp");
		}
		
		if (sc) {
			sc.delegateToSceneAssistant("incomingDialogLaunch")
		} else {
			QDLogger.log( "announceIncomingInRemoteDialog: not creating.");
		}
	},
	
	openRemoteIncomingDialog: function(id, number, contact, fromContacts, soundclass, soundfile) {
		this.remoteIncomingCallAssistant = new IncomingcallAssistant(id, number, contact, fromContacts, soundclass, soundfile, this.remoteDialogScene);
		this.remoteIncomingCallDialogElement = this.remoteDialogScene.showDialog({
			template: 'incomingcall/incomingcall-dialog',
			assistant: this.remoteIncomingCallAssistant,
			preventCancel: true			
		});
		
		//this.remoteDialogScene.document.body.appendChild(this.remoteIncomingCallDialogElement);
		this.remoteIncomingCallDialogElement._mojoController.reparent(this.remoteDialogScene.document.body);
	},
	
	closeIncomingCallDialog: function(deactivateStage) {
		QDLogger.log( "closeIncomingCallDialog");
		this.lastIncomingSceneParameters = undefined;
		if (this.remoteIncomingCallDialogElement) {
			this.remoteIncomingCallDialogElement.mojo.close();
			this.remoteIncomingCallDialogElement = undefined;
			this.remoteIncomingCallAssistant = undefined;
		}	
	
		if (deactivateStage) {
			var stageController = this.getIncomingActiveStage();
			if (stageController) {
				stageController.delegateToSceneAssistant("closeWindowNoAction");
			} else {
				QDLogger.error("closeIncomingCallDialog: can't find incoming stage")
			}
		}
		
		QDLogger.log( "closeIncomingCallDialog closed");	
	},
	
	// called when a contact lookup arrives after the incoming call stage is shown
	announceIncomingUpdateContactLate: function(contact, retries) {
		QDLogger.log( "announceIncomingUpdateContactLate");
		var stageController = this.getIncomingActiveStage(); 
		
		// try to get stage controller a few times.  bail if this doesn't work out.
		if (!stageController) {
			if (retries < 6) {
				QDLogger.log( "announceIncomingUpdateContactLate retry", retries);
				this.announceIncomingUpdateContactLate.delay(1, contact, retries++);
			} else {
				QDLogger.error("announceIncomingUpdateContactLate: can't find stage.  giving up.");
			}
			return;
		} 
		
		stageController.delegateToSceneAssistant("updateContactLate", contact);
		
	},
	
	// closes incoming call stage.  cause triggers post-close actions
	announceIncomingClose: function(cause, id, retries) {
		QDLogger.log( "announceIncomingClose", cause);
	 	
		var stageController = this.getIncomingActiveStage(); 
		
		// try to get stage controller a few times (~length of contact lookup timeout)
		if (!stageController) {
			if (retries < 6) {
				QDLogger.log( "announceIncomingClose retry", retries);
				this.announceIncomingClose.delay(1, cause, retries++);
			} 
			return;
		}
		
		QDLogger.log( "announceIncomingClose", "window exists");
		var method = ""
		
		// call incoming call assistant's appropriate method to handle post-close action
		switch (cause) {
			case AnnouncerAssistant.kIncomingMissed:
				method = "onMissed";
				break;
			case AnnouncerAssistant.kIncomingRejected:
				method = "rejectCall";
				break;
			case AnnouncerAssistant.kIncomingAnswered:
			default:
				method = "onAnswered";
				break;				
		}
		stageController.delegateToSceneAssistant(method);
		
		
		// close the emergency mode/first use dialog, if we have one
		if (this.remoteDialogScene) {
			this.closeIncomingCallDialog();
		}
		
		// close the dashboard if there is one
		this.announceIncomingDashboardClear();
		
	},
	
	// pops a dashboard up to allow call to be answered after popup minimized
	announceIncomingDashboard: function(contact, number, callback) {
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;
			
		var onTap = function() {
			this.announceIncomingDashboardClear();
			callback();
		}.bind(this);
		this.announce("incomingdash", "notification-small-incoming.png", true, "answer", 1, contact, number, onTap)
	},
	
	announceIncomingDashboardClear: function() {
		
	 	var stageName = "incomingdash";
		var stageProxy = this.appControl.getStageProxy(stageName);
		if (stageProxy !== undefined) {
			this.appControl.closeStage(stageName);
		}
	},

	announceDisconnectAbnormal: function(callState) {
		QDLogger.log( "announceDisconnectAbnormal");
		
	 	var stageName = "dropped";
		var stageProxy = this.appControl.getStageProxy(stageName);
		var disconnectErrorMessage;
		
		if (PlatformType.isGSM())
			disconnectErrorMessage = Messages.disconnectErrorMessageGsm;
		else
			disconnectErrorMessage = Messages.disconnectErrorMessageCdma;
		
		var message = disconnectErrorMessage[callState.causeCode];
		if (message === undefined) 
			message = Messages.disconnectErrorMessageDefault;
		
		var closeSelf = function(){
			this.droppedTimeout = undefined;
			var stageProxy = this.appControl.getStageProxy("dropped");
			if (stageProxy !== undefined) {
				this.appControl.closeStage("dropped");
			}	
		}
		
		// stay up for 20 seconds
		this.droppedTimeout = window.setTimeout(closeSelf.bind(this), 200000);		
	
		// get contact info
		var contacts = Mojo.Controller.getAppController().assistant.contacts;
        var callerDetails = contacts.callerDetailsTable.get(callState.number);
		var name = "";
		var picture = "";
		var label = "";
		
		// TODO FIXME MOCK
		if (MockTelephony.useMock === 1) {
			callerDetails = {
				name: "Zooey Glass",
				pictureLoc: "",
				labelFormatted: "Mobile"
			}
		}
		
		if (callerDetails === undefined 
			|| callState.affectedCallId === undefined) {
			name = (callState.cnapName === undefined ?
				"" : callState.cnapName);
			picture = "";
		} else {
			name = callerDetails.name;	
			picture = callerDetails.pictureLoc;
			label = callerDetails.labelFormatted;
		}
	
		// turn display on
		TelephonyCommands.displayOn();
	
		// if the active call screen is focused, don't use popup -- just a banner
		// notification with reason
		// TODO: only working in experimental mode for now
		if (this.appAssistant.experimentalMode
			&& this.appAssistant.activeCallFocused == true ) {
			this.appControl.showBanner(
				{
					messageText: message,
					soundClass: 'notifications'
				}, 
				{
					prefill: callState.number
				}
			);
			return;
		}
		
		// if the window already exists, abandon ship
		if (stageProxy !== undefined) {
			QDLogger.log( "announceDisconnectAbnormal", "window exists");
			return;
		// otherwise create a new one
		} else {
			var height = (picture ? 195 : 195);
			QDLogger.log( "announceDisconnectAbnormal", "creating window of height " , height);
			this.appControl.createStageWithCallback({
					lightweight: true,
					name: stageName, 
					"height": height, 
					soundclass: "alerts"
				}, 
				this.onAnnounceDisconnectAbnormalCreated.bind(this, name, callState.number, label, picture, message, callerDetails),
				'popupalert');
		}
	},
	
	onAnnounceDisconnectAbnormalCreated: function(name, number, label, picture, message, contact, stagecontrol) {
		QDLogger.log( "onAnnounceDisconnectAbnormalCreated", name,number,message);
	
		stagecontrol.pushScene({"name": "droppedcall"}, 
			name, number, label, picture, message, contact);
	},
	
	announceDisconnectNormal: function(callState) {
		QDLogger.log( "announceDisconnect");
		// not valid in first use
		if (PalmSystem.isMinimal)
			return;
				
		// turn display on
		TelephonyCommands.displayOn();

		if (this.appAssistant.activeCallFocused == true) {
			QDLogger.log( "announceDisconnectNormal", "not showing: active call is focused");
			return;
		}
		
		var contacts = Mojo.Controller.getAppController().assistant.contacts;
        var callerDetails = contacts.callerDetailsTable.get(callState.number);
		var message = "";
		var callbackNumber = callState.number;
		
		// if this is the last call being disconnected from a conference, 
		// show name as conference label
		if (callState.lines.length == 1 && callState.lines[0].confId === -1) {
			callbackNumber = "";
			message = Messages.conferenceEndedBanner;
		// otherwise look for contact name; if it's not there, use number
		} else { 
			var name = "";
			if (callerDetails !== undefined 
				&& callerDetails.name !== undefined 
				&& callerDetails.name != "") {
				QDLogger.log( "announceDisconnectNormal", "using contact name");
				name = callerDetails.name;
			} else {
				if (callState.cnapName === undefined 
					|| callState.cnapName == ""
					|| callState.cnapName == "unknown") {
					QDLogger.log( "announceDisconnectNormal", "formatting number");
					name = FormatPhoneNumber(callState.number);
				} else {
					QDLogger.log( "announceDisconnectNormal", "using cnap name");
					name = callState.cnapName;
				}
			}
			if (name != "") {
				message = Messages.callEndedBanner;
				message = new Template(message).evaluate({
					"contact": name
				});
			} else {
				message = Messages.callEndedNoNameBanner;
			}
		}
		
		QDLogger.log( "announceDisconnectNormal", callState.number  , name);
		
		this.appControl.showBanner(
			{
				messageText: message,
				soundClass: 'notifications'
			}, 
			{
				prefill: callbackNumber
			}
		);
	},
	
	announceDialFail: function(errorCode, errorText) {
		QDLogger.log( "announceDialFail");
		
	 	var stageName = "fail";
		var stageProxy = this.appControl.getStageProxy(stageName);
		
		var message = Messages.callFailErrorMessage[errorCode];
		if (message === undefined) 
			message = Messages.callFailErrorMessageDefault;
		
	
		// turn display on
		TelephonyCommands.displayOn();

		// if the window already exists, abandon ship
		if (stageProxy !== undefined) {
			QDLogger.log( "announceDialFail", "window exists");
			return;
		// otherwise create a new one
		} else {
			var height = 140;
			QDLogger.log( "announceDialFail", "creating window of height " , height);
			this.appControl.createStageWithCallback({
					lightweight: true,
					name: stageName, 
					"height": height, 
					soundclass: "alerts"
				}, 
				this.onAnnounceDialFailCreated.bind(this, message),
				'popupalert');
		}
	},
	
	onAnnounceDialFailCreated: function(message, stagecontrol) {
		QDLogger.log( "onAnnounceDialFailCreated", message);
	
		stagecontrol.pushScene({"name": "dialfail"}, 
			message);
	},
	
	announceSmallCall: function(callCount){
        QDLogger.log( "announceSmallCall");
		// not valid in first use, or when screen is locked
		if (PalmSystem.isMinimal || this.appAssistant.screenLocked)
			return;

		/*					
 		var stageProxy = this.appControl.getStageProxy("smallcall");
        // if the window already exists, don't do anything
        if (stageProxy !== undefined) {
            QDLogger.log( "smallCallUpdate", "window exists");
            // otherwise create a new one
        } else {
            QDLogger.log( "smallCallUpdate", "window does not exist");
            this.appControl.createStageWithCallback({
				lightweight: true,
			    name: this.smallCallStage,
				soundclass: 'none',
				htmlFileName: 'smallcall'
            }, this.onSmallCallCreated.bind(this), 'activebanner');
        }
        */
    },
    
    onSmallCallCreated: function(stagecontrol){
        QDLogger.log( "onSmallCallCreated");
        
        stagecontrol.pushScene({
            "name": "smallcall"
        });
    },
    
    smallCallClear: function(){
        /*
		var stageProxy = this.appControl.getStageProxy("smallcall");
	
        if (stageProxy !== undefined) {
            this.appControl.closeStage("smallcall");
        }
        */
    },
	
	announceEmergencyMode: function(number){
        QDLogger.log( "announceEmergencyMode");
		var stageName = "emergencymode"
		
 		var stageController = this.appControl.getStageController(stageName);
		var stageProxy = this.appControl.getStageProxy(stageName);

        // turn display on
		TelephonyCommands.displayOn();

		
		// if the window already exists, don't do anything
        if (stageProxy !== undefined) {
            QDLogger.log( "announceEmergencyMode", "window exists");
			stageProxy.delegateToSceneAssistant("updateRedialNumber", number);
			if (stageController !== undefined) {
				stageController.activate();
			}
        // otherwise create a new one
        } else {
            QDLogger.log( "announceEmergencyMode", "window does not exist");
            this.appControl.createStageWithCallback({
				lightweight: true,
                name: stageName,
                height: 400
            }, this.onEmergencyModeCreated.bind(this, number), 'banneralert');
        }
    },
    
    onEmergencyModeCreated: function(number, stagecontrol){
        QDLogger.log( "announceEmergencyMode");
        
        stagecontrol.pushScene({
            "name": "emergencymode"
        }, number);
    },
	
	emergencyModeClear: function(){
        QDLogger.log( "emergencyModeClear");
		var stageName = "emergencymode";
        var stageProxy = this.appControl.getStageProxy(stageName);
	
		if (stageProxy !== undefined) {
            this.appControl.closeStage(stageName);
        }
    },

	announceProvisioning: function(type, msg, isCancelabel, showAlert, errorCode) {
		QDLogger.log( "announceProvisioning", msg) 
		
	 	var stageName = "provisioning";
		var stageProxy = this.appControl.getStageProxy(stageName);

		// turn display on
		TelephonyCommands.displayOn();
		
		if (stageProxy !== undefined) {
			QDLogger.log( "announceProvisioning", "window exists");
			stageProxy.delegateToSceneAssistant("updateDisplay", type, msg, isCancelabel, errorCode);
		} else if(msg!=="success" && showAlert == true){
			this.appControl.createStageWithCallback({
					lightweight: true,
					name: stageName, 
					"height": (isCancelabel ? 260 : 200), 
				}, 
				this.onAnnounceProvisioningCreated.bind(this, type, msg, isCancelabel ,errorCode),
				'popupalert');
		}
	},
	
	onAnnounceProvisioningCreated: function(type, msg, isCancelabel ,errorCode, stagecontrol) {
		QDLogger.log( "onAnnounceProvisioningCreated", msg);
		stagecontrol.pushScene({"name": "provisioning"}, 
			type, msg, isCancelabel ,errorCode);
	},
	
	displayStatusChangeCallback: function(payload){
		if (payload.event && payload.event == 'displayOn') {
			var count = this.missed.length;
			if (count > 0) {
				var lastCall = this.missed[count - 1];
				var d = new Date(parseInt(lastCall.timestamp));
				var msg = Messages.missedCallLabel 
					+ Mojo.Format.formatRelativeDate(d, {date:'short'})
					+ " " + Mojo.Format.formatDate(d, {time:'short'});
				if (msg !== lastCall.message) {
					lastCall.message = msg;
					this.announceUpdate("misseddash", lastCall.displayName, lastCall.message, count, lastCall.timestamp);
				}
			}
		}
	},
	
	kUnknownVoicemailCount: 255

});

AnnouncerAssistant.kIncomingRejected = "rejected";
AnnouncerAssistant.kIncomingAnswered = "answered";
AnnouncerAssistant.kIncomingMissed = "missed";
AnnouncerAssistant.kDefaultCallOnCallSound = "/usr/palm/applications/com.palm.app.phone/sounds/incoming-call-active.wav";

