/**		
 * rmFxIcalMail.js
 * 
<p>		SEND:	
<ul>		Reminderfox events stored in the users list can be send using the TB/mail facility.
<br>		Sending modes are:
<br>		- just send one or more events from the list to another
		  		user, this is the METHOD:PUBLISH. 
<br>		- send one event as "Invitation" or "Schedule", this is 
		  		based on RFC2446 (iTIP)
<p>			Current implementation supports: 
<br>	  	-- METHOD: PUBLISH, REQUEST, REPLY
</ul> 
		RECEIVE:	
<ul>		ICS-file with RFC2445 (iCalendar) data is read and added
			to the Reminderfox.ics file.
<br>		The ICS-data can be part of the body or attached as an ICS file.
<br>		The data is interpreted in conformance to RFC2446 and supports:
<br>		 -- METHOD: PUBLISH, REQUEST, REPLY, CANCEL
</ul>
		NOTE:	
<br>		Both RFC's are not covered in all aspects, for actual implementation
 			please refer to  'RmFx_iCal_iTIP_Implementation.pdf'
 
<p>		@since
 		2008-04-14	
<ul> 		- messageID added to event. This enables to call msg from reminder
 	  			and reminder from msg;
<br> 		- msg tagging with iCal METHOD;
<br> 		- D&D added;
<br> 		- Attendee can process CANCEL send by Organizer;
<br> 		- supports rmFxUtil.PromptAlert(msg) instead of plain 'alert';
<br>
		2009-03 D&D:  moved to  'utils/rmFxDragDrop.js'
</ul>
* 	@see 			'RmFx_iCal_iTIP_Implementation.pdf'
*/

var rmFx_fromMailadr;
var rmFx_iCalMETHOD;  
var rmFx_iCalAttendees;
var rmFx_iCalOrganizer;
var rmFxMessageId;
var rmFxIcalLastEvent;


/**
 * 	Processes message for iCal-content 
<P> 		1. reads data from 'msgHdr'
<br> 		2. reads mail ICS-data from 
<br>			(a.)  mail-inline (body)   
<br>			(b.)  first attachment including a iCal data set
<br>	If iCal found, passes to add the event, if no iCal will add a reminder
		for the message to the event list
		
<P>		@return	rv	true: if iCal/ICS data found
 */
function rmFxGetiCalMailed(info) {
    var rv = false;
    var ret = "\n"; 
    
    // --- get some msgHeader Infos ------	
	var msgHdr = gDBView.hdrForFirstSelectedMessage;
    // subject
    var rmFxSummary = msgHdr.mime2DecodedSubject;
    // from
    var rmFxFrom =  msgHdr.mime2DecodedAuthor;
    rmFx_fromMailadr =rmFxFrom;				// need for processing eg REPLY
    
    // recipients
    var rmFxTo = msgHdr.mime2DecodedRecipients;
    
    // messageID
    rmFxMessageId = "<" + msgHdr.messageId.replace(new RegExp(/\"/g),"") + ">";
    // date   
    var dateStr =  msgHdr.date;
    var time = new Date();
    time.setTime(dateStr / 1000);		
   
    var timeString = reminderFox_mail_getTimeString( time );
    var dateVariableString;
    try {
        dateVariableString = reminderFox_prefs.getCharPref(REMINDER_FOX_PREF + 
				"." + REMINDER_FOX_LIST_DATE_LABEL);
    } catch(e) {}
         
    var rmFxDate =reminderFox_getDateVariable( null, time, dateVariableString ) 
			+ "  " + timeString;

	var mInvitation = "     " +reminderFox_getBundle().getString("rf.add.mail.message.date") + ": " + rmFxDate + ret
					+ "     " +reminderFox_getBundle().getString("rf.add.mail.message.sender") + ": " + rmFxFrom + ret
					+ "     " +reminderFox_getBundle().getString("rf.add.mail.message.recipients") + ": " + rmFxTo + ret	;

	var _baseURI= this.content.document.body.baseURI;
	var _content= this.content.document.body.textContent;
	var _contentType= this.content.document.contentType;
	var _documentURI= this.content.document.documentURI;
	var _title= this.content.document.title;

	// 1a.   check if events in the body, pass to "Add Reminder"
	info = info + "%1a."
	var rvTxt = rmFxGetiCalFromTextBody(_content, mInvitation, info);
	
	// the event is read from the body, or import was canceled so done!
	if ((rvTxt == true) || (rvTxt == 'CANCEL')) return; 
	
	//2.	check Attachments for events, pass to "Add Reminder"

	if (currentAttachments.length > 0) {
		var i=0;
		while (i < currentAttachments.length) {	
			var xx = currentAttachments[i].contentType.toLowerCase();	
			if (  (xx == "text/calendar") 					/* 'normal apps */					
				|| (xx == "application/ics") 				/* Google Calendar */ 	
				|| (xx == "application/octet-stream")) { 	/* some calendars do not identify as calendar type */ 		
				var _contentType =	xx;
				var _url =	currentAttachments[i].url;
				var _name =	"iCalMsgAttReceive" + i + ".txt";
				var _uri =	currentAttachments[i].uri; 
	
				var temp = Components.classes["@mozilla.org/file/directory_service;1"]
							 .getService(Components.interfaces.nsIProperties)
							 .get("TmpD", Components.interfaces.nsIFile);
				
				var attfile = messenger.saveAttachmentToFolder(
					_contentType, _url, _name, _uri, temp, null); 
					
				// delete the temporary file  automatically on exit			<<< //gW_PB for Postbox 		
    			externalAppLauncher.deleteTemporaryFileOnExit(attfile);
								
				//  we need  Timeout ---> +++2do  use eventhandler instead!!
				info = info + "%2."
				setTimeout(rmFxGetiCalFromAttachment,500, mInvitation, attfile, _content, rmFxMessageId, info);    
		//		rmFxGetiCalFromAttachment(mInvitation, attfile, _content, rmFxMessageId);    
		
			rv = true;
			}
			i++;
		}		
	}

	//  3. coming to here  with rv=false, probably the msg was D&D from mail:3pane
	//   +++2do check  +++2do check  +++2do check  +++2do check  +++2do check  +++2do check  +++2do check  +++2do check   
	if (rv == false) {		
		reminderFox_thunderBirdAddEmailReminder();
	}
	
	rmFxIcalLastEvent = null;
	return rv;                  
}

/**
 * Read iCal/ICS data from attachment, if no data found alternativly check the body of the message
 * 
 * @param mInvitation	--> METHOD as with RFC defined
 * @param attfile		--> temp file() of attachment
 * @param content		--> messages body text
 * @param rmFxMessageId	--> the msgHdr.messageId
 * @return
 */
function rmFxGetiCalFromAttachment(mInvitation, attfile, content, rmFxMessageId, info) { 
	var rv; 
	var reminderFoxEvents = new Array();
	var reminderFoxTodosArray = { };
	reminderFox_readInRemindersAndTodosICSFromFile(reminderFoxEvents, reminderFoxTodosArray, attfile, true);
	
	// check if we've successfully found any reminders or todo events		
	var foundEventsInAttachment = reminderFoxEvents.length != 0;
	if ( !foundEventsInAttachment ) {
		for ( var n in reminderFoxTodosArray ) {
			var importedTodos = reminderFoxTodosArray[n];
			if ( importedTodos.length > 0 ) {
				foundEventsInAttachment = true;
				break;
			}
		}
	}
	
	// if so, read-in from the attachment
	if ( foundEventsInAttachment ) {	
		info = info + "%att."
		rv = rmFxGetiCalEvents( mInvitation, reminderFoxEvents, reminderFoxTodosArray, info);  
	} 
	rmFx_iCalTagging (rv);
	
	return rv;
}

function rmFx_iCalTagging (rv) {
	if ((rmFx_iCalMETHOD != "") && (rv == true)){
		rmFx_msgTAGing('iCal-' + rmFx_iCalMETHOD, true, '#3333FF');	
	}
}


/**
 * 	Support D&D a URL download link (ICS/webcal) to 'Subscribe' or 'add reminders'
<br>     ex:  http://dl.erweiterungen.de/kalenderdateien/Feiertage_2006-2010_DE.ics
<br>     ex:  webcal://sports.yahoo.com/nfl/teams/pit/ical.ics
 * 
 * 	@param	url
 * 
 *  @since	 2008-10-30
 *  @since   2010-11-06	 support subscription and import from (url ics/webcal)
 */
var rmFx_icsOrwebcalURL;
var rmFx_icsOrwebcalURLname;

function rmFxSubscribeOrAddReminder(url) {
   //gWtodo :   Check 'url' for validity *****  
   
   if ( url != null && url.length > 0 ) {
      var webcalIndex = url.indexOf( "webcal://");   // handle webcal address
      if ( webcalIndex != -1 ) {
         url = "http://" + url.substring( "webcal://".length );
      }
      rmFx_icsOrwebcalURL = url;
      
      rmFx_icsOrwebcalURLname = url.substring( "http://".length).toUpperCase()
                  .replace(new RegExp(/\//g),"_")
                  .replace(new RegExp(/\./g),"-");
      var icsPart = rmFx_icsOrwebcalURLname.indexOf( "-ICS");
               rmFx_icsOrwebcalURLname = icsPart >- 1 ? 
                  rmFx_icsOrwebcalURLname.substring(0,icsPart) : rmFx_icsOrwebcalURLname ;
               
               var subscribedCal = new Array();
    
               reminderFox_download_Startup_headless_URL(
                     REMINDER_FOX_UI_MODE_HEADLESS_SHOW_ERRORS   /* 2 */,
            rmFx_downloadSubscribedCalendarCallback, 
            url, 
            subscribedCal, 
            null);
   } else {
      //  .... need to handle non-url??   //gWtodo 
   }
}

function rmFx_downloadSubscribedCalendarCallback( statustxtString, actionID, downloadedReminders ) {
   rmFxCore.statusSet ("ICS/webcal download callback: " + actionID + " >" + statustxtString +"<");
    
   if ( actionID == 2 ) { // reminders were downloaded
      var msg1=  ("\n\nICS/webcal downloaded for > " + rmFx_icsOrwebcalURLname
            + "<\n # of Events: " + downloadedReminders.length);              //$$$locale 

      // --- ask user to subscribe or add as reminder --- 
      var title = reminderFox_getBundle().getString('rf.options.subscribe.title');
      var msg =   reminderFox_getBundle().getString('rf.options.subscribe.description1')
               + '\n' + reminderFox_getBundle().getString('rf.options.subscribe.description2')
               + msg1; 
      var key0 =  reminderFox_getBundle().getString('rf.options.subscribe');  
      var key1 =  reminderFox_getBundle().getString('rf.button.cancel'); 
      var key2 =  reminderFox_getBundle().getString('rf.options.subscribe.add2reminders'); 
     
      switch (rmFxUtil.ConfirmEx(title, msg, key0, key1, key2) ) {
         case 0:  
            reminderFox_subscribeWithReminderFox(rmFx_icsOrwebcalURL); break;
         case 1:
            alert ("Canceled    ;-)");  
         break;
         case 2:
            //  How about VEVENTS and VTODOS ??   -- do we get VTODOS here ??
            var reminderFoxTodosArray = new Array();
            rmFxGetiCalEvents( "" /*mInvitation*/, downloadedReminders /*reminderFoxEvents*/, reminderFoxTodosArray, "ics/webcal" /*info*/)                
      }
   }
}


function rmFxGetiCalFromTextBody(_content, mInvitation, info) {	
	var reminderFoxEvents = new Array();
	var reminderFoxTodosArray = { };
	
	reminderFox_readInRemindersAndTodosICSFromString(reminderFoxEvents, reminderFoxTodosArray, _content, true);

   info = info + "%body"
	var rv = rmFxGetiCalEvents(mInvitation,  reminderFoxEvents, reminderFoxTodosArray, info);
	return rv;
}

function rmFxGetiCalEvents( mInvitation, reminderFoxEvents, reminderFoxTodosArray, info) {
	info = info + "%events"
	//  here we need to know the METHOD of the event
	//		with "send" 	it's set by processing before
	//		with "receive"	it's written to "this.reminderfox_Method"
	rmFx_iCalMETHOD = this.reminderfox_Method; 

	// now iterate over each VEVENT, for Invitations  
	//    get infos into reminder.notes ... depended of "METHOD"	
	var numEvents = reminderFoxEvents.length;
	for ( var i = 0; i < numEvents; i++ ) {
		var reminder = reminderFoxEvents[i];	
		
		// prevent to import reminders without UID .. as they may come from Outlook
		if (reminder.id == null) {
			reminder.id = reminderFox_generateUniqueReminderId() ;
		}
		var result = reminderFox_processExtraScheduleInfo(reminder, mInvitation, rmFx_iCalMETHOD );
		if (result != "") {
			rmFxUtil.PromptAlert(result);
			return false;
		}
	}		
   // count the VTODOs 
   var numTodos = 0;
   for ( var list in reminderFoxTodosArray ) {
      var cList = reminderFoxTodosArray[list];
      for (var next in cList) {
         numTodos++;
      }
   }
   var singleEventOrTodo =  ((numEvents > 1) || (numTodos > 0)) ? true : false;

	// #1   handle multiple VEVENT  OR  VTODO -->>  import them all with normal import    

	if (singleEventOrTodo) {  
		// check [Revert] status  
	   // import with tagging the 'CATEGORIES' item, ask user / get prefs 

      var params = { mode: 'CANCEL', 
         categories:"importICS", 
         numEvents:numEvents, 
         numTodos:numTodos,
         info: "## " + info };
         
      window.openDialog("chrome://reminderfox/content/mail/rmFxImportWithCategory.xul",
      "rmFx_ReminderImportwCategory", "chrome,resizable,modal", params);        
      // mode :  CANCEL or OK 
      if (params.mode == 'CANCEL'){ return 'CANCEL';} //  false;}
  
	   // ...  add CATEGORY item for import
      var categoryItem = params.categories;
      
	   for ( var i = 0; i < reminderFoxEvents.length; i++ ) {
         reminder = rmFxUtil.addCategory4Import (reminderFoxEvents[i], categoryItem);
	   }     
	   for ( var list in reminderFoxTodosArray ) {
	      var cList = reminderFoxTodosArray[list];
	      for (var next in cList) {
	         rmFxUtil.addCategory4Import (cList[next], categoryItem);
	      }
	   }

		reminderFox_addMultipleEvents(reminderFoxEvents, reminderFoxTodosArray);
		
		return true;
	}     
    
	// #2a  single Event/Schedule.
	// 		Check for Reminders passed. None --> return false;
	var reminder = reminderFoxEvents[0];	// the 'read' reminder
	if (reminder == null) return false;		// no Reminders, return
	
	// check if previous event is the same as this one (POSTBOX workaround)
	try {
		if ((reminder.id == rmFxIcalLastEvent.id) 
			&& (reminder.extraInfo == rmFxIcalLastEvent.extraInfo)) {
			// rmFxUtil.PromptAlert(" here we have an duplicated event");
			rmFxIcalLastEvent = null;
			return false;
		}
	} catch (ex) {}
	rmFxIcalLastEvent = reminder;
	
	// #2b 	loop with all reminders in list and check if already in reminder.ics
	// 		known: return false
	// 		new:   call the "Add Reminder" dialog, return "true" if finally added, 
	//		 		"false" if user suspend adding
	var rmFx_statusMsg="";  
	reminder.messageID = rmFxMessageId;
	
	var newExtra = rmFx_extraInfoArray(reminder);	// the 'extraInfo' items	
	
	var activeReminders = reminderFox_getReminderEvents();
    
   for (var nR =0; nR < activeReminders.length; nR++) {	
		if (reminder.id == activeReminders[nR].id ) { 
			// reminder already known, check for details and alert it.
        
			var oldExtra = rmFx_extraInfoArray(activeReminders[nR]);	
			var same  = (rmFx_extraInfo(newExtra,"DTSTAMP")) 
						== (rmFx_extraInfo(oldExtra,"DTSTAMP"))
						&& (rmFx_extraInfo(newExtra,"SEQUENCE")) 
						== (rmFx_extraInfo(oldExtra,"SEQUENCE"))	;		//++++2do  ++++2do  ++++2do  ++++2do  ++++2do  
																		//  check for oldSEQ > newSEQ  ==> ERR
			var older = (rmFx_extraInfo(newExtra,"DTSTAMP")) 
						<= (rmFx_extraInfo(oldExtra,"DTSTAMP"))
						|| (rmFx_extraInfo(newExtra,"SEQUENCE")) 
						 < (rmFx_extraInfo(oldExtra,"SEQUENCE"))	;		//++++2do  ++++2do  ++++2do  ++++2do  ++++2do  
																	//        for oldDTSTAMP > new ==> ERR
        
			switch (rmFx_iCalMETHOD) {
	        	
		        case "CANCEL":  {
					// check if msg/cancel was already processed 
					if  (same == true) {
						rmFx_statusMsg =	"[iCal  CANCEL] " + "  »" + activeReminders[nR].summary	 + "«"
										+	"\n\n" + mInvitation	 				
										+	"\n\n" + reminderFox_getBundle().getString("rf.schedule.attendee.processed");								
						rmFxUtil.PromptAlert(rmFx_statusMsg);
						return false;
					}
					if  (older == true) {
						rmFx_statusMsg =	"[iCal  CANCEL] " + "   »" + activeReminders[nR].summary	 + "«"
										+	"\n\n" + mInvitation											
										+	"\n\n" + reminderFox_getBundle().getString("rf.schedule.older1.processed")
										+	"\n"   + reminderFox_getBundle().getString("rf.schedule.older2.processed")	;							
						rmFxUtil.PromptAlert(rmFx_statusMsg);
						return false;
					}
					// save all event-items {reminder.xx} if not included 
					// in CANCEL-msg {activeReminders[nR].xx}
					// 	reminder.categories, reminder.location, reminder.url, reminder.priority, 
					// also set Description to [iCal CANCEL] .... 
					// 
					if (reminder.categories == null) {reminder.categories = activeReminders[nR].categories};
					if (reminder.location == null) {reminder.location = activeReminders[nR].location};
					if (reminder.url == null) {reminder.url = activeReminders[nR].url};
					if (reminder.priority == null) {reminder.priority = activeReminders[nR].priority};
					reminder.notes = reminder.notes +'\n\n' +  activeReminders[nR].notes;
		
		        	break;
		        }
		        
		        case "REQUEST":  {
					// check if msg/reply was already processed 
					if  (same == true) {
						rmFx_statusMsg =  "[iCal  REQUEST] " + "   »" + activeReminders[nR].summary + "«"
											+ "\n\n" + mInvitation
											+ "\n\n" + reminderFox_getBundle().getString("rf.schedule.attendee.processed");
						rmFxUtil.PromptAlert(rmFx_statusMsg);
						return false;
					}
					if  (older == true) {
						rmFx_statusMsg =  "[iCal  REQUEST] " + "	»" + activeReminders[nR].summary	+ "«"
									+   "\n\n" + mInvitation
									+   "\n\n" + reminderFox_getBundle().getString("rf.schedule.older1.processed")
									+   "\n"	+ reminderFox_getBundle().getString("rf.schedule.older2.processed");
						rmFxUtil.PromptAlert(rmFx_statusMsg);
						return false;
					}
					break;
				}

				case "REPLY":  {
					// check if msg/reply was already processed.
					// result on 'same' only doesn't say if the current 
					// processed msg was already processed.
					// So we check if a TAG 'iCal-Reply' is added to the msg.
	
					// this.currentHeaderData.tags.headerValue
					var msgHdr = gDBView.hdrForFirstSelectedMessage;
					var msgKeys = msgHdr.getStringProperty("keywords");
					if   ((same == true) && (msgKeys.indexOf("iCal-REPLY") > -1)) {
	
						var msg =  "[REPLY] " + "   »" + activeReminders[nR].summary	 + "«"
									+ "\n\n" + mInvitation
									+ "\n\n" + reminderFox_getBundle().getString("rf.schedule.attendee.processed");
						if (confirm(msg + "\n\n" + reminderFox_getBundle().getString("rf.schedule.processReply")) == false) {
							return false;
						}  
					}
	
					var attNo;
					
					rmFx_fromMailadr = msgHdr.mime2DecodedAuthor;
					
					var fromAttendee = rmFx_fromMailadr.substring(
								rmFx_fromMailadr.indexOf( "<" ) + 1,
								rmFx_fromMailadr.indexOf( ">" ));
					var fromATT = fromAttendee.toUpperCase();
					
					for ( var i = 0; i < rmFx_iCalAttendees.length; i++ ) {
						if (rmFx_iCalAttendees[i].toUpperCase().indexOf(fromATT) > -1) attNo=i;
					}
	  				// is the "from" address == the ATTENDEE ??, 
	  				// if NOT  --> unknown CU ( + a "Party Crasher") ... 
					//	 So we have to ask the user which ATTENDEE has to be taken here
					if (rmFx_iCalAttendees[attNo] == null) {
						
						var results = { attendees:rmFx_iCalAttendees };
						window.openDialog("chrome://reminderfox/content/mail/rmFxReplyAttendees.xul",
						"rmFx-set-getReplyAttendee", "chrome,resizable,modal", results);
						// CANCEL and not seleteced ==  -1
						// OK and selected == #
						if (results.attendeeNo == -1){
							return false;}

						var xx= rmFx_iCalAttendees[results.attendeeNo];
						
						var fndIndex = xx.toUpperCase().lastIndexOf( "MAILTO:" ); 
	        			if (fndIndex == -1) { return false};
	            		var fromATT =  xx.substring( fndIndex + 7).toUpperCase();
					}
					// clone the stored event and update some items from
					// newEvent [REPLY] to oldEvent [the stored]
					//  - save the .notes
					var replyReminderNotes = reminder.notes;

					//  - ATTENDEE  grap the new 
					for ( var i = 0; i < newExtra.length; i++ ) {
						if (newExtra[i].toUpperCase().indexOf(fromATT) > -1) var iNew=i;
					}
					for ( var i = 0; i < oldExtra.length; i++ ) {
						if (oldExtra[i].toUpperCase().indexOf(fromATT) > -1) var iOld=i;
					}
					oldExtra[iOld] = newExtra[iNew];
	
					// rebuild the extraInfo string
					for ( var i = 0; i < oldExtra.length; i++ ) {
						if (i==0) {activeReminders[nR].extraInfo = oldExtra[i];
						} else {
						activeReminders[nR].extraInfo += "\\n" + oldExtra[i];}
					}	
	
					reminder = activeReminders[nR];
					reminder.notes = replyReminderNotes
						+ "\n _._._._._._._ " + reminderFox_getBundle().getString("rf.schedule.previous") + " _._._._._._._\n" 
						+ activeReminders[nR].notes;  
					break;
				}	//METHOD:REPLY
				
				default: {//METHOD: ... all other (for the moment)
			        //  get info from reminder 'in the list'
			        
					var rSEQ = rmFx_extraInfo(oldExtra,'sequence')
					var rDTSTAMPz = rmFx_extraInfo(oldExtra,'dtstamp');

					var rDTSTAMP = "";
					if (rDTSTAMPz != null ) {
				   	    rDTSTAMP= reminderFox_parseDateTimes(rDTSTAMPz) ;
					}
					//  get info from 'new' reminder
					var nSEQ = rmFx_extraInfo(newExtra,'sequence'); 
					var nDTSTAMPz = rmFx_extraInfo(newExtra,'dtstamp');	   
				     
					var nDTSTAMP = "";
					if ( nDTSTAMPz != null ) {
				   		 nDTSTAMP =  reminderFox_parseDateTimes(nDTSTAMPz) ;
					}  
					var newStr = reminderFox_getBundle().getString("rf.schedule.new");
					var oldStr = reminderFox_getBundle().getString("rf.schedule.old");

					var info1 = reminderFox_getBundle().getString("rf.reminder") + " [ " + activeReminders[nR].summary + " ] \n"
						+reminderFox_getBundle().getString("rf.schedule.check.summary")+ nR + "\n\n";  
					
					var info2 =  "\n\nSEQUENCE\n    "+ newStr +":  [#"     + nSEQ      + "]     "+ oldStr +": [#" + rSEQ
						+   "]\nDTSTAMP \n     "+ newStr +":  [" + nDTSTAMP + "]     "+ oldStr +":  [" + rDTSTAMP + "]";	
				
					if ((nSEQ *1) > (rSEQ*1)) { // new SEQUENCE should be greater
						rmFx_statusMsg = reminderFox_getBundle().getString("rf.schedule.new") + " '" + reminderfox_Method + "' "
										+ " SEQUENCE" + " #" + nSEQ ;
				//	  alert (info1  + rmFx_statusMsg +  info2) ;
					} else {
						if (nDTSTAMPz  <= rDTSTAMPz  ) {
							rmFx_statusMsg = 'SEQUENCE / DTSTAMP ' + reminderFox_getBundle().getString("rf.schedule.notValid");
							rmFxUtil.PromptAlert(info1  + rmFx_statusMsg +  info2) ;
							return false;
							
						} else {
							rmFx_statusMsg = reminderFox_getBundle().getString('rf.schedule.newDate') + '  [' + nDTSTAMP + ']';
						  	//              alert (info1  + rmFx_statusMsg +  info2) ;
						}
					}
	
					if (rmFx_statusMsg != ""  && activeReminders[nR].notes != null)  {
						reminder.notes += "\n _._._._._._._ " 
											+ reminderFox_getBundle().getString("rf.schedule.previous") 
											  +  " _._._._._._._\n" + 
						activeReminders[nR].notes   
		    		}   		
				} // METHOD  ... all other
        	} // switch  
	    } // reminder already known	
    } //#2a   -- loop with all reminders in  list 
	
	var rv = reminderFox_addReminderHeadlessly( reminder, true, true );  // gW 2009-02-25 edit flag added
	return rv;  // should be true if added to list, so tag the msg
}


function reminderFox_processExtraScheduleInfo(reminder, mInvitation, rmFx_Method ) { 
/* 	here we prepare the reminder.notes   to reflect special schedule items 
 */ 
 	var msgReturn="";
 	
	if ( reminder.extraInfo == null ) return msgReturn;

//  here we need to know the METHOD of the event
// 		it's written to "this.reminderfox_Method"  
// 			eg.  REPLY, REQUEST, CANCEL, COUNTER, DECLINECOUNTER

	//var rmFx_iCalMETHOD = this.reminderfox_Method;	
			
	var addPerson = "";
	var addOption="";		var iSchComment = null;		var iSchStatus = null;  
	var nDTSTAMP;			var iSchStart;				var iSchEnd;    		
	var option ="";
	var ret = "\n";	
	
	var extraInfos =  rmFx_extraInfoArray(reminder);
		
	var nDTSTAMPz = rmFx_extraInfo(extraInfos,"DTSTAMP"); 
	if ( nDTSTAMPz != "" ) {
      	 nDTSTAMP  =  reminderFox_parseDateTimes(nDTSTAMPz) ;  
	}
	var nSEQ = rmFx_extraInfo(extraInfos,"SEQUENCE"); 
	
	option = rmFx_extraInfo(extraInfos,"COMMENT"); 
	if ( option != "" )
		iSchComment =  option + ret;             

	// next items go with  'addOption' to Notes
			function addOptItem (option, optText) {
				//	var option = rmFx_extraInfo(extraInfos,"PRIORITY"); 
				return ((option == null) || (option == ""))
					? ""
					: "    " + optText + " [" + option +  "]";
			}
	addOption += addOptItem (rmFx_extraInfo(extraInfos,"PRIORITY"), "Priority");
	addOption += addOptItem (rmFx_extraInfo(extraInfos,"CLASS"), "Class");
	addOption += addOptItem (rmFx_extraInfo(extraInfos,"CUTYPE"), "CuType");
	addOption += addOptItem (rmFx_extraInfo(extraInfos,"TRANSP"), "TRANSP");

	// ---->>  process PERSONS infos  ------
		var myMailAccounts = rmFxMsg.myMailIDs();
		         
		rmFx_iCalOrganizer = rmFx_extraInfo(extraInfos,"ORGANIZER", ";");
		
		// check if ORGANIZER is part of my accounts, 
		//    if METHOD:REPLY  it has to be! Else ERROR, don't add to reminder.ics
		if (rmFx_Method == "REPLY") {
			var fndIndex = rmFx_iCalOrganizer.toUpperCase().lastIndexOf( "MAILTO:" ); 
				if (fndIndex != -1) {
				var fndString = "<" + rmFx_iCalOrganizer.substring( fndIndex + 7) + ">";
				if (myMailAccounts.indexOf(fndString) == -1 ) {
					msgReturn = "[REPLY] " +reminderFox_getBundle().getString("rf.schedule.replyWrongOrganizer")
		    			+  ": \n" + fndString;
					return msgReturn;
				}
			}
		}  
	  
		// get PARTSTAT for myAccount
		var _Attendees = rmFx_extraInfo(extraInfos,"ATTENDEE", ";", true);  // true==read multiple entries
		var attPart ="";
		
		rmFx_iCalAttendees = _Attendees.split("\n");
		
		if (rmFx_iCalAttendees.length > 0  || nSEQ != null){
			for (var n=0; n<rmFx_iCalAttendees.length; n++){
				rmFx_iCalAttendees[n] = rmFx_iCalAttendees[n].toUpperCase();
				var fnd =  rmFx_iCalAttendees[n].lastIndexOf("MAILTO:");
				if (fnd != -1) {
					var address = rmFx_iCalAttendees[n].substring(fnd+7);
					if (address.indexOf(myMailAccounts)) {

						fnd =  rmFx_iCalAttendees[n].indexOf("PARTSTAT=");
						if (fnd != -1) {
							var attPart = rmFx_iCalAttendees[n].substring(fnd+9);
							fnd = attPart.indexOf(";");
							if (fnd == -1) {attPart.indexOf(":")};
							var attPart = attPart.substring(0,fnd);
						}
					}
				}
			}
		}
		var wPART ="";
		if (rmFx_Method != "REQUEST") { var wPART = "  " + attPart; }
		var extraInfoSchedule = "[iCal] " + rmFx_Method + wPART + ": " + reminderFox_getBundle().getString("rf.schedule") ;	
		if ( nDTSTAMP != null && nDTSTAMP.length > 0 ) {
			extraInfoSchedule += " " + reminderFox_getBundle().getString("rf.schedule.asof") + "  " +nDTSTAMP;
		}
		if ( nSEQ != null ) {
			extraInfoSchedule += "    [# " + nSEQ + "]" + ret ;
		}
		extraInfoSchedule += mInvitation + ret;	

	// <<<----  process PERSONS infos  ------


	switch (rmFx_Method) {
		case "REQUEST": 
		case "PUBLISH": {	// this is send to ATTENDEE(s), can be 
											// - new 
											// - revised 
			
			// ICS containing "ATTENDEE" is an invitation !	
			var anInvitation = ((reminder.extraInfo.indexOf("ATTENDEE:") > -1 ) 
				|| (reminder.extraInfo.indexOf("ATTENDEE;") > -1)) ? true : false;
			
			if (anInvitation) { // check for invitation 
						// ++++++++++++ Google Calendar Special  ++++++++++++
				 		if ( reminder.notes != null && reminder.notes.length > 0 ) {
							var iGMail = reminder.notes.toLowerCase().indexOf("http://www.google.com/calendar/event?action=view");
							if ( iGMail != -1) {
								var iGMail1 = reminder.notes.toLowerCase().indexOf(" ",iGMail);
								var httpGMail = reminder.notes.substring(iGMail,iGMail1);
								reminder.url = httpGMail;
							}
				 		}
						// ++++++++++++ Google Calendar Special  ++++++++++++

				if (addOption != "" ) 
					extraInfoSchedule += reminderFox_getBundle().getString("rf.schedule.options") +
					" ______________________" + ret + addOption + ret;
	
				if (iSchComment != null )
					extraInfoSchedule += reminderFox_getBundle().getString("rf.schedule.comment") +						
					" ______________________" + ret + iSchComment + ret;

				if (reminder.notes != null && reminder.notes.length > 0 ) {
					reminder.notes = "> " + reminder.notes.replace(new RegExp(/\n/g),"\n>");
		 		}
		 		
		 		if (reminder.notes != null ) {
					extraInfoSchedule +=	 reminderFox_getBundle().getString("rf.schedule.description") +					
					"  ______________________" + ret
					+  reminder.notes	+ ret;
		 		} 
				reminder.notes = extraInfoSchedule;	
				
				// add 'Category' item signifying that this is an invitation
				var categoryItem = reminderFox_getBundle().getString("rf.mail.ical.send.subject.invitation"); //   "invitation";  
				reminder = rmFxUtil.addCategory4Import (reminder, categoryItem);

				return msgReturn;
				
			} else {  // this is NOT an invitation
			}
			break;
			
		} //case:REQUEST" & "PUBLISH"

		case "REPLY": {	// this is send back to ORGANIZER 
			
			reminder.notes = extraInfoSchedule;	
			return msgReturn;
			break;					
		}	//case "REPLY"
		
		case "CANCEL": {	// this 'cancel's the local event/invitation
			
			reminder.notes = extraInfoSchedule;	
			return msgReturn;
			break;
		}	//case "CANCEL"
		
	}	// switch (rmFx_Method)	
	return msgReturn;
}
    
function reminderFox_addMultipleEvents(reminderEvents, reminderTodos) {    
        // merge
	var existingEvents = reminderFox_getReminderEvents();
	var existingTodos = reminderFox_getReminderTodos();  //  ALL  todos
	var rvEvent = reminderFox_mergeEvents(existingEvents, reminderEvents  );
	var rvTodo = reminderFox_mergeTodos( existingTodos, reminderTodos );
 
	reminderFoxEvents = existingEvents;
	reminderFoxTodosArray = existingTodos;      
   
	reminderFox_importRemindersUpdateAll(false, null );   
	
// write to status !!	
   var xEvents= reminderFox_getBundle().getString("rf.html.heading.reminders");
   var xToDos = reminderFox_getBundle().getString("rf.html.heading.todos");
   var xImported  = reminderFox_getBundle().getString("rf.reminders.imported");    //"imported";
   var xExists  = reminderFox_getBundle().getString("rf.reminders.exists");      //"already exists";
   
   var msgText =  xEvents + " : " + rvEvent.importNo + " " + xImported
         + ",  " + rvEvent.existNo + " " + xExists +"."  
         + "\n" + xToDos + " : " + rvTodo.importNo  + " " + xImported
         + ",  " + rvTodo.existNo + " " + xExists + "." ;
				
	rmFxCore.statusSet (msgText);
}

//  ------------- GET TODO(s) ------------------------------
/**
 * 
 */
function rmFx_getSelectedTodos () { 

	var tabList = document.getElementById("tabList");    
	var tab = tabList.selectedItem;
	var tabLabel =  tab.label;
		
	var todosToBeSend = getAllSelectedTodos();
	
	if (todosToBeSend.length == 0) return;
	//  todosToBeSend[0].extraInfo
	for (var i = 0; i < todosToBeSend.length; i++) {
		if (todosToBeSend[i].extraInfo == null) {
			todosToBeSend[i].extraInfo = REMINDERFOX_EXTENDED + "LISTID:" + tabLabel;
		} else {
			if (todosToBeSend[i].extraInfo.indexOf(REMINDERFOX_EXTENDED + "LISTID") == -1) {
				todosToBeSend[i].extraInfo += "\\n" + REMINDERFOX_EXTENDED + "LISTID:" + tabLabel;
			}
		}
	}
	var todoArrayArray = new Array();
	todoArrayArray[0] = todosToBeSend;
	
	return todoArrayArray;
} 



//  ------------- SEND / EXPORT  iCal ------------------------------
/**
 *  Send/export one or more 'reminder(s)' as they are
 * 
 * @param selectedReminders 
 * @param organizer         
 * @param mode              if 'xExport' stores reminders to file
 * @param reminderTyp       'reminder' | 'todo'
 *
 */
function rmFx_sendAsItIs (selectedReminders, organizer, mode, reminderTyp) {
	var methodTyp = "ICS";	
	var attendees = null;

    if (mode == 'xExport') {    // generate an ICS file here  
      
      var nReminders = selectedReminders.length; 
      if (reminderTyp == 'todo') {
            var iCalString = reminderFox_constructReminderOutput( "", selectedReminders, true, true, "PUBLISH" );
            var nReminders = selectedReminders[0].length; 
      }  else {
            var iCalString = reminderFox_constructReminderOutput( selectedReminders, "", true, true, "PUBLISH" );
            var nReminders = selectedReminders.length; 
      }
      var exportFile = reminderFox_prefsBranch.getCharPref("exportEventsFile");
        
      rmFxUtil.dump2Console ('Darwin', "exportReminders to File   >>" + exportFile + "<<  "
               + " #of reminders:" + nReminders);         //gWTEST darwin

      var iCalToEmailFile = rmFxUtil.makeMsgFile (rmFxUtil.encodeUTF8(iCalString), exportFile);
      if (iCalToEmailFile == null) {
            rmFxUtil.PromptAlert("Export failed. File '" + exportFile + "' path not valid!");
      }  else {
      	// write status 
      	rmFxCore.statusSet(reminderTyp + " " + "exported: " + nReminders + " to file: " + exportFile)
      }
      return;
   }
   rmFx_sendEventNow(selectedReminders, "", 'ICS' /*methodTyp*/, organizer, attendees, reminderTyp);		
} 

var selectedReminders = null;

/**
 *   With the selected Reminder/Todo's 
 *     'Export to file' or  'Send a Mail' as an INVITATION/SCHEDULE
 * 
 * @param   event     has '.id' for selected ReminderTyp, if 'null' called from function
 * @param   _selectedTyp        //    'invite'   | 'info'
 * @param   _reminderTyp        //    'reminder' | 'todo'
 * @param   _Reminders          //      
 *
 * @return
 */
function rmFx_ExportOrSend (event, _selectedTyp, _reminderTyp, _Reminders) {

//	var selectedReminders="";
   var methodTyp = "PUBLISH";	 // default=PUBLISH ... other METHOD:PUBLISH, REQUEST, REPLY
   var attendees = null;
   var organizer = null;
   var selectedTyp;     // 'invite'   | 'info'
   var reminderTyp;     // 'reminder' | 'todo'
   var eventLength;     // use to show # of events in XUL title     
    
   if (event == null) { // function call (eg. from 'View')
      selectedTyp = _selectedTyp;
      reminderTyp = _reminderTyp;
      selectedReminders = _Reminders;
	    
      if (reminderTyp == 'reminder') eventLength = selectedReminders.length;
      if (reminderTyp == 'todo') eventLength = selectedReminders[0].length;
	    
   } else {  // called from ReminderList popup menu 

      if (event.currentTarget.id == "treechildren-contextmenu-sendReminder")  {
         selectedTyp = 'invite'; 
         reminderTyp = 'reminder';
			
         selectedReminders = getAllSelectedReminders();
         var eventLength = selectedReminders.length;
         if (eventLength == 0) return;  // no reminders selected!
	        		
         if (selectedReminders.length > 1)  {
            selectedTyp = 'info';   // only 'single' events can be send as invitation
         }
      } 
	
      if (event.currentTarget.id == "treechildren-contextmenu-sendTodos") {
	        selectedTyp = 'info'; 
	        reminderTyp = 'todo';
	
			selectedReminders = rmFx_getSelectedTodos();

			if (selectedReminders == null) {
				rmFxCore.statusSet (reminderFox_getBundle().getString("rf.schedule.resendwithDialog")) // ("No Todo's selected!"); 
				return;
			}
			
			var eventLength = selectedReminders[0].length;
		} 
    }
	
    if (selectedTyp == 'invite') {
    	
    /*  have to check if the selected "Reminder" was already send as invitation/schedule;
     *  that's the case if ORGANIZER is already included in "selectedReminders"
     */
		if (selectedReminders[0].extraInfo!= null) { 
			if (selectedReminders[0].extraInfo.indexOf("ORGANIZER") != -1) { 
				var msg = reminderFox_getBundle().getString("rf.schedule.wasSend") 
					+ "\n"   + reminderFox_getBundle().getString("rf.schedule.resendwithDialog")	
					+ "\n\n" + reminderFox_getBundle().getString("rf.schedule.sendAsEvent");
				
				if (confirm(msg) == false) {	
					var msg = 		reminderFox_getBundle().getString("rf.schedule.wantDelete")
						+ "\n\n"+ 	reminderFox_getBundle().getString("rf.schedule.okDelete");
					
					if (confirm(msg ) == true) {  // this is the 'delete invitation' part 
						var extraInfoArrayInv = rmFx_extraInfoArray(selectedReminders[0]);
						var extraInfoArray = new Array ();	var j=0;
						
						for (var i=0; i < extraInfoArrayInv.length; i++) {
							if (extraInfoArrayInv[i].indexOf("ORGANIZER")	> -1 ||
								extraInfoArrayInv[i].indexOf("ATTENDEE")	> -1 ||
								extraInfoArrayInv[i].indexOf("DTSTAMP")		> -1 ||
								extraInfoArrayInv[i].indexOf("STATUS")		> -1 ||
								extraInfoArrayInv[i].indexOf("CLASS")		> -1 ||
								extraInfoArrayInv[i].indexOf("COMMENT")		> -1 ||
								extraInfoArrayInv[i].indexOf("SEQUENCE")	> -1 )
								{ 
								} else {
								extraInfoArray[j] = extraInfoArrayInv[i]; j++;	
							}							
						}
						// delete the 'invitation' category also
						var xCategories = selectedReminders[0].categories;
						
						var categoryItem = reminderFox_getBundle().getString("rf.mail.ical.send.subject.invitation"); //   "invitation";
						if (xCategories.indexOf(categoryItem) > -1) {
							selectedReminders[0].categories = xCategories.replace(categoryItem, '');
						}
						
						// write the selectedReminder back to currentReminder without 'extra' strings					
						selectedReminders[0].extraInfo= extraInfoArray.join("\n");
						var reminderTodos=null;
						reminderFox_addMultipleEvents(selectedReminders, reminderTodos)
	
						rmFxUtil.PromptAlert(reminderFox_getBundle().getString("rf.schedule.hasDeleted")
							  + "\n\n" + reminderFox_getBundle().getString("rf.schedule.checkDeleted"));
					}
					return;
				} 
				selectedTyp ='info';  // was already send, don't allow to send as 'invite'
			}
		}
	}
	// Reminder(s)  'send' or 'export'
	//   if 'CANCEL' or 'close window' pressed -->> terminate	
	var results = {	organizer: null, 
					attendees: null, 
					mode: null, 
					selectedTyp: selectedTyp,
					reminderTyp: reminderTyp,
					eventLength: eventLength,
					schComment: ""};
	window.openDialog("chrome://reminderfox/content/mail/invitation.xul",
            	"reminderFox-set-invitationmailAppString", "chrome,resizable,modal", results);        

	if (results.mode == 'CANCEL') return;	
	
   if (results.mode == 'xExport') {         // export to ICS file 
      rmFx_sendAsItIs (selectedReminders, results.organizer, results.mode, reminderTyp)
      return;
   }

   if (results.selectedTyp == 'info') {	// send "as-it-is" ===> PUBLISH
   
      var attendees = null;
      if (reminderTyp == 'reminder') {
      // this.selectedReminders[0].url $[1] = [string] "mailto:abc@xyz.de"
			if ((this.selectedReminders.length == 1) && (!!this.selectedReminders[0].url)){
			    if (this.selectedReminders[0].url.indexOf('mailto:') == 0) 
			        attendees = this.selectedReminders[0].url.substring(7);
			}
			rmFx_sendEventNow(selectedReminders, "", 'ICS' /*methodTyp*/, organizer, attendees, reminderTyp);	
		}
			
      if (reminderTyp == 'todo') {
      // this.selectedReminders[0][0].url $[1] = [string] "mailto:abc@xyz.de"
			if ((this.selectedReminders[0].length == 1) && (!!this.selectedReminders[0][0].url)){
			    if (this.selectedReminders[0][0].url.indexOf('mailto:') == 0) 
			        attendees = this.selectedReminders[0][0].url.substring(7);
			}
         rmFx_sendEventNow("", selectedReminders,  'ICS' /*methodTyp*/, organizer, attendees, reminderTyp);
      }
      return;
	}

	//	send  INVITATION/SCHEDULE  ===> REQUEST
	if (results.selectedTyp == 'invite') {methodTyp = 'REQUEST';}	
		         
	organizer = results.organizer;
	if (organizer == "") {
		rmFxUtil.PromptAlert(reminderFox_getBundle().getString("rf.schedule.organizer.required")
		+ "\n" + reminderFox_getBundle().getString("rf.schedule.organizer.mailAdr"));
		return;
	}	

	if (results.attendees != null && results.attendees != "") {
		methodTyp = "REQUEST"; 		// attendees where entered --> REQUEST
		} else {
		methodTyp = "PUBLISH"; 	
	}
	//  add invitation info to 'extraInfo' item
	var originalReminder = selectedReminders[0];	
	var updatedReminder = reminderFox_cloneReminderFoxEvent(selectedReminders[0] );	

	if ( updatedReminder.extraInfo == null ) { 
		updatedReminder.extraInfo = "";
	}
	else {
		updatedReminder.extraInfo += "\\n";
	}
	//2008-12-16   clear trailing/leading spaces
	var organizerName = reminderFox_trim(organizer.split("<")[0]);
	var organizerMail = reminderFox_trim(organizer.split("<")[1]);

	if (organizerMail == null) {
			organizerMail = organizerName;
			organizerName ="";
	}
	if (organizerMail.charAt(organizerMail.length-1) == ">") {
		organizerMail = organizerMail.substring(0,organizerMail.length-1)
	}
	var xString ="ORGANIZER";
	if (organizerName != "") {xString += ";CN=" + organizerName}
	if (organizerMail != "") {xString += ":MAILTO:" + organizerMail}

	updatedReminder.extraInfo = updatedReminder.extraInfo + xString;
	
	// add SEQUENCE=1 and DTSTAMP (current date/time in 'Z')
	var currentDate = new Date();
	var tzOffset = new Date().getTimezoneOffset(); 
	currentDate.setMinutes( currentDate.getMinutes() + tzOffset );

	var dtStamp = reminderFox_getDateAsString(currentDate)+ "Z";
	updatedReminder.extraInfo += "\\nSEQUENCE:" + 1 +"\\nDTSTAMP:" + dtStamp;

	// add ATTENDEE(s)
	if (methodTyp == "REQUEST") {
		attendees = results.attendees.replace(/(^\s+)|(\s+$)/g, '');

		if ( updatedReminder.extraInfo == null ) { 
				updatedReminder.extraInfo = "";
		}  else {
				updatedReminder.extraInfo += "\\n";
		}
		//  ATTENDEE;RSVP=TRUE:MAILTO:abcde@fghi.xx
		var attendeeArray = attendees.split(",");
		for ( var i = 0; i < attendeeArray.length; i++  ) {
			if (attendeeArray[i] == "") {break;}
			var attendeeMail ="";
			var attendeeName ="";

			var attendeeX = attendeeArray[i].split("<");
			if (attendeeX.length == 1) {	// only mailAdr
				var attendeeMail = attendeeX[0].replace(/(^\s+)|(\s+$)/g, '').replace(">", '');
			} else {						// mailName and adr
				var attendeeName = attendeeX[0].replace(/(^\s+)|(\s+$)/g, '');
			 	var attendeeMail = attendeeX[1].replace(/(^\s+)|(\s+$)/g, '').replace(">", '');
			}
			var xString ="ATTENDEE";
			if (attendeeName != "") {xString += ";CN=" + attendeeName}
			if (attendeeMail != "") {xString += ";RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:MAILTO:" + attendeeMail}

			if ( i != 0 ) {
				updatedReminder.extraInfo += "\\n";
			}
			updatedReminder.extraInfo = updatedReminder.extraInfo + xString; 
		}
	}

	// add 'comment'  from invitation.xul dialog
	if (results.schComment != "") {
		updatedReminder.extraInfo += "\\nCOMMENT:" + results.schComment;
	}
	// add other items 
	reminderFox_processExtraScheduleInfo(updatedReminder, "", methodTyp );
	
	// add category
	var categoryItem = reminderFox_getBundle().getString("rf.mail.ical.send.subject.invitation"); //   "invitation";  
    updatedReminder = rmFxUtil.addCategory4Import (updatedReminder, categoryItem);

	//  REPLACE the current entry 
	removeListItemsForReminder(originalReminder); 
	// remove from model list
	var reminders = reminderFox_getReminderEvents();	
	for( var i = 0; i < reminders.length; i++) {
		if ( reminders[i].id == originalReminder.id ) {
			reminderFox_removeElement(reminders, i);
			break;
		}
	}

	// add reminder in sorted order...
	reminders = reminderFox_getReminderEvents();
	if ( updatedReminder.remindUntilCompleted != REMINDERFOX_REMIND_UNTIL_COMPLETE_NONE ) {
		updatedReminder.remindUntilCompleted = REMINDERFOX_REMIND_UNTIL_COMPLETE_TO_BE_MARKED;
	}
	var sortedIndex = reminderFox_getSortedIndexOfNewReminder( reminders, updatedReminder, false );
	reminderFox_insertIntoArray( reminders, updatedReminder, sortedIndex );
	
	updatedReminder.snoozeTime = null;
	createListItem(updatedReminder);

	var currentDate = oeDatePicker.gSelectedDate;
	if ( currentDate == null ) {
		currentDate = new Date();
	}	

	var newDate = new Date();
	if ( updatedReminder.alarm != null ) {
		updatedReminder.alarmLastAcknowledge = newDate.getTime();
		// if there's a snooze... and lastack > snooze, erase snooze...  
		// this means...  well it should be if date changed at all, then need to clear snooze...
	}
	updatedReminder.lastModified = reminderFox_getDateAsString(newDate );
	var reminder = reminderFox_processReminderDescription(updatedReminder,  currentDate.getFullYear(), false);		
	var modified = updateReminderInList( reminder );
	sortReminderIfNeccessary( updatedReminder.id);

	refreshCalendar();
	modifiedReminders();

	selectedReminders[0] = updatedReminder;		// need array	
	rmFx_sendEventNow(selectedReminders, "", methodTyp, organizer, attendees, selectedTyp);
}

/**
 * Preparing the message content and passing to the send or compose mail function
 * 
 * @param reminderToBeSend	passed as array!!
 * @param todosToBeSend		passed as array!!
 * @param methodTyp			'PUBLISH' | 'REQUEST' | 'REPLY' | 'ICS' (for sending 'view')
 * @param fromAddress
 * @param attendees
 * @param selectedTyp		'invite' = send one event as invitation | 'info' = send one/more event
 * @return
 */
function rmFx_sendEventNow(reminderToBeSend, todosToBeSend, methodTyp, fromAddress, attendees, selectedTyp) { 

	var statusMsg = "";
	if ((fromAddress != "") && (fromAddress != null)) {
		statusMsg += reminderFox_getBundle().getString("rf.mail.ical.sendby") 
					 + " " + fromAddress;
	}	else {
		statusMsg += reminderFox_getBundle().getString("rf.mail.ical.send")  + " ";		// "Sending"
	}		 
	statusMsg += " " + reminderFox_getBundle().getString("rf.mail.ical.sending");
	rmFxCore.statusSet (statusMsg);

	var footer = "  " + "______________________________________________________\n" 
						+ reminderFox_getBundle().getString("rf.mail.ical.send.body");

	// --- setup parameters for message ----------------- 
	var eMailSubject ="";

	if (methodTyp == "ICS") {
	    eMailSubject = "[ics]  ";
	}	
	if (methodTyp == "PUBLISH") {
	    eMailSubject = "[iCal]  " + methodTyp + ": ";		// $$$locale  iCal PUBLISH
	}

	if ((reminderToBeSend != null) && (reminderToBeSend != "")) {
		var uid = reminderToBeSend[0].id;
		var extraInfo = rmFx_extraInfoArray(reminderToBeSend[0]);
		
		if (selectedTyp == 'reminder') { methodTyp = "PUBLISH"; }
		var iCalString = reminderFox_constructReminderOutput( reminderToBeSend, "", true, true, methodTyp ); 
	}
	
	if ((todosToBeSend != null) && (todosToBeSend != "")) {
		var uid = todosToBeSend[0][0].id;
		var extraInfo = "";
		if (selectedTyp == 'todo') { methodTyp = "PUBLISH"; }
		var iCalString = reminderFox_constructReminderOutput( "", todosToBeSend, true, true, methodTyp ); 
	}

	
	if (methodTyp == 'REQUEST' ) {
	    eMailSubject = "[iCal]  " + methodTyp + ": ";	//$$$locale  iCal eg. REQUEST
	    selectedTyp = 'invite';
	}    
	if (methodTyp == 'REPLY') {
	    eMailSubject = "[iCal]  ";
	    selectedTyp = 'invite';

	    var xAtt =rmFx_extraInfoArray(reminderToBeSend[0]);
	    var Item = "ATTENDEE";
	    var attPart="";
	    if (xAtt != null) {
		    if (xAtt.length > -1) {
				for (var n =0; n < xAtt.length; n++) {
					if (xAtt[n].indexOf( Item )  == 0) {
						var fnd =  xAtt[n].indexOf("PARTSTAT=");
						if (fnd != -1) {
							var attPart = xAtt[n].substring(fnd+9);
							fnd = attPart.indexOf(";");
							if (fnd == -1) {attPart.indexOf(":")};
							var attPart = attPart.substring(0,fnd);	
						}
					}
				}
			}
		}
    	eMailSubject +=  attPart  + ": ";		//$$$locale 	iCal eg. ACCEPTED / DECLINED
	}  
	
	////////////////// 'invite' was selected ////////////////////////////////////
	// sending without extra compose
	if (selectedTyp == 'invite') {  
	    eMailSubject += reminderToBeSend[0].summary 
				+ " / " + reminderFox_getBundle().getString("rf.schedule.statusOf")
				+ " "   + reminderFox_parseDateTimes(rmFx_extraInfo(extraInfo,"DTSTAMP"))
				+ " [#" + rmFx_extraInfo(extraInfo,"SEQUENCE") +"]";
				
		var body  = "*" + reminderFox_getBundle().getString("rf.mail.ical.send.subject.invitation") 
			+ "*  »" + reminderToBeSend[0].summary  + "«"
	 		+ "\n"	+ reminderFox_getBundle().getString("rf.mail.ical.send.sentBy") + "  " + fromAddress + "\n";

		// setup for different invitation items ....
			function addBody (option, optText) {
				return ((option == null) || (option == ""))
					? ""
					: "\n" + optText + option;
			}
		var priority = reminderToBeSend[0].priority;
		var priorityStr = (priority == 1) 
			? reminderFox_getBundle().getString("rf.add.mail.message.priority")
			: "";

		body += addBody (priorityStr, "*" + reminderFox_getBundle().getString("rf.add.mail.message.priority.label")+ "*  ");
		body += addBody (reminderToBeSend[0].location, "*" + reminderFox_getBundle().getString("rf.mail.ical.send.location") + "* ");
		body += addBody (reminderToBeSend[0].url, "*" + reminderFox_getBundle().getString("rf.add.reminders.tooltip.url") + "* ");
		body += addBody (reminderToBeSend[0].notes, "\n*" + reminderFox_getBundle().getString("rf.add.mail.message.notes") 
										+"* ___________________________ \n");
		
		/** ---------- sending without extra compose --------------------------**/
		var tmpMsgFile = 	rmFxMsg.FileCreate( 
										eMailSubject, 
										fromAddress, 
										attendees,
										priority,  
										body,
										footer, 
										uid, 
										iCalString, methodTyp);

		rmFxMsg.FileSend (eMailSubject, 
								fromAddress, 
								attendees,
								priority,		
								tmpMsgFile,
								uid);
							
		rmFxCore.statusSet (reminderFox_getBundle().getString("rf.mail.ical.sendby") + " " + fromAddress); 		//  "Send by"
		return;			
	}
 

	/////////// 'reminder' or 'todo' has been selected /////////////
	//  go for compose
	//     one event: just take the reminder.summary as 'subject'
	//     no ATTENDEES (toAddress) ... have to add with 'composemessage'
	
	// prepare 'body' and 'subject' of message
	
	var body  = reminderFox_getBundle().getString("rf.add.mail.message.body") + "\n";

	if ((fromAddress != "") && (fromAddress != null)) {
		body  +=  reminderFox_getBundle().getString("rf.mail.ical.send.sentBy") 
				+ "  " + fromAddress +"\n";
	} 

	var _subject = "";
	if (selectedTyp == 'todo') {
		if (todosToBeSend[0].length == 0) {
			statusMsg = reminderFox_getBundle().getString("rf.mail.ical.noitems");
			rmFxCore.statusSet (statusMsg);
			return;  // no todo's selected
		}
		if (todosToBeSend[0].length == 1) {	
			_subject = todosToBeSend[0][0].summary
		} else {
			_subject = todosToBeSend[0].length;
		}
	} 
	if (selectedTyp == 'reminder') { 
		if (reminderToBeSend.length == 0) {
			statusMsg = reminderFox_getBundle().getString("rf.mail.ical.noitems"); //"No items to be send."
			rmFxCore.statusSet (statusMsg);	
			return;}	// no events selected
		if (reminderToBeSend.length == 1) {
			_subject = reminderToBeSend[0].summary
		} else {
			_subject = reminderToBeSend.length; 
		}
	}
	var msgInfo = reminderFox_getBundle().getString("rf.schedule.event.send." + selectedTyp)
			+ " :  " + _subject;	
			
//	var viewLabel; 
//	(rmFxViewLabel != "")
//			? viewLabel=(" [" + reminderFox_getBundle().getString("rf.views.name") + ": " + rmFxViewLabel + "] : ") 
//			: viewLabel=(" : ");	
	// body  += selectedTyp.toUpperCase() + viewLabel + _subject + "\n\n";	
	body  += msgInfo + "\n\n";	
					
	eMailSubject += msgInfo;
		

	// ---------- compose ------------------------------------------------
	var iCalFile =   reminderFox_getReminderStoreFile();
	iCalFile.leafName = "reminderfoxEvents.ics";

	rmFxUtil.dump2Console ('Darwin', "msg Compose iCalToEmailFile   >>" +iCalFile.path+ "<<");			//gWTEST darwin	

	var iCalToEmailFile = rmFxUtil.makeMsgFile (rmFxUtil.encodeUTF8(iCalString), iCalFile.path);
    if (iCalToEmailFile == null) {
        rmFxUtil.PromptAlert("Compose failed. File '" + iCalFile.path + "' path not valid!");
        return;
    }

	rmFxMsg.Compose(eMailSubject, fromAddress,  attendees,
		priority, body, footer, uid, iCalToEmailFile, methodTyp);

	rmFxCore.statusSet (reminderFox_getBundle().getString("rf.add.mail.message.compose")) /*"Compose message"*/
}

function reminderFox_parseDateTimes(stringDT) { /*  20051208T224616  or  20051208T224616Z = UTC */
     var thisDate = reminderFox_getStringAsDate(stringDT);
     
    var timeString = reminderFox_mail_getTimeString( thisDate );
    var dateVariableString;
    try {
        dateVariableString = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LIST_DATE_LABEL);
    } catch(e) {
    }
	var remFoxDate =reminderFox_getDateVariable( null, thisDate, dateVariableString ) + "  " + timeString;
	return remFoxDate;

	return stringDT;
}

function rmFx_extraInfoArray(reminder){
/* ------ converts the extraInfo string to an array 
 */
	if  (!!reminder.extraInfo) {
		var extraInfoArray = reminder.extraInfo.split("\\n");	  
		return extraInfoArray;  
	} else {
		return null;
	}
}


function rmFx_extraInfo(extraInfos, item, delimiter, multiple){  // if multiple==true --> build array
// ------ reads from extraInfos array using item 
	if (delimiter == null) delimiter = ":";
	var Item = item.toUpperCase();
	var result="";
	if (extraInfos != null) {
		if (extraInfos.length > -1) {
			for (var n =0; n < extraInfos.length; n++) {
				if (extraInfos[n].indexOf( Item )  == 0) {
					if (multiple) {result +=  extraInfos[n].substring(extraInfos[n].indexOf( delimiter ) +1 ) + "\n"; 
					} else {
						result =  extraInfos[n].substring(extraInfos[n].indexOf( delimiter ) +1); 
						break;
					}
				}
			}
		}
	}
	return result;
}


//============================================================

// -------- select Attendee from menu -----------------

function rmFx_replyAttDialogClose() {
	window.arguments[0].attendeeNo = 
		document.getElementById('rmFx_replyAttendeeGroup').selectedIndex;
}
function rmFx_replyAttDialogCancel() {
	window.arguments[0].attendeeNo = -1;
}

function rmFx_replyAttendeeAdd() {
	var attendeesList = window.arguments[0].attendees;
	var attGroup = document.getElementById("rmFx_replyAttendeeGroup");
	for ( var i = 0; i < attendeesList.length; i++ ) {	
		
    	var fndIndex = attendeesList[i].toUpperCase().lastIndexOf( "MAILTO:" ); 
        if (fndIndex != -1) {
            var fndString =  attendeesList[i].substring( fndIndex + 7);

			var e = document.createElement("radio");
				e.setAttribute("group", "rmFx_replyAttendeeGroup");
				e.setAttribute("label", fndString);
			attGroup.appendChild(e);
        }
	}
}

// ---- setup 'mail-app' and 'myAccounts' ---- (for FX) ----
function rmFx_mailAppSetup() {

	var results = { organizer: 	null, 
						attendees:		null, 
						mode: 			'mailApp', 
						selectedTyp: 	'info',
						schComment: 	''};
	window.openDialog("chrome://reminderfox/content/mail/invitation.xul",
            	"reminderFox-set-invitationmailAppString", "chrome,resizable,modal", results);        

	if (results.mode == 'CANCEL') { return 'CANCEL';} // user pressed 'CANCEL'

	return 	reminderFox_prefsBranch
				.getCharPref(REMINDER_FOX_MAIL_SENDER);
}

// ---- setup 'mail-app' and 'myAccounts' ---- (for FX) ----
function rmFx_sendExportDialog() {

    var results = { organizer:  null, 
                    attendees:      null, 
                    mode:           'mailApp', 
                    selectedTyp:    'info',
                    schComment:     ''};
    window.openDialog("chrome://reminderfox/content/mail/invitation.xul",
                "reminderFox-set-invitationmailAppString", "chrome,resizable,modal", results);        

    if (results.mode == 'CANCEL') { return 'CANCEL';} // user pressed 'CANCEL'

    return  results;
}

// ---- invitation XUL dialogs -------------

function rmFx_invitationLoadDialog() {
   var rmFx_exportFile;
		
	if (window.arguments[0].mode == "mailApp") {
	 	this.title = reminderFox_getBundle().getString("rf.schedule.setDefaults");
	}

	var orgMenu= document.getElementById('organizerMenu');

	//  with rmFxMsg.myMailIDs the mailIdentities/organizer 
	//  and the mailApplication location are checked and read
	var myAccount = rmFxMsg.myMailIDs();

	if (!!myAccount) {
		var myAccounts = myAccount.split(",");
		for (var i = 0; i < myAccounts.length; i++) {
		     var myAccount = myAccounts[i];
			 var menuitem = orgMenu.appendItem(myAccount, i);
		}
		orgMenu.selectedIndex = 0;
	}

	// with TB/SM the pulldown menu is NOT editable !!!
	if (rmFxMsg.messenger()) {
	 	document.getElementById('organizerMenu').removeAttribute( "editable");
	 	
			// 	document.getElementById('reminderFox-mailApp.Location-Box')		/* //gWTEST DARWIN  do not hide for testing */
			//			.setAttribute( "hidden", true);
	}
	
   try {
      rmFx_exportFile = reminderFox_prefsBranch.getCharPref("exportEventsFile");
   } catch (ex) {  
   	rmFx_exportFile = rmFxUtil.filePath4storePath ("reminderfoxEvents.ics");
   }
	
	document.getElementById("exportFile").setAttribute ("value", rmFx_exportFile);

   if (window.arguments[0].reminderTyp == 'reminder') {
      document.title = document.title 
         + " :  " + reminderFox_getBundle().getString("rf.html.heading.reminders")  	/*Reminders*/
         + " (" + window.arguments[0].eventLength + ") ";                     /*Todo's*/
   } else {
      document.title = document.title 
         + " :  " + reminderFox_getBundle().getString("rf.html.heading.todos") 
         + " (" + window.arguments[0].eventLength + ") ";             
   }

	rmFx_invitationSwitch();  // setting to 'Export'
}	


function rmFx_invitationCloseDialog(mode) {  // mode = CANCEL or OK

	if (mode == 'CANCEL') {
		window.arguments[0].mode = mode;
		return;
	}
	
    if (document.getElementById('sendSection').checked) {

        window.arguments[0].mode = 'xSend';
	
		var organizer = document.getElementById('organizerMenu').label;
		
		if ((organizer == "") && (organizer.indexOf('<') == -1) && (organizer.indexOf('>') == -1)) {
			organizer = "<" + organizer + ">";
		}
        window.arguments[0].organizer = organizer;
		
		reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MAIL_SENDER, organizer);

		if (document.getElementById('inviteEnable').checked == true) {
			window.arguments[0].selectedTyp = 'invite';		
			window.arguments[0].attendees = document.getElementById('attendees').value;
		} else {
			window.arguments[0].selectedTyp = 'info';
			window.arguments[0].attendees = "";
		}

		if ( document.getElementById('commentText').value != "") {
			window.arguments[0].schComment  = document.getElementById('commentText').value;
		}else {
			window.arguments[0].schComment  = "";
		} 
		
		var mailApp = document.getElementById('mailApp.location.input').value
		reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MAIL_PATH, mailApp);    	
    }
     
    if (document.getElementById('exportSection').checked) {

        window.arguments[0].mode = 'xExport';
        window.arguments[0].selectedTyp = 'info';
        
        var exportFile = document.getElementById('exportFile').value;
        
        var prefsName = "exportEventsFile"    // set as prefs 'extensions.reminderFox.exportEventsFile'
        reminderFox_prefsBranch.setCharPref(prefsName, exportFile);
    }
}         
            
function rmFx_invitationSwitch() {

	if (window.arguments[0].selectedTyp == 'info') {
				
		document.getElementById('reminderFox-invitationGroup')
			.setAttribute( "hidden", true );
		document.getElementById('reminderFox-commentGroup')
			.setAttribute( "hidden", true );
		sizeToContent();
		
		rmFx_sendExportChange("exportSection");
		return;
    } 
	
	if ( document.getElementById('inviteEnable').checked ==  true ) {					
        document.getElementById('reminderFox-commentGroup')
                    .setAttribute( "hidden", false );
        document.getElementById('reminderFox-attendeeGroup')
                    .setAttribute( "hidden", false );      			
	}
	
	if ( document.getElementById('inviteEnable').checked ==  false ) {
		document.getElementById('reminderFox-commentGroup')
			.setAttribute( "hidden", true );
		document.getElementById('reminderFox-attendeeGroup')
			.setAttribute( "hidden", true );			
	}

	sizeToContent();
}


// --------- functions for TB,SM   ... and 'non' mail (like FX)  ---------

/*
Firefox {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
Thunderbird	{3550f703-e582-4d05-9a08-453d09bdfdc6}
Nvu {136c295a-4a5a-41cf-bf24-5cee526720d5}
Mozilla Suite {86c18b42-e466-45a9-ae7a-9b95ba6f5640}
SeaMonkey {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
Sunbird {718e30fb-e89b-41dd-9da7-e25a45638b28}
Netscape Browser {3db10fab-e461-4c80-8b97-957ad5f8ea47}
Flock Browser {a463f10c-3994-11da-9945-000d60ca027b}	
*/

/**
 * get the  messenger apps	location
 * first check prefs if already set
 * 
 */ 
function rmFx_MessengerApp(){
//------------------------------------------------------------------------------
	var fileValid = true;
    var mFile = null;
    var mailApp = "";
	
	var mFileServ = Components.classes["@mozilla.org/file/directory_service;1"]                                  
                       .getService(Components.interfaces.nsIProperties);
	               			
	var file = Components.classes["@mozilla.org/file/local;1"]
                      .createInstance(Components.interfaces.nsILocalFile);
	// sets the default location for messenger app	
	var appNameX =Components.classes["@mozilla.org/xre/app-info;1"];
	var appName = appNameX.getService(Components.interfaces.nsIXULAppInfo).name;
	var appID = appNameX.getService(Components.interfaces.nsIXULAppInfo).ID;

	var osInfo = rmFx_opSystemInfo();
   
    if (rmFx_isMessenger()) {
        mFile = mFileServ.get("CurProcD", Components.interfaces.nsIFile);
        
        if (osInfo.indexOf("WINNT") != -1) {
            mFile.append(appName + ".exe");                       
        }
        if(osInfo.indexOf("Linux") != -1) {
            mFile.append(appName.toLowerCase());                                  
        }
        if(osInfo.indexOf("Darwin") != -1) {
            var mFile = mFileServ.get("LocApp", Components.interfaces.nsIFile);
            mFile.append(appName + ".app");                      
        }
    }

	try {
		var mailApp = reminderFox_prefsBranch.getCharPref(REMINDER_FOX_MAIL_PATH );
	} catch (ex) {}


	try { 
		file.initWithPath(mailApp);
		fileValid = file.exists();
	} 	catch ( e ) {
		fileValid = false;
	}	

    if ((fileValid == false) && (mFile != null)) {
        mailApp = mFile.path;
        file.initWithPath(mailApp);
        fileValid = true;
    }

	if (fileValid == false) { // mailApp / OS not valid, ask user
	
//gW appPicker   2009-10-03	 +++2do  change for application menu (see FX --> Options --> Applications)
        
        var fp = Components.classes["@mozilla.org/filepicker;1"]
                .createInstance(Components.interfaces.nsIFilePicker);
        var winTitle = "Select Mail/Messenger Application" // this._prefsBundle.getString("fpTitleChooseApp");
        fp.init(window, winTitle, Components.interfaces.nsIFilePicker.modeOpen);
        fp.appendFilters(Components.interfaces.nsIFilePicker.filterApps);
     
        // Prompt the user to pick an app.  If they pick one, and it's a valid
        // selection, then set it for 'mailto' / 'messenger'
        
        if (fp.show() == Components.interfaces.nsIFilePicker.returnOK 
                && fp.file && rmFxUtil.isValidHandlerExecutable(fp.file)) 
	    {
	        var handlerApp =rmFxUtil.getLocalHandlerApp(fp.file);

        } else {      	
			reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MAIL_PATH, "");
			 
			return "";  // return file object
        }
        	
        var mailApp = fp.file.path;
		reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MAIL_PATH, mailApp); 

		file.initWithPath(mailApp);
	}	

	
	if(osInfo.indexOf("Darwin") != -1) {
		
		if (mailApp.toLowerCase().indexOf("-bin") == -1) {
			file.initWithPath(mailApp);	
			
			file.append("Contents"); 
			file.append("MacOS");
			
			if (mailApp.toLowerCase().indexOf("thunderbird") != -1)  file.append("thunderbird-bin");
			if (mailApp.toLowerCase().indexOf("seamonkey") != -1)  file.append("seamonkey-bin");
			if (mailApp.toLowerCase().indexOf("postbox") != -1)  file.append("postbox-bin");
			fileValid = true;
		}
	}
	
	reminderFox_prefsBranch.setCharPref(REMINDER_FOX_MAIL_PATH, mailApp); 
	return file;  // return file object
}


// ------------  "Browse" for 'mail app' path -------------------

function rmFx_mailAppStringBrowse() { 
	reminderFox_prefsBranch.setCharPref (REMINDER_FOX_MAIL_PATH, ""); 
    document.getElementById('mailApp.location.input').value = rmFx_MessengerApp().path;
}	


// -------------- open 'mail' addressbook ------------------

function rmFx_abookOpen() {
	// first enable textbox for easy pasting
	document.getElementById('attendees').removeAttribute( "disabled");
	document.getElementById('inviteEnable').setAttribute( "checked","true");

	var topWindow = rmFx_getWindow("mail:addressbook");

	if ( topWindow ) {	// if already open bring it to front
		topWindow.focus();
	} else {
        var mailApp = rmFx_MessengerApp();
		if ((mailApp == null) || (mailApp == ""))  {
			rmFxUtil.PromptAlert("Messenger not found!");  // reminderFox_getBundle().getString("rf.schedule. $$string$$ "));
            return;
        }
		try {
			go4Process.init(mailApp);
		} catch (ex) {}
	    go4Process.run(false, new Array( "-addressbook"), 1);
	}
}

function rmFx_abookMini() {
	var topWindow = rmFx_getWindow("mail:addressbook");
	topWindow.minimize();
}

function rmFx_insertAttendees(xAttendees) {
// focus on the  'invitation' window
	var topWindow = rmFx_getWindow("window:ItemDialog");

	try {
		topWindow.focus();
		var attendeeBox = topWindow.document.getElementById("attendees");
		var attendeeText = attendeeBox.value;
		var end0 = attendeeBox.selectionEnd; 

		if (attendeeText == "" && attendeeText != null){
			attendeeBox.value = xAttendees;
		}
		else {
			if (attendeeText.charAt(attendeeText.length) != ',') {
				attendeeBox.value = attendeeText + ',' + xAttendees;
			} else {
				attendeeBox.value = attendeeText + xAttendees;
			}
		}
		var end = attendeeBox.textLength;
		attendeeBox.setSelectionRange(end);
		topWindow.focus();
	} catch (e) {}
}

/////////////////////// iCalUtil ///////////////////////////////////////////////

function iCalUtil () {
}

  		//	icsString  ORGANIZER;CN=name:MAILTO:mailadr@abc.xx
  		//	returns:   name<mailadr@abc.xx>
		iCalUtil.getMailAddress = function (icsString) {	
			var persName="";
			var persMail="";
			var fndIndex = icsString.toUpperCase().lastIndexOf( "MAILTO:");  
			if (fndIndex != -1) {
				persMail = icsString.substring( fndIndex + 7);          
			} else {
				var colnIndex = icsString.lastIndexOf(":");
				if (colnIndex != -1) {
					if (icsString.substring( colnIndex).indexOf("@") != -1) {
						persMail = icsString.substring( colnIndex + 1);  }
				}   
			}     
			var fndIndex = icsString.toUpperCase().indexOf( "CN=" ); 
			if (fndIndex != -1) {
				var fndString = icsString.substring( fndIndex + 3);
				var colnIndex = fndString.indexOf(":");
				var semkiIndex = fndString.indexOf(";");
			
				if ((semkiIndex != -1) && (semkiIndex < colnIndex))  {
					persName = fndString.substring( 0, semkiIndex);       
				} else { persName = fndString.substring( 0, colnIndex);  }
			}
			
			if (persName == "") {return '<' + persMail +'>';
				} else {
				return persName + '<' + persMail +'>';
			}
		}

  
// http://tools.ietf.org/html/rfc2446#section-3.2.2.1 Rescheduling an Event
function rmFx_iCalReschedule(originalReminder, currentReminder) {
// ---------------------------------------------------------------	
	if (originalReminder.extraInfo == null) return;
	
	var extraInfoOrginal = rmFx_extraInfoArray (originalReminder);
	var extraInfoCurrent = rmFx_extraInfoArray (currentReminder);
	
	var currentATT = rmFx_extraInfo( extraInfoOrginal,"ATTENDEE"); 
	if (currentATT == null || currentATT.length == 0)  { return;}  
	// OK  it's a Invitation/Schedule .. rescheduling requirements:
	// 		1. is the ORGANIZER one of my accounts?  Maybe hard with FX!!
	// 		2.  A rescheduled event involves time or recurrence intervals 
	//     		and possibly the location or description 
	
  // ad 1.  check ORGANIZER
	// currentORG =   "ORGANIZER;CN=name:MAILTO:mailadr@abc.xx"
	// myAccounts =   "name<mailadr@xyz.xx>,name2<mailadr2@mmm.zz>"

	var currentORG = rmFx_extraInfo( extraInfoOrginal,"ORGANIZER", ";");	
	if (currentORG.length == 0)  { return;}  // no ORGANIZER
	var fndIndex = currentORG.toUpperCase().lastIndexOf( "MAILTO:" ); 

	if (rmFxMsg.myMailIDs().toUpperCase().indexOf(currentORG
//	if (rmFxMsg.myMailIDs().toUpperCase().indexOf(currentORG
		.substring( fndIndex + 7).toUpperCase()) == -1 ) {return;} // no ORGANIZER -- no Invitation/Schedule
  	// ORGANIZER ok
  	
	var fromAddress = iCalUtil.getMailAddress(currentORG);  	
  		
  // ad 2. check if parameters changed 	

	if (currentReminder.endDate == null  && originalReminder.endDate != null) {
		currentReminder.endDate = originalReminder.endDate;
	}	

	var dateChange   = originalReminder.date.toGMTString()
                     != currentReminder.date.toGMTString()
                 ||     originalReminder.endDate.toGMTString()
                     != currentReminder.endDate.toGMTString();
	var recurChange	= ( 
		  	originalReminder.recurrence.byDay 	 != currentReminder.recurrence.byDay
		||	originalReminder.recurrence.endDate  != currentReminder.recurrence.endDate
		||	originalReminder.recurrence.interval != currentReminder.recurrence.interval
		||	originalReminder.recurrence.type 	 != currentReminder.recurrence.type);

	var sumChange	= originalReminder.summary != currentReminder.summary;

	var locChange	= originalReminder.location != currentReminder.location;

	if ( !(dateChange || recurChange || sumChange|| locChange ) ) {return;}  // no Change

  //  ORGANIZER 'rescheduled' the event   
  //   read ORGANIZER   from reminder and set it to 'fromAddress'	
  //   read ATTENDEE(s) from reminder and set it to 'attendees'	
  //   parameter to be updated:
  //   - DTSTAMP
  //   - SEQUENCE
  //   - SUMMARY/DESCRIPTION
  //   - LASTMODIFIED ????
	
	
	var aExtraInfo  = rmFx_extraInfoArray(currentReminder);

	// for ATTENDEE(s) have to build the to=mailString and all ATT need to called RSVP!!
	var attendeeString ="";		// for iCal ATTENDEE:
	var attendees ="";			// for mail compose to=
	
	for (var i=0; i< aExtraInfo.length; i++) {
		if (aExtraInfo[i].indexOf("ATTENDEE") == 0) {

			var attendeeName="";
			var attendeeMail="";
			var fndIndex = aExtraInfo[i].toUpperCase().lastIndexOf( "MAILTO:");  
	        if (fndIndex != -1) {
	            attendeeMail = aExtraInfo[i].substring( fndIndex + 7);          
	        } else {
				var colnIndex = aExtraInfo[i].lastIndexOf(":");
				if (colnIndex != -1) {
					if 	(aExtraInfo[i].substring( colnIndex).indexOf("@") != -1) {
						attendeeMail = aExtraInfo[i].substring( colnIndex + 1);  }
				}   
			}     
	        var fndIndex = aExtraInfo[i].toUpperCase().indexOf( "CN=" ); 
	        if (fndIndex != -1) {
				var fndString = aExtraInfo[i].substring( fndIndex + 3);
				var colnIndex = fndString.indexOf(":");
				var semkiIndex = fndString.indexOf(";");
				
				if ((semkiIndex != -1) && (semkiIndex < colnIndex))  {
					attendeeName = fndString.substring( 0, semkiIndex);       
				} else {attendeeName = fndString.substring( 0, colnIndex);  }
	        }
			if (attendeeName == "") {attendees +=  '<' + attendeeMail +'>,';
				} else {
				attendees += attendeeName + '<' + attendeeMail +'>,';
			}
			
			var attendeeString ="ATTENDEE";		
			if (attendeeName != "") {attendeeString += ";CN=" + attendeeName}
			if (attendeeMail != "") {attendeeString += ";RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:MAILTO:" + attendeeMail}
			aExtraInfo[i] = attendeeString;
		}
	}
	rmFx_extraInfoReplace (aExtraInfo, "SEQUENCE", rmFx_extraInfo(aExtraInfo, "SEQUENCE")*1 + 1);
	rmFx_extraInfoReplace (aExtraInfo, "DTSTAMP", rmFx_setDateTimeZ());
	rmFx_extraInfoReplace (aExtraInfo, "COMMENT", "");		// erase old
	
	currentReminder.extraInfo = aExtraInfo.join("\\n");
	// delete double 'CR'
	currentReminder.extraInfo = currentReminder.extraInfo.replace(new RegExp(/\\n\\n/g),"\\n");

	var chText =	(dateChange		? " '" + reminderFox_getBundle().getString("rf.add.mail.message.datetime") + "' " 		: "") // "Date/Time") 
					+ 	(recurChange	? " '" + reminderFox_getBundle().getString("rf.add.mail.message.reccurance") + "' " 	: "") // "Recurrance") 
					+	(sumChange 		? " '" + reminderFox_getBundle().getString("rf.schedule.description") + "' " 			: "") // "Title") 
					+	(locChange		? " '" + reminderFox_getBundle().getString("rf.mail.ical.send.location") + "' " 		: ""); // "Location");
		
	var methodTyp = "REQUEST";
	var newNotes = "[iCal] " + methodTyp + ": " + reminderFox_getBundle().getString("rf.schedule.statusOf")
		+ ": " + reminderFox_parseDateTimes(rmFx_extraInfo(aExtraInfo,"DTSTAMP"))
		+ " [#" + rmFx_extraInfo(aExtraInfo,"SEQUENCE") +"]\n"
		+ "*" + reminderFox_getBundle().getString("rf.schedule.statusChanged")+"*  " + chText +"\n\n";	
	currentReminder.notes = newNotes + currentReminder.notes
	var reminders = new Array();
	reminders[0] = currentReminder;
	var iCalInvite = true;
	rmFx_sendEventNow(reminders, "", methodTyp, fromAddress, attendees, iCalInvite); 
}

function rmFx_inviteStatus(currentReminder) {
// --------------------------------------------	
//	var extraInfoOrginal = rmFx_extraInfoArray (currentReminder);

	var currentORG = rmFx_extraInfo( rmFx_extraInfoArray (currentReminder),"ORGANIZER");	
	if (currentORG.length == 0)  { return;}  // no ORGANIZER

	var fndIndex = currentORG.toUpperCase().lastIndexOf( "MAILTO:" ); 
	if (rmFxMsg.myMailIDs().toUpperCase()
		.indexOf(currentORG.substring( fndIndex + 7).toUpperCase()) == -1) {
		
			document.getElementById("newReminderText").setAttribute("disabled", "true");	
			
			document.getElementById("reminderFox-all-day").setAttribute("disabled", "true");	

			document.getElementById("reminderFox-timeList").setAttribute("disabled", "true");	
			document.getElementById("yearlist").setAttribute("disabled", "true");	
			document.getElementById("monthlist").setAttribute("disabled", "true");	
			document.getElementById("daylist").setAttribute("disabled", "true");
			
			document.getElementById("reminderFox-endTimeList").setAttribute("disabled", "true");	
			document.getElementById("endyearlist").setAttribute("disabled", "true");	
			document.getElementById("endmonthlist").setAttribute("disabled", "true");	
			document.getElementById("enddaylist").setAttribute("disabled", "true");	

			document.getElementById("datepickerToggle").setAttribute("disabled", "true");
			document.getElementById("datepickerEndToggle").setAttribute("disabled", "true");

			document.getElementById("location").setAttribute("disabled", "true");
			document.getElementById("reminderFox-repeat").setAttribute("disabled", "true");
	}
}

function rmFx_extraInfoReplace (extraInfo, itemName, itemValue) {
// ------ writes to aExtraInfo array using item 
    itemName = itemName.toUpperCase();
    var result="";
    if (extraInfo != null) {
	    if (extraInfo.length > -1) {
			for (var n =0; n < extraInfo.length; n++) {    
				if (extraInfo[n].indexOf( itemName )  == 0) { 
					if  (itemValue == "") {
						extraInfo[n] ="";
						break;
					}
		        	extraInfo[n] = itemName + ":" + itemValue;
		        	break
	            }
			}
	    }
    }
}

function rmFx_setDateTimeZ() {	
	var currentDate = new Date();
	var tzOffset = new Date().getTimezoneOffset(); 
	currentDate.setMinutes( currentDate.getMinutes() + tzOffset );						
	 	
	return  reminderFox_getDateAsString(currentDate)+ "Z";   
}





/**
//gWTEST rmFx_iCalTest    TEST  TEST  TEST  TEST  TEST  TEST 
<br>  test purpose only:  copy a BEGIN:CALENDAR ... END:CALENDAR 
<br>         to clipboard and call this function to process /simulate
<br>         an 'iCal import form email'
*/                     
function rmFx_iCalTest (){
	var clip = Components.classes["@mozilla.org/widget/clipboard;1"]. 
	getService(Components.interfaces.nsIClipboard); 
	if (!clip) return false; 
	
	var trans = Components.classes["@mozilla.org/widget/transferable;1"]. 
		createInstance(Components.interfaces.nsITransferable); 
	if (!trans) return false; 
	trans.addDataFlavor("text/unicode");

	clip.getData(trans,clip.kGlobalClipboard); 
	var str = new Object(); 
	var strLength = new Object(); 
	trans.getTransferData("text/unicode",str,strLength);

	if (str) str = str.value.QueryInterface(Components.interfaces.nsISupportsString); 
	if (str) pastetext = str.data.substring(0,strLength.value / 2);

	var mInvitation = "[iCal] Schedule copied from Clipboard";		
	this.reminderfox_Method ="CLIPBOARD";
	
	rmFx_iCalTagging(rmFxGetiCalFromTextBody(pastetext, mInvitation));       
	return true;          
}


/**
 *    Change Groupbox elements for 'Export' and 'Send' dialogs
 *  
 */
function rmFx_sendExportChange(mode) {
    var sendOp;
        
    if (mode.id == "exportSection") sendOp = !mode.checked;
    if (mode.id == "sendSection")   sendOp = mode.checked;
 
    // called from ... send Invitation as 'info' see: rmFx_invitationLoadDialog
    if (mode == "sendSection")      sendOp = true;      

    if (sendOp) {
        /* --- 'Export' -->     disabled */ 
        document.getElementById("exportSection").setAttribute("checked", "false");
        document.getElementById("exportFile").setAttribute("disabled", "true");        
        document.getElementById("getFileLocationButton").setAttribute("disabled", "true");        

        /* --- 'Send' -->       enabled */
        document.getElementById("sendSection").setAttribute("checked", "true");
        
        document.getElementById('mailApp.Description')   .setAttribute( "class", "textNormal" ); 
        document.getElementById('mailApp.location.input').setAttribute( "class", "textNormal" ); 
        
        document.getElementById("organizerMenu").removeAttribute("disabled");         
        document.getElementById("inviteEnable").removeAttribute("disabled");

        if (document.getElementById('inviteEnable').checked == true){
            document.getElementById('reminderFox-attendeeGroup').setAttribute( "hidden", false );            
            document.getElementById('reminderFox-commentGroup').setAttribute( "hidden", false );
        }
        document.getElementById('attendees').removeAttribute( "disabled");
        document.getElementById('commentText').removeAttribute( "disabled");
        document.getElementById("mailAppButton").removeAttribute("disabled");
        
    //  check the messenger to be used
        document.getElementById('mailApp.location.input').value = rmFx_MessengerApp().path;
    } else {
    	/* --- 'Export' -->     enabled */ 
        document.getElementById("exportSection").setAttribute("checked", "true");
        document.getElementById("exportFile").removeAttribute("disabled");        
        document.getElementById("getFileLocationButton").removeAttribute("disabled");        
    	 
        /* --- 'Send' -->       disabled */
        document.getElementById("sendSection").setAttribute("checked", "false");

        document.getElementById('mailApp.Description')   .setAttribute( "class", "textDisabled" );            
        document.getElementById('mailApp.location.input').setAttribute( "class", "textDisabled" );           

        document.getElementById("organizerMenu").setAttribute("disabled", "true");
        document.getElementById("inviteEnable").setAttribute("disabled","true");

        document.getElementById('reminderFox-attendeeGroup').setAttribute( "hidden", true );            
        document.getElementById('reminderFox-commentGroup').setAttribute( "hidden", true );

        document.getElementById("mailAppButton").setAttribute("disabled", "true");          
    }
    sizeToContent();
}

/**
 *  Set the file for  'export' of reminders/todos
 *  .. and set prefs for it
 *  
 */
function rmFx_getExportFile () {

    var currentFileName 	= document.getElementById("exportFile").value;
    var windowText          = reminderFox_getBundle().getString("rf.export.send.title");   // "Set / Select file to export reminder(s)";  
    var filterName          = "Event File (ICS)";
    var defaultExtension    = "ICS";
    var rmFx_exportFile     = "exportEventsFile"    // set as prefs 'extensions.reminderFox.exportEventsFile'
    
    var file = rmFx_filePicker (windowText, filterName, defaultExtension, 
                currentFileName /*defaultString*/, rmFx_exportFile /*prefsName*/, 1 /*mode = modeSave*/) 
    
    if (file != null) {
    	reminderFox_prefsBranch.setCharPref(rmFx_exportFile, file.path);
    	document.getElementById("exportFile").setAttribute("value", file.path);
    }
}