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

var Timeout = 2000;//2000 milliseconds
var DatetimeAssistant = Class.create({
    initialize: function(targetEvent, targetDate, callback, oldEvent, setEventCallback, editSceneController, callBackAfterUpdate, longTargetId){
        //Mojo.Log.info("datetime-assistant:initialize");
        this.targetEvent = targetEvent;
        this.targetCallBack = callback;
        this.oldEvent = oldEvent;
        this.timer = null;
        this.targetModifiedTime = targetDate;
        this.unchangedtargetModified = Object.clone(targetDate);
        this.originalstartTimestamp = targetDate.start;
        this.setEventCallback = setEventCallback;
        this.recurrenceRule = getRecurrenceRule();
        this.editSceneController = editSceneController;
        if (!targetEvent.id > 0) //if it is a new event yet to be saved
            this.oldAllday = targetEvent.allDay;
        this.callBackAfterUpdate = callBackAfterUpdate;
        this.targetId = longTargetId;
		this.formatter = getFormatterService();
    },
    
    update: function(){
    },
    
    renderEventDuration: function(response){
        this.updateDuration(response);
    },
    
    updateDuration: function(duration){
        Mojo.Log.info("datetime-assistant:updateDuration");
		var button = Mojo.View.render({object: {info: duration}, template: "datetime/info"});
        this.controller.get('edit_duration').update(button);
    },
    
    updateTimedAllDay: function(transition){
		var that = this;
        if (transition == false) {
            if (this.targetEvent.allDay == false) {
                this.allDayCheckboxModel.value = false;
                
                this.controller.get('edit_startTime').show();
                this.controller.get('edit_endTime').show();
                
			} else {
                this.allDayCheckboxModel.value = true;
                this.controller.get('start_time_row').hide();
                this.controller.get('end_time_row').hide();
            }
		} else {
            if (this.targetEvent.allDay == false) {
                this.allDayCheckboxModel.value = false;
				
				// Since we're revealing them, call modelChanged() now, so current data is visible immediately.
                this.controller.modelChanged(this.startTimeModel);
                this.controller.modelChanged(this.endTimeModel);
		        
                this.slideDown(this.controller.get('start_time_row'), 0.4);
                this.slideDown(this.controller.get('end_time_row'), 0.4);
                this.controller.get('start_date_row').removeClassName('last');
                this.controller.get('end_date_row').removeClassName('last');
			} else {
                this.allDayCheckboxModel.value = true;
                this.slideUp(this.controller.get('start_time_row'), 0.4);
                this.slideUp(this.controller.get('end_time_row'), 0.4, function() {
                        // Defer modelChanged calls until animation is complete, so it's not visually distracting.
                        that.controller.modelChanged(that.startTimeModel);
                        that.controller.modelChanged(that.endTimeModel);
                    });
                
                this.controller.get('start_date_row').addClassName('last');
                this.controller.get('end_date_row').addClassName('last');
            }
        }
        this.controller.modelChanged(this.allDayCheckboxModel);
        this.calcDuration();
    },
    
    slideDown: function(div, duration){
		div.show();
        var divDimensions = div.getDimensions();
       	div.style.height='0px';
		Mojo.Animation.animateStyle(div, 'height', 'bezier', {from: 0, to: divDimensions.height, duration: duration, curve: 'ease-in-out', 
                                                    onComplete:function(el, cancelled){
                                                            if(!cancelled) {
                                                                div.style.height='';
                                                            }
                                                        }
        });
    },
    
    slideUp: function(div, duration, onNotCancelled){
        var divDimensions = div.getDimensions();		
        div.show();
		Mojo.Animation.animateStyle(div, 'height', 'bezier', {from: divDimensions.height, to: 0, duration: duration, curve: 'ease-in-out', 
                       onComplete:function(el, cancelled){
                                if(!cancelled) {
                                    div.style.height='';
                                    div.hide();
                                    if(onNotCancelled) {
                                        onNotCancelled();
                                    }
                                }
                            }
        });
    },
    
    calcDuration: function(){
    	this.renderEventDuration(this.formatter.getEventDurationText(this.targetModifiedTime.start, this.targetModifiedTime.end, this.targetEvent.allDay));       
    },
    blurNeedSetEventCheck: function(){
        if (this.targetEvent.dirty && this.checktargetEventDirty()) {
        
            if (this.targetEvent.id > 0 /*this is not a new event*/ &&
				this.targetEvent.rrule && this.targetEvent.rrule != "" /* this event has an rrule */ &&
				this.oldEvent.rrule && this.oldEvent.rrule != "" /* this is not the first time we are setting the rrule*/) 
                return 2; //create an exception of series
            else 
                return 1; //just save the event
        }
        else 
            return 0; //not dirty, dont attempt a save
    },
    blurStageBound: function(){
        //Mojo.Log.info("&&&&&&&&&&&&&&&&&&&&&&&&entered here into blur stage");
        //this will send a Mojo.propertychanged on fields
        //which have changed
        this.controller.commitChanges();
        
        switch (this.blurNeedSetEventCheck()) {
            case 1:
                //Mojo.Log.info("saving the current event");
                this.saveEvent(0, true);
                break;
                
            case 2:
                //Mojo.Log.info("creating an exception in a recurrence...");
                this.saveEvent(this.targetEvent.id, true);
                break;
        }
    },
    
    setup: function(){
        //Mojo.Log.info("datetime-assistant:setup");
        
		this.appMenuModel= { visible:true, 
            label: $L('Calendar'),
							items: [ Mojo.Menu.editItem,
									{label:$L('Preferences & Accounts'), command:Mojo.Menu.prefsCmd, disabled: true},
									{label:$L('Help'), command:Mojo.Menu.helpCmd, disabled:false}]
        }
        
		this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems:true}, this.appMenuModel);
        
        
        this.dateTimeView = this.controller.get('datetime_view');
        this.header = this.controller.get('edit_header');
        
        this.blurStage = this.blurStageBound.bind(this);
        this.controller.listen(this.controller.document, Mojo.Event.deactivate, this.blurStage);
		this.header.update(Mojo.View.render({template: 'datetime/header', object: this.targetEvent}));
        
        this.service = getCalendarService();
        this.requests = [];
        var date = new Date(this.targetEvent.startTimestamp);
        
        this.startDateModel = {
            date: new Date(this.targetModifiedTime.start)
        };
        
	this.controller.setupWidget('edit_startDate',{label: $L('Date'),modelProperty:'date'}, this.startDateModel);
        this.controller.listen('edit_startDate', Mojo.Event.propertyChange, this.startDateCallback.bindAsEventListener(this));
        
        this.endDateModel = {
            date: new Date(this.targetModifiedTime.end)
        };
    this.controller.setupWidget('edit_endDate', {label: $L('Date'),modelProperty:'date'}, this.endDateModel);
        this.controller.listen('edit_endDate', Mojo.Event.propertyChange, this.endDateCallback.bindAsEventListener(this));
        
        this.startTimeModel = {
            time: new Date(this.targetModifiedTime.start)
        };
    this.controller.setupWidget('edit_startTime', {label: $L('Time'),modelProperty:'time'}, this.startTimeModel);
        this.controller.listen('edit_startTime', Mojo.Event.propertyChange, this.startTimeCallback.bindAsEventListener(this));
        
        this.endTimeModel = {
            time: new Date(this.targetModifiedTime.end)
        };
    this.controller.setupWidget('edit_endTime', {label: $L('Time'), modelProperty:'time'}, this.endTimeModel);
        this.controller.listen('edit_endTime', Mojo.Event.propertyChange, this.endTimeCallback.bindAsEventListener(this));
        
        
        // All Day Checkbox
        
        this.allDayCheckboxAttribute = {
            modelProperty: "value"
        }
        this.allDayCheckboxModel = {
            value: this.targetEvent.allDay
        }
        this.controller.get('dtl_allday_cb').observe(Mojo.Event.propertyChange, this.handleAllDayTap.bindAsEventListener(this));
        this.controller.get('allDay_div').observe(Mojo.Event.tap, this.handleAllDayTap.bindAsEventListener(this));
        this.controller.setupWidget('dtl_allday_cb', this.allDayCheckboxAttribute, this.allDayCheckboxModel);
        
        this.updateTimedAllDay(false);
        
        
    },
    
    checktargetEventDirty: function(){
        //construct rrule
		if(this.targetEvent.rruleModel)
		{
            this.recurrenceRule.constructRRuleFromModel(this.targetEvent);
        }
        if (this.service.isEventDirty(this.oldEvent, this.targetEvent) || this.targetModifiedTime.changed == true) 
            return true;
        else {
            return false;
        }
    },
    handleCommand: function(event){
        if (event.command == Mojo.Menu.helpCmd) {
            getAppManagerService().launchHelp(this.controller);
        }
        else 
            if (event.type == Mojo.Event.back) {
                if (this.datetimeoutID) {
                    this.endDateSet(true);
                    
                }
                if (this.targetEvent.dirty && this.checktargetEventDirty()) {
                    //Mojo.Log.info('***************got here first');
                    
                    if (this.targetEvent.rruleModel) {
                        this.recurrenceRule.constructRRuleFromModel(this.targetEvent);
                    }
                    //we check if the oldevent is undefined because
                    //this might be the first time we are creating a rrule for this event
                    
                    if (this.targetEvent.rrule && this.targetEvent.rrule != "" &&
                    this.oldEvent != undefined) {
                    
                        //event.preventDefault();
                        Event.stop(event);
                        this.doDialog();
                    }
                    else {
                        Event.stop(event);
                        this.saveEvent(null);
                    }
                    
                }
            }
        
    },
    
    
    doDialog: function(){
        startdate = new Date(this.targetEvent.startTimestamp);
		start = Mojo.Format.formatDate(startdate, {date: "long"});
        //Mojo.Log.info("datetime-assistant: in doDialog");
        this.controller.showDialog({
            template: 'shared/recurrence-warning',
            assistant: new RecurrenceWarning(this, this.targetEvent.id),
            start: start
        
        });
    },
    
    handleAllDayTap: function(){
        //Mojo.Log.info("datetime-assistant:handleAllDayTap");
        this.targetEvent.dirty = true;
        
        //end date callback is on a delay. Make sure it's done before we change the value of allDay.
        if (this.datetimeoutID) 
            this.endDateSet(false);
        
        if (this.targetEvent.allDay == true) {
            this.targetEvent.allDay = false;
            
            //if we have a reserved start time, and it is not set to midnight, use the reserved start and end times
            if (this.targetEvent.alldayReservedStartTimestamp && (this.targetEvent.alldayReservedStartTimestamp != this.targetModifiedTime.start)) {
                this.targetModifiedTime.start = this.targetEvent.alldayReservedStartTimestamp;
                this.targetModifiedTime.end = this.targetEvent.alldayReservedEndTimestamp;
			} else{
            
                //if we do not have a reserved start time or the reserved time is midnight, 
                //calculate the start time using the current time (same as if this was a new event)
                //and the user's selected date. 
                var startTime = getCurrentDateTime();
                var startDate = new Date(this.targetModifiedTime.start);
                if (startTime.getMinutes() > 30) 
						startDate.set({	hour: startTime.getHours(), minute: 30, second: 0, millisecond: 0 });
                else 
						startDate.set({	hour: startTime.getHours(), minute: 0, second: 0, millisecond: 0 });
                this.targetModifiedTime.start = startDate.getTime();
                this.targetModifiedTime.end = startDate.addMinutes(getPrefs().defaultEventDuration).getTime();
            }
		} else {			
            this.targetEvent.allDay = true;
            
            //Save the start and end time into the reserve
            this.targetEvent.alldayReservedStartTimestamp = this.targetModifiedTime.start;
            this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
            
            //Use the start date, set time to 00:00:00
            var alldayTime = new Date(this.targetModifiedTime.start);
			alldayTime.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
            this.targetModifiedTime.start = alldayTime.getTime();
            
            //Use the end date, set time to 23:59:59 
            alldayTime = new Date(this.targetModifiedTime.end);
			alldayTime.set({ hour: 23, minute: 59, second: 59, millisecond: 0 });
            this.targetModifiedTime.end = alldayTime.getTime();
        }
        
        this.targetModifiedTime.changed = true;
        this.startTimeModel.time = new Date(this.targetModifiedTime.start);
        this.startDateModel.date = new Date(this.targetModifiedTime.start);
        this.endTimeModel.time = new Date(this.targetModifiedTime.end);
        this.endDateModel.date = new Date(this.targetModifiedTime.end);
        
        this.updateTimedAllDay(true);
        
        this.controller.modelChanged(this.startDateModel);
        this.controller.modelChanged(this.endDateModel);
		// We call modelChanged() on the time models later, inside updateTimedAllDay() (or following the animation).
		// This prevents the times from immediately jumping to teh all-day versions during the animation.
		
    },
    
    saveEvent: function(parentid, inCardMode){
        //if there is no subject name we need to assign a default name to it.
        if (this.targetEvent.subject == "" || this.targetEvent.subject == null) {
            if (this.targetEvent.id > 0) 
                this.targetEvent.subject = $L('Event name');
            else 
                this.targetEvent.subject = $L('New event');
        }
        if (parentid) {
            // we are creating an exception
            this.targetEvent.parentId = parentid;
            this.targetEvent.id = -1;
            this.targetEvent.rrule = '';
            this.targetEvent.exdates = '';
            
            this.targetEvent.rruleModel = null;
            this.targetEvent.originalstartTimestamp = this.originalstartTimestamp;
            this.targetEvent.endValidity = 0;
            
        }
        else {
        
            if (parentid <= 0 && this.targetEvent.isRecurringForever == true) 
                //we need to do this because if the end validity returned from the 
                //service is a long value, it seems to get truncated when retuned to 
                //JS layer and hence while setting it back 
                this.targetEvent.endValidity = "Long.MAX_VALUE";
        }
        if ((this.oldEvent && this.targetEvent.allDay != this.oldEvent.allDay) /*this is in case of an existing event*/ ||
        (this.oldAllday != undefined && this.oldAllday != this.targetEvent.allDay) /*this is in the case of a new event*/) {
            if (this.targetEvent.allDay == true) 
                this.targetEvent.alarm = getPrefs().defaultAllDayEventReminder;
            else 
                this.targetEvent.alarm = getPrefs().defaultEventReminder;
        }
        
        //instead of adding the exdates separately here
        //we append this while constructing the rrule string
        //while calling this.recurrenceRule.constructRRuleFromModel
        
        //if(this.targetEvent.exdates && this.targetEvent.rrule != this.oldEvent.rrule)
        //	this.recurrenceRule.addExdateToRRule(this.targetEvent);
                
        //Changes to the start date may require the rruleModel to be refreshed
        if (this.targetEvent.rruleModel && this.targetEvent.rruleModel.frequency && this.targetEvent.rruleModel.frequency != '') {
            this.updateRecurrenceWhenDateChanged(this.originalstartTimestamp, this.targetModifiedTime.start);
        }
        
		if ((!parentid || parentid <= 0) && !this.dateChanged && this.targetEvent.rrule) {
			var oldTimeStart = new Date(this.oldEvent.startTimestamp);
			var newTimeStart = new Date(this.targetModifiedTime.start);
			
			var duration = this.targetModifiedTime.end - this.targetModifiedTime.start;
			oldTimeStart.setHours(newTimeStart.getHours());
			oldTimeStart.setMinutes(newTimeStart.getMinutes());
			oldTimeStart.setSeconds(newTimeStart.getSeconds());
			var oldTimeEnd = oldTimeStart.clone();
			var oldTimeEnd = oldTimeEnd.addMilliseconds(duration);
			this.targetEvent.startTimestamp = oldTimeStart.getTime();
			this.targetEvent.endTimestamp = oldTimeEnd.getTime();
		}
		else {
			this.targetEvent.startTimestamp = this.targetModifiedTime.start;
			this.targetEvent.endTimestamp = this.targetModifiedTime.end;
		}
        
        var callback = (inCardMode) ? this.renderSetEvent.bind(this) : this.setEventCallback;
        this.requests.push(this.service.setEvent(this.targetEvent, callback, this.editSceneController));
        
        this.oldEvent = Object.clone(this.targetEvent);
        this.targetEvent.dirty = false;
        //we do this so that we can make sure we dont do multiple
        //saves on an event that is already saved.
        
        this.targetCallBack(null, this.oldEvent);
        
        this.targetEvent.pendingSave = true;
        if (!inCardMode) {
            if (this.callBackAfterUpdate != undefined) 
                this.callBackAfterUpdate(this.targetId);
            this.controller.stageController.popScene("datetime");
        }
        
        
        
    },
    renderSetEvent: function(response){
        //this callback is called only in the case
        //when we are in the scene and went into cardmode
        //and a setEvent was done.
        
        this.targetEvent.id = response.id;
    },
    
    cleanup: function(){
    
    
    },
    
    activate: function(){
    },
    
    deactivate: function(){
        //Mojo.Log.info("datetime-assistant:deactivate");	
        this.controller.stopListening(this.controller.document, Mojo.Event.deactivate, this.blurStage);
    },
    	
	//When the start date of the event is changed, WEEKLY:single day, WEEKLY:custom, MONTHLY repeating events 
	//must update their rruleModel. DAILY, YEARLY, and WEEKLY:weekdays repeating events do not need to be changed.
	//This function only changes the rruleModel.byday and/or rruleModel.bymonthday fields. All other fields are left unchanged.
	//If the model's byday/bymonthday fields are changed, the rrule will be reconstructed.
	//Params: removeDate - the day/date to be removed from byday/bymonthday
	//        addDate - the day/date to be added to the byday/bymonthday array.  
    updateRecurrenceWhenDateChanged: function(removeDate, addDate){
        var oldDate = new Date(removeDate);
        var newDate = new Date(addDate);
		var changed = false;
        
        switch (this.targetEvent.rruleModel.frequency) {
			
            case 'WEEKLY': // Do NOT Localize
                //Weekly: weekdays
                if (this.recurrenceRule.arraysEqual(this.targetEvent.rruleModel.byday, ['MO', 'TU', 'WE', 'TH', 'FR']) &&
                (this.targetEvent.rruleModel.interval == 1 || !this.targetEvent.rruleModel.interval)) {
                    //Weekdays -> do nothing.                    
                    break;
                }
                
                //Weekly: single day
                else if (this.targetEvent.rruleModel.byday.length === 1) {
                	this.targetEvent.rruleModel.byday = [];
                    this.targetEvent.rruleModel.byday.push(this.recurrenceRule.dayMap[newDate.getDay()]);
					changed = true;
                }                    
                
			    //Weekly: custom. 
				//Remove old date's weekday, add new date's weekday, leaving previous values intact
                else {
                    //find the index of the old date's weekday in the byday array					
                    var oldDayIndex = this.targetEvent.rruleModel.byday.indexOf(this.recurrenceRule.dayMap[oldDate.getDay()]);
                  
				    //remove the old day from the byday array
                    if (oldDayIndex > -1) 
                        this.targetEvent.rruleModel.byday.splice(oldDayIndex, 1);
                    
                    //Make sure the new day we're adding isn't already in the array                  
                    if (this.targetEvent.rruleModel.byday.indexOf(this.recurrenceRule.dayMap[newDate.getDay()]) == -1) {
                        //find the right spot to add the new day
                        var i = 0;
                        while (i < this.targetEvent.rruleModel.byday.length && 
								newDate.getDay() > this.recurrenceRule.dayMap.indexOf(this.targetEvent.rruleModel.byday[i])){							 
                            i++;
						}
                        //insert the new day                        
                        this.targetEvent.rruleModel.byday.splice(i, 0, this.recurrenceRule.dayMap[newDate.getDay()]);                        
                    }
					changed = true;
                }
            	break;
                
            case 'MONTHLY': // Do NOT Localize
                //Monthly by date
                if (this.targetEvent.rruleModel.bymonthday.length > 0) {
                    this.targetEvent.rruleModel.bymonthday = [];
                    this.targetEvent.rruleModel.bymonthday.push(newDate.toString("d"));
                }
                else {
                    var nth = getDOWCount(this.targetEvent.startTimestamp);
                    this.targetEvent.rruleModel.byday = [];
                    var byday = this.recurrenceRule.dayMap[newDate.getDay()];
                    this.targetEvent.rruleModel.byday.push(nth + byday);
                }
				changed = true;
                break;
                
            default:                
                break;
        }
		
		if(changed)
			this.recurrenceRule.constructRRuleFromModel(this.targetEvent);        
    },
    
    startDateCallback: function(event){
		this.dateChanged =true;
        this.targetEvent.dirty = true;
        if (this.changingStartDate) 
            return;
        
        var date = event.value;
        
        var duration = this.targetModifiedTime.end - this.targetModifiedTime.start;
        var newTimeStamp = new Date(this.targetModifiedTime.start);
        newTimeStamp.setFullYear(date.getFullYear());
        newTimeStamp.setDate(date.getDate());
        newTimeStamp.setMonth(date.getMonth());
        this.targetModifiedTime.start = newTimeStamp.getTime();
        this.targetModifiedTime.end = this.targetModifiedTime.start + duration;
        this.endDateModel.date = new Date(this.targetModifiedTime.end);
        this.changingEndDate = true;
        this.controller.modelChanged(this.endDateModel);
        this.changingEndDate = false;
        this.targetModifiedTime.changed = true;
        
        if (this.targetEvent.allDay) {
            //If this event is allday, change only the date component of the reserved timestamp. 
            //This preserves the user-set start/end times.
            newTimeStamp = new Date(this.targetEvent.alldayReservedStartTimestamp);
            newTimeStamp.setFullYear(date.getFullYear());
            newTimeStamp.setDate(date.getDate());
            newTimeStamp.setMonth(date.getMonth());
            this.targetEvent.alldayReservedStartTimestamp = newTimeStamp.getTime();
            
            newTimeStamp = new Date(this.targetEvent.alldayReservedEndTimestamp);
            newTimeStamp.setFullYear(date.getFullYear());
            newTimeStamp.setDate(date.getDate());
            newTimeStamp.setMonth(date.getMonth());
            this.targetEvent.alldayReservedEndTimestamp = newTimeStamp.getTime();
		} else {
            this.targetEvent.alldayReservedStartTimestamp = this.targetModifiedTime.start;
            this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
        }
    },
    
    endDateSet: function(isOnBack){
		this.dateChanged =true;
        //Mojo.Log.info('***************in End Date set');
        if (this.datetimeoutID) {
            var date = this.tentativeEndDate;
            var newTimeStamp = new Date(this.targetModifiedTime.end);
 			var prevEndYear = newTimeStamp.getFullYear();
            newTimeStamp.setFullYear(date.getFullYear());
            newTimeStamp.setDate(date.getDate());
            newTimeStamp.setMonth(date.getMonth());
            this.targetModifiedTime.end = newTimeStamp.getTime();
            
            if (this.targetEvent.allDay) {
                //If this event is allday, change only the date component of the reserved timestamp.
                //This preserves the user-set end time.
                newTimeStamp = new Date(this.targetEvent.alldayReservedEndTimestamp);
                newTimeStamp.setFullYear(date.getFullYear());
                newTimeStamp.setDate(date.getDate());
                newTimeStamp.setMonth(date.getMonth());
                this.targetEvent.alldayReservedEndTimestamp = newTimeStamp.getTime();
			} else {
                this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
            }
            
			newTimeStamp = new Date(this.targetModifiedTime.end);
            if (this.targetModifiedTime.end < this.targetModifiedTime.start) {
                //when end date/time is less than start date/time
                //we set the end date/time's value to be the start
           		// with the exception of the month....
				// fix for JIRA NOV-66811
				// if end month is less than start month, bump the end year by start year + 1
				var startDate = new Date(this.targetModifiedTime.start);
				if ((newTimeStamp.getMonth() < startDate.getMonth()) && (newTimeStamp.getFullYear() == prevEndYear)) {
					newTimeStamp.addYears(1);
					this.targetModifiedTime.end = newTimeStamp.getTime();
					this.endDateModel.date = newTimeStamp;					
					this.controller.modelChanged(this.endDateModel);
                    
                    if (this.targetEvent.allDay) {
                        //If this event is allday, change only the date component of the reserved timestamp.
                        //This preserves the user-set end time.
                        newTimeStamp = new Date(this.targetEvent.alldayReservedEndTimestamp);
						newTimeStamp.addYears(1);
                        this.targetEvent.alldayReservedEndTimestamp = newTimeStamp.getTime();
                    }
                    else {
                        this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
                    }
				}
				else {
 					var newStartStamp = new Date(this.targetModifiedTime.end);
					newStartStamp.setFullYear(date.getFullYear());
					newStartStamp.setDate(date.getDate());
					newStartStamp.setMonth(date.getMonth());
					
					//we need to set both the start date and time, not just the date
					newStartStamp.setHours(this.endTimeModel.time.getHours());
					newStartStamp.setMinutes(this.endTimeModel.time.getMinutes());
					newStartStamp.setSeconds(this.endTimeModel.time.getSeconds());
					this.targetModifiedTime.start = newStartStamp.getTime();
					
					if (this.targetEvent.allDay) {
						//If this event is allday, change only the date component of the reserved timestamp.
						//This preserves the user-set start time.
						newStartStamp = new Date(this.targetEvent.alldayReservedStartTimestamp);
						newStartStamp.setFullYear(date.getFullYear());
						newStartStamp.setDate(date.getDate());
						newStartStamp.setMonth(date.getMonth());
						this.targetEvent.alldayReservedStartTimestamp = newStartStamp.getTime();
					}
					else {
						this.targetEvent.alldayReservedStartTimestamp = this.targetModifiedTime.start;
					}
					
					this.startDateModel.date = newStartStamp;
					this.startTimeModel.time = new Date(newStartStamp);
					
					//we don't need to do this locking anymore
					//as we are using frameworkised date/time picker
					
					//this.changingStartDate = true;
					this.controller.modelChanged(this.startDateModel);
					this.controller.modelChanged(this.startTimeModel);
					//this.changingStartDate = false;
				}
            }
            
            if (isOnBack == false) 
                this.calcDuration();
            this.targetModifiedTime.changed = true;
            if (this.datetimeoutID) {
                this.controller.window.clearTimeout(this.datetimeoutID);
                this.datetimeoutID = 0;
            }
        }
    },
    
    endDateCallback: function(event){
        this.targetEvent.dirty = true;
        //if (this.changingEndDate)
        //	return;
        if (this.datetimeoutID) 
            this.controller.window.clearTimeout(this.datetimeoutID);
        this.tentativeEndDate = event.value;
        
        this.datetimeoutID = this.controller.window.setTimeout(this.endDateSet.bind(this, false), Timeout);
        
        //this.controller.listen('datetime_view',Mojo.Event.back, this.endDateSet.bindAsEventListener(this,this.tentativeEndDate,true));	
    
    },
    
    startTimeCallback: function(event){
    
        //if (this.changingStartTime) 
        //	return;
        
        this.targetEvent.dirty = true;
        var time = event.value;
        //Mojo.Log.info("start time call back, %s ",time);
        
        var duration = this.targetModifiedTime.end - this.targetModifiedTime.start;
        var newStartTimeStamp = new Date(this.targetModifiedTime.start);
        newStartTimeStamp.setHours(time.getHours());
        newStartTimeStamp.setMinutes(time.getMinutes());
        this.targetModifiedTime.start = newStartTimeStamp.getTime();
        this.targetModifiedTime.end = this.targetModifiedTime.start + duration;
        this.endTimeModel.time = new Date(this.targetModifiedTime.end);
        this.controller.modelChanged(this.endTimeModel);
        this.endDateModel.date = new Date(this.targetModifiedTime.end);
        //this.changingEndTime = true;
        this.controller.modelChanged(this.endDateModel);
        //this.changingEndTime = false;
        this.targetModifiedTime.changed = true;
        
        //Update the reserved timestamps
        this.targetEvent.alldayReservedStartTimestamp = this.targetModifiedTime.start;
        this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
    },
    
    endTimeCallback: function(event){
        Mojo.Log.info("endTimeCallBack");
        //if (this.changingEndTime) 
        //	return;
        
        this.targetEvent.dirty = true;
        var time = event.value;
        
        
        var newTimeStamp = new Date(this.targetModifiedTime.end);
        newTimeStamp.setHours(time.getHours());
        newTimeStamp.setMinutes(time.getMinutes());
        this.targetModifiedTime.end = newTimeStamp.getTime();
        if (this.targetModifiedTime.end < this.targetModifiedTime.start) {
            //this.targetModifiedTime.start = this.targetModifiedTime.end;
            //this.startTimeModel.time = new Date(this.targetModifiedTime.start);
            //this.changingStartTime = true;
            //consider it as setting for next 12 hour clock
            //example if in am set to pm .. if in pm set to next day am
            
            this.endTimeModel.time = new Date(newTimeStamp);
            this.endTimeModel.time.addHours(12);
            this.endDateModel.date = new Date(this.endTimeModel.time);
            this.targetModifiedTime.end = this.endTimeModel.time.getTime();
            //this.changingEndTime = true;
            this.controller.modelChanged(this.endTimeModel);
            this.controller.modelChanged(this.endDateModel);
            //this.changingEndTime = false;
        
        
        }
        
        this.calcDuration();
        this.targetModifiedTime.changed = true;
        
        //Update the reserved timestamps
        this.targetEvent.alldayReservedStartTimestamp = this.targetModifiedTime.start;
        this.targetEvent.alldayReservedEndTimestamp = this.targetModifiedTime.end;
    },
    
    recurrenceCancel: function(){
        this.targetEvent = Object.clone(this.oldEvent);
        this.targetEvent.dirty = false;
        var start = new Date(this.unchangedtargetModified.start);
        var end = new Date(this.unchangedtargetModified.end);
        
        this.targetModifiedTime.start = this.unchangedtargetModified.start;
        this.targetModifiedTime.end = this.unchangedtargetModified.end;
        
        this.startDateModel.date = this.startTimeModel.time = start;
        this.endDateModel.date = this.endTimeModel.time = end;
        
        this.controller.modelChanged(this.startDateModel);
        this.controller.modelChanged(this.endDateModel);
        this.controller.modelChanged(this.startTimeModel);
        this.controller.modelChanged(this.endTimeModel);
        this.targetModifiedTime.changed = false;
        //Mojo.Log.info("Old event all day %o, new Event all day %o",this.oldEvent.allDay,this.allDayCheckboxModel);
        if (this.oldEvent.allDay != this.allDayCheckboxModel.value) {
        
            this.allDayCheckboxModel.value = this.oldEvent.allDay;
            this.controller.modelChanged(this.allDayCheckboxModel);
            this.updateTimedAllDay(true);
        }
        this.targetCallBack(this.targetEvent, null);
        
    },


});
