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

/*jslint laxbreak: true, white: false, devel: true */
/*global Class: false, Mojo: false, $L: false, Template: false, getAppAssistant: false */

var ReminderAssistant = Class.create({

	initialize: function(eventId,needThrobbing) {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant initialize: start: "+eventId);

		this.DEFAULT_SNOOZE			= 5;
		this.app					= getAppAssistant();
		this.reminders				= this.app.getReminderManager();
		this.app.openReminderAlert	= this;
		this.requests				= [];
		this.dismissed				= false;	
		this.snoozed				= false;	
		this.eventId				= eventId;	
		this.doThrob				= needThrobbing;
		this.autoSnoozed			= false;

		Mojo.Log.info("$$$$$$$$ Reminder-assistant initialize:end");
	},

	activate:function(){
		Mojo.Log.info("$$$$$$$$ Reminder-assistant activate:start");
		if (this.doThrob) {
			Mojo.Log.info("$$$$$$$$ Reminder-assistant doThrob:true");
			this.controller.stageController.indicateNewContent(true);
		}
		Mojo.Log.info("$$$$$$$$ Reminder-assistant activate:end");
	},
	
	setup: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant setup:start");
	
		this.reminders.observeReminders ("alert", this);

		this.onEventHandler		= this.onEvent	.bindAsEventListener(this);
		this.onDismissHandler	= this.onDismiss.bindAsEventListener(this);
		this.onEmailHandler		= this.onEmail	.bindAsEventListener(this);
		this.onSnoozeHandler	= this.onSnooze	.bindAsEventListener(this);
	
		this.updateMostRecentReminder();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant setup:end");
	},
    
	cleanup: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant cleanup:start:");
		this.reminders.stopObservingReminders('alert');
		
		getAppAssistant().openReminderAlert = null;
		if (this.reminder) {
			Mojo.Log.info("$$$$$$$$ Reminder Assistant cleanup for:"+this.reminder.id);
			if (!this.dismissed && this.reminders.getReminder(this.reminder.id)/*this might be an auto close task and hence already removed*/) {
				Mojo.Log.info("$$$$$$$$ Reminder-assistant cleanup: snoozing reminder " + this.reminder.id);
				this.snooze(this.DEFAULT_SNOOZE);
			}
			if (this.dismissed || this.snoozed) {				
				Mojo.Log.info("$$$$$$$$ Reminder-assistant cleanup : removing autoclosetask");
				//only remove the auto close task if it is acted upon
				this.removeAutoCloseTask();
				
			}
		}
		Mojo.Log.info("$$$$$$$$ Reminder-assistant cleanup:end:");
	},
	
	remindersUpdated: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant remindersUpdated: start");
		if (this.autoSnoozed) {
			Mojo.Log.info("$$$$$$$$ Reminder-assistant remindersUpdated: autoSnoozed so returning...");
			return;
		}
		
		if (this.reminders.getNumReminders() === 0) {
			Mojo.Log.info("$$$$$$$$ Reminder-assistant remindersUpdated:closingAlert");
			this.closeAlert();	
		}
		else {
			Mojo.Log.info("$$$$$$$$ Reminder-assistant remindersUpdated:updateMostRecentReminder");
			this.updateMostRecentReminder();
		}
		Mojo.Log.info("$$$$$$$$ Reminder-assistant remindersUpdated: end");
	},

	updateMostRecentReminder: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateMostRecentReminder:start");
		//this.reminder = this.reminders.getMostRecentReminder();
		this.reminder = this.reminders.getReminder(this.eventId);
		if(!this.reminder){
			//the reminder manager does not have any reminders
			//so just close this scene and return.
			this.closeAlert();
			return;
		}
		
		this.scheduleAtStartTime();		
		this.scheduleAutoCloseTask();
		this.updateDisplay();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateMostRecentReminder:end");
	},

	updateDisplay: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateDisplay:start, StageName:"+this.controller.window.name);
		var data = {};
		
		data.subject = this.reminder.subject;
		if (!data.subject) {
			data.subject = '';
		}
			
		if (this.reminder.time || this.reminder.isAllDay) {
			var timeStartStr;
			var ampmStr;
					
			if(this.reminder.isAllDay)
			{
				data.time = Mojo.Format.formatDate(new Date(this.reminder.time), $L("MMM d, yyyy"));
			}
			else if (this.app.getTimeFormat() == "HH12")
			{
				data.time = Mojo.Format.formatDate(new Date(this.reminder.time), $L('EEE MMM d, h:mm a'));
			}
			else
			{
				data.time = Mojo.Format.formatDate(new Date(this.reminder.time), $L('EEE MMM d, H:mm'));
			}
		
		}
		if (this.reminder.location) {
			data.location = this.reminder.location;
		}
		else {
			data.location = $L("No location");
		}
			
		this.removeListeners();
		
		var eventHtml = Mojo.View.render({object: data, template: 'reminder/reminder-event'});
		this.updateHTML(this.controller.get('reminder-event'), eventHtml);
		
		if (this.reminder.attendees.length > 1/* we now include the organizer in the attendee list*/) {
			this.controller.get('reminder-email').style.display = '';
			this.controller.get('reminder-email').addEventListener(Mojo.Event.tap, this.onEmailHandler);
		}
		
		this.addListeners();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateDisplay:end");
	},
	
	addListeners: function() {
		this.controller.get('notification-event-title').addEventListener(Mojo.Event.tap, this.onEventHandler);
		this.controller.get('notification-event-subtitle').addEventListener(Mojo.Event.tap, this.onEventHandler);
		this.controller.get('notification-event-icon').addEventListener(Mojo.Event.tap, this.onEventHandler);
		this.controller.get('notification-event-location').addEventListener(Mojo.Event.tap, this.onEventHandler);
		
		this.controller.get('reminder-dismiss').addEventListener(Mojo.Event.tap, this.onDismissHandler);
		this.controller.get('reminder-snooze').addEventListener(Mojo.Event.tap, this.onSnoozeHandler);
	},

	removeListeners: function() {
		var title = this.controller.get('notification-event-title');
		if (title) {
			title.removeEventListener(Mojo.Event.tap, this.onEventHandler);
		}
		var subtitle = this.controller.get('notification-event-subtitle');
		if (subtitle) {
			subtitle.removeEventListener(Mojo.Event.tap, this.onEventHandler);
		}
		var location = this.controller.get('notification-event-location');
		if (location) {
			location.removeEventListener(Mojo.Event.tap, this.onEventHandler);
		}
		var icon =this.controller.get('notification-event-icon');
		if (icon) {
			icon.removeEventListener(Mojo.Event.tap, this.onEventHandler);
		}
		var dismiss = this.controller.get('reminder-dismiss');
		if (dismiss) {
			dismiss.removeEventListener(Mojo.Event.tap, this.onDismissHandler);
		}
		var email = this.controller.get('reminder-email');
		if (email) {
			email.removeEventListener(Mojo.Event.tap, this.onEmailHandler);
		}
		var snooze = this.controller.get('reminder-snooze');
		if (snooze) {
			snooze.removeEventListener(Mojo.Event.tap, this.onSnoozeHandler);
		}
	},
	
	
	formatTimeText: function(date1, date2) {
		var minsInDay = 24 * 60;
		var t1 = $L('in #{min} mins');
		var t2 = $L('in #{hour} hrs #{min} mins');
		var t3 = $L('#{min} mins ago');
		var t4 = $L('#{hour} hrs #{min} mins ago');
		var t5 = $L('in #{day} days #{hour} hrs #{min} mins');
		var t6 = $L('#{day} days #{hour} hrs #{min} mins ago');
		var timeDelta = {};
		var template;
		var days1 = date1.getDayOfYear();
		var days2 = date2.getDayOfYear();
		var year1 = date1.getFullYear();
		var year2 = date2.getFullYear();
		for (var y1 = year1; y1 < year2; y1++) {
			days2 += Date.isLeapYear(y1) ? 366: 365;
		}
		for (var y2 = year2; y2 < year1; y2++) {
			days1 += Date.isLeapYear(y2) ? 366: 365;
		}
		var dt = (days1 - days2) * minsInDay + (date1.getHours() - date2.getHours()) * 60 + (date1.getMinutes() - date2.getMinutes());
		if (dt < 0) {
			dt = Math.abs(dt);
			if (dt >= minsInDay) {
				template = new Template(t6);
				timeDelta.day = Math.floor(dt / minsInDay);
				timeDelta.hour = Math.floor(dt / 60) % 24;
				timeDelta.min = dt % 60;
			}else if (dt >= 60) {
				template = new Template(t4);
				timeDelta.hour = Math.floor(dt / 60);
				timeDelta.min = dt % 60;
			} else {
				template = new Template(t3);
				timeDelta.min = dt;
			}
		} else {
			if (dt >= (24 * 60)) {
				template = new Template(t5);
				timeDelta.day = Math.floor(dt / minsInDay);
				timeDelta.hour = Math.floor(dt / 60) % 24;
				timeDelta.min = dt % 60;
			} else if (dt >= 60) {
				template = new Template(t2);
				timeDelta.hour = Math.floor(dt / 60);
				timeDelta.min = dt % 60;
			} else {
				template = new Template(t1);
				timeDelta.min = dt;
			}
		}
		
		return template.evaluate(timeDelta);
	},
	
	//If there are autosnoozed reminders, and the displayed reminder is snoozed or dismissed, 
	//display the most recent autosnoozed reminder.
	reissueAutoSnoozedAlerts: function(){
				
		var reminders	= this.app.getReminderManager().getAllReminders();
		var now			= new Date().getTime();
		var reminder;
				
		//Scan the list, find which autosnoozed alarm's start time is most recent
		Mojo.Log.info("$$$$$$$$ Reminder-assistant reissueAutoSnoozedAlerts start: reminders in list: "+reminders.size());
		var latestReminderIndex	= -1;
		var latestStartTime		= 0;

		for(var i = 0; i < reminders.size(); i++){
			reminder = reminders[i];
			var closeTime = new Date(reminder.time + reminder.duration);
			if(now < closeTime && reminder.time > latestStartTime && reminder.userClosed === false){
				latestStartTime = reminder.time;
				latestReminderIndex = i;
			}
		}
		
		//Reissue the alarm.
		if (latestReminderIndex != -1) {
			reminder = reminders[latestReminderIndex];
			Mojo.Log.info("$$$$$$$$ Reminder-assistant reissueAutoSnoozedAlerts reissuing: "+reminder.id);
			var request = new Mojo.Service.Request('palm://com.palm.applicationManager', {
					                    method: 'open',
					                    parameters: {
													'id': 'com.palm.app.calendar',
													'params': {'alarmsnooze': reminder.id,'dontAlert':true}
													}
									});
		}
	},
	
	onEvent: function(event) {	
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onEvent: start: " + this.reminder.id);
		
		this.dismissed = true;
		this.closeAlert();
		this.removeReminder();
		this.showEventDetails();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onEvent: end: " + this.reminder.id);
	},

	onDismiss: function(event) {		
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onDismiss: start: " + this.reminder.id);
		
		this.dismissed = true;
		this.closeAlert();
		this.removeReminder();
		this.autoSnoozed = false;
		this.reminder.userClosed = true;
		this.reissueAutoSnoozedAlerts();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onDismiss: end: " + this.reminder.id);
	},

	onEmail: function(event) {		
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onEmail: start " + this.reminder.id);
		
		if (this.reminder.attendees.length > 0) {
			var messageBody = $L("Running late, on my way...");
			this.app.getAppManagerService().launchComposeMessage(this.controller
																,this.reminder.subject
																,this.reminder.attendees
																,messageBody
																,this.reminder.emailAccountId);
			this.closeAlert();
		}

		Mojo.Log.info("$$$$$$$$ Reminder-assistant onEmail: end " + this.reminder.id);
	},

	onSnooze: function(event) {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onSnooze: start: " + this.reminder.id);
		this.snoozed =true;
		this.closeAlert();
		this.autoSnoozed = false;
		this.reminder.userClosed = true;
		this.reminder.scheduleStartTime = true;
		this.reissueAutoSnoozedAlerts();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant onSnooze: end: " + this.reminder.id);
	},
	
	removeReminder: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant removeReminder: start: " + this.reminder.id);
		this.reminders.removeReminder(this.reminder.id);
		Mojo.Log.info("$$$$$$$$ Reminder-assistant removeReminder: end: " + this.reminder.id);
	},
	
	scheduleAtStartTime: function(){
		
		//Schedule the alarm to go off again at the start time
		if(this.reminder.scheduleStartTime && (new Date().getTime()) < this.reminder.time){
			Mojo.Log.info("$$$$$$$$ Reminder-assistant scheduleAtStartTime: scheduling "+this.reminder.id+" for "+new Date(this.reminder.time));

			this.controller.serviceRequest ("palm://com.palm.taskScheduler",
			{	method		:	"updateTask"
			,	parameters	:	{ "arguments"	:	{ id	: "com.palm.app.calendar"
													, params: {alarmsnooze: this.reminder.id}
													}
								, key			:	"calendar-snooze-" + this.reminder.id
								, misfirePolicy	:	{ executeNow: true }
								, prereq		:	[ "MSM_OFF" ]
								, start			:	{ date: new Date(this.reminder.time).toUTCString() }
								, uri			:	"palm://com.palm.applicationManager/open"
								}
			});
		}
		this.reminder.scheduleStartTime = false;
	},
	
	snooze: function(minutes) {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: start: " + this.reminder.id);
		
		if(this.autoSnoozed && this.reminder.userClosed === false) {
			//if autoSnoozed, let the reminder go to the missed reminders list without snoozing.
			Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: autosnoozed "+this.reminder.id);
			return;
		}	
		
		var snooze = new Date().addMinutes(minutes);
		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: updateTask: calendar-snooze-" + this.reminder.id + "   date = " + snooze.toUTCString());

		this.controller.serviceRequest ("palm://com.palm.taskScheduler",
		{	method		:	"updateTask"
		,	parameters	:	{ "arguments"	:	{ id	: "com.palm.app.calendar"
												, params: {alarmsnooze: this.reminder.id}
												}
							, key			:	"calendar-snooze-" + this.reminder.id
							, misfirePolicy	:	{ executeNow: true }
							, prereq		:	[ "MSM_OFF" ]
							, start			:	{ date: snooze.toUTCString()}
							, uri			:	"palm://com.palm.applicationManager/open"
							}
		});

		var templateModel = {};
		var templateStr = $L("Snoozed for #{num} minutes");
		templateModel.num =minutes;
		var template = new Template(templateStr);
		var snoozeText=template.evaluate(templateModel);
		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: showBanner" + this.reminder.id);
		Mojo.Controller.appController.showBanner({messageText: snoozeText}, null /*launchArguments*/, "calendar-snooze");

		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: end" + this.reminder.id);
	},
	
	closeAlert: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant closeAlert: start ");
		this.reminders.stopObservingReminders('alert');
		Mojo.Log.info("$$$$$$$$ Reminder-assistant closeAlert: window.close() ");
		this.controller.window.close();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant closeAlert: end ");
	},
	
	autoCloseAlert: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant autoCloseAlert: start" + this.reminder.id);
		this.dismissed = true; // prevent snooze
		this.closeAlert();
		Mojo.Log.info("$$$$$$$$ Reminder-assistant autoCloseAlert: end " + this.reminder.id);
	},
	
	specialCleanup:function(){
		//we need to do this so that cleanup cleans the reminder rightaway		
		Mojo.Log.info("$$$$$$$$ Reminder-assistant specialCleanup: window Name:" + this.controller.window.name);
		
		//we're auto-snoozing this because another reminder is being put up.
		this.controller.window.close();
		this.autoSnoozed =true;
	},
	
	showEventDetails: function() {
		this.controller.serviceRequest('palm://com.palm.applicationManager', {
					                    method: 'open',
					                    parameters: {
													'id': 'com.palm.app.calendar',
													'params': {'details': this.reminder.id.toString() }	
													}
										});
	},
	
	scheduleAutoCloseTask: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant scheduleAutoCloseTask: start " + this.reminder.id);

		var minCloseTime= new Date(this.reminder.time).addMinutes(15);
		var closeTime	= new Date(this.reminder.time + this.reminder.duration);

		if (closeTime < minCloseTime) {
			closeTime = minCloseTime;
		}

		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: scheduleAutoCloseTask: calendar-alarmclose-" + this.reminder.id + "   date = " + closeTime.toUTCString());

		this.controller.serviceRequest ("palm://com.palm.taskScheduler",
		{	method		:	"updateTask"
		,	parameters	:	{ "arguments"	:	{ id	: "com.palm.app.calendar"
												, params: { alarmclose: this.reminder.id }
												}
							, key			:	"calendar-alarmclose-" + this.reminder.id
							, misfirePolicy	:	{ executeNow: true }
							, prereq		:	[ "MSM_OFF" ]
							, start			:	{ date: closeTime.toUTCString() }
							, uri			:	"palm://com.palm.applicationManager/open"
							}
		});
		
		Mojo.Log.info("$$$$$$$$ Reminder-assistant scheduleAutoCloseTask: end " + this.reminder.id);
	},
	
	removeAutoCloseTask: function() {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant removeAutoCloseTask: start " + this.reminder.id);
		
		Mojo.Log.info("$$$$$$$$ Reminder-assistant snooze: removeTask: calendar-alarmclose-" + this.reminder.id);
		this.controller.serviceRequest('palm://com.palm.taskScheduler', {
					                    method: 'removeTask',
					                    parameters: {key: 'calendar-alarmclose-'+this.reminder.id}
									});
		Mojo.Log.info("$$$$$$$$ Reminder-assistant removeAutoCloseTask: end " + this.reminder.id);
	},
	
	replaceHTML: function(element, content) {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant replaceHTML:start");
		var range = element.ownerDocument.createRange();
		range.selectNode(element);
		content = range.createContextualFragment(content.stripScripts());
		element.parentNode.replaceChild(content, element);
		Mojo.Log.info("$$$$$$$$ Reminder-assistant replaceHTML:end");
		return element;
	},
	
	updateHTML: function(element, content) {
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateHTML:start");
		element.innerHTML = content;
		Mojo.Log.info("$$$$$$$$ Reminder-assistant updateHTML:end");
		return element;
	}
	
});