// ++ IMPORTANT NOTICE --     
// 
// +++++++       This file is UTF-8. 
// +++++++       Please adjust you text editor prior to saving any changes!
//
// ++ IMPORTANT NOTICE --  

//https://developer.mozilla.org/en/nsIAbCard%2f%2fThunderbird3

/**
 *   add a Reminder for a selected 'Contact' of the TB / ADDRESSBOOK
 *
 *  //gW - Guenter Wahl ...    vers. 01. August 2007 15:03
 
		The ABcard items added to the output (reminder.notes) are 
		configured with a 'rmFx_cardItems'-string 
		which is read from/written to the 'rmFx.abCardItems' TB-prefs.
		
		Valid items are all addressbook/card items, but only the following 
		have a 'locale' entry. For the others their item name is displayed.
		
			- LabelContact
				- DisplayName	
				- NickName
				- PrimaryEmail
				- SecondEmail
				- ScreenName
				
			- LabelHome
				- HomeAddress	
					
			- LabelWork
				- WorkAddress	
	
			- LabelPhone
				- CellularNumber	
				- FaxNumber			
				- PagerNumber
				
			- LabelOther
				- Costom1 .. 4
				

		'rmFx_cardItems'-string interpretation:

			!item				generates 'nameString' tab 'dataOfNameString'
			item				generates 'dataOfNameString' only
			item,[!]item		items separated with comma are generated as
								data output on same line separated by space								
			;					delimiter for generating a CR for the output
			//					an entry beginning with // is treated as comment 
								which is not written to the output
					
			- Items containing a substring of 'Label' are interpreted as header lines.	
			
			- Items with a leading 'X' are skipped for output.
			  This is a easy way to skip them, but hold them at the 
			  standard place in the default 'rmFx_cardItems'-String.	

			- The 'Category' items need not to be added to the
			  interpretation string, it's added to rmFx-field 'Categories'

			- 'Custom1..4'-item labels
				With the extension "MoreColsForAddressBook"
					https://nic-nac-project.org/~kaosmos/morecols-en.html
				installed, the 'labels' can be set individually and are 
				stored in the prefs.js parameters  
				"morecols.custom"+num+".label"  (num= 1...4)
				Those settings are read if xpi is installed.

	*/
	
var EXPORTED_SYMBOLS = ["reminderFox_addReminder4Contact", "rmFxOpenABcard"];

	var rmFx_cardItemsUS = "// US version;"
					+ "LabelContact;"
						+ "!DisplayName;"
						+ "X!LastName,XFirstName;"
						+ "!PrimaryEmail,XSecondEmail;"
			
					+ "LabelPhone;"					
						+ "!HomePhone,!FaxNumber;"
						+ "!WorkPhone;"
						+ "!CellularNumber;"
					
					+ "LabelHome;"	
						+ "HomeAddress,HomeAddress2;"
						+ "HomeCity,HomeState,HomeZipCode;"			
						+ "HomeCountry;"				
			
					+ "LabelWork;"	
						+ "JobTitle;"
						+ "Company,Department;"
						+ "WorkAddress,WorkAddress2;"
						+ "WorkCity,WorkState,WorkZipCode;"			
						+ "WorkCountry;"				
			
					+ "LabelOther;"	
						+ "!Custom1,!Custom2;"
						+ "!Custom3;!Custom4;"
					//	+ "!AnniversaryYear,AnniversaryMonth,AnniversaryDay;"
						+ "X!BirthYear,XBirthMonth,XBirthDay;"
					
					;  // semikolon terminates 'rmFx_cardItems' !


	var rmFx_cardItemsEU = "// European version;"
					+ "LabelContact;"
						+ "!DisplayName;"
						+ "!LastName,FirstName;"
						+ "!PrimaryEmail,SecondEmail;"
			
					+ "LabelPhone;"					
						+ "!HomePhone,!FaxNumber;"
						+ "!WorkPhone;"
						+ "!CellularNumber;"
					
					+ "LabelHome;"	
						+ "!HomeAddress,HomeAddress2;"
						+ "!HomeZipCode,HomeCity;"			
						+ "!HomeCountry,!HomeState;"				
			
					+ "LabelWork;"	
						+ "JobTitle;"
						+ "!Company,Department;"
						+ "!WorkAddress,WorkAddress2;"
						+ "!WorkCity,WorkZipCode;"			
						+ "!WorkCountry,!WorkState;"				
			
					+ "LabelOther;"	
						+ "!Custom1,!Custom2;"
						+ "!Custom3;!Custom4;"
					//	+ "!AnniversaryYear,AnniversaryMonth,AnniversaryDay;"
						+ "X!BirthYear,XBirthMonth,XBirthDay;"
					
					;  // semikolon terminates 'rmFx_cardItems' !

	var rmFx_cardItems;		// this contain the active cardItem set

	var rmFx_ABprop = "rf.contacts.";

   var rmFx_ABerrMsg = "addContact2Reminder Warning!";
   var rmFx_ABerrMsg1 = "Configuration item missing for: "; 
   var rmFx_ABerrMsg2 = "Item naming missing for:  ";

	
	var rmFx_personalABURI = 'moz-abmdbdirectory://abook.mab';
	var rmFx_collectedAABURI = 'moz-abmdbdirectory://history.mab';
	var rmFx_selectedABURI = null;
	var rmFx_cDirectory = '';
	var rmFx_cCard;
	var rmFx_ABbundle = document.getElementById("bundle_addressBook");

/*
 * 
 * /messenger/addressbook/abCardOverlay.js/
 * 
 * function AbEditSelectedCard()
	{
  		AbEditCard(GetSelectedCard());
	}

		--> goEditCardDialog(GetSelectedDirectory(), card);
		
		ondialogaccept="return EditCardOKButton();">
		
		siehe 
 *		function InitEditCard() 
 *		--> gEditCard
 *
 *
 *
 */	
	
	
	
function reminderFox_addReminder4Contact(op){

	//	--- get the Contact info
	rmFx_selectedABURI = GetSelectedDirectory();
	rmFx_cDirectory = GetDirectoryFromURI(rmFx_selectedABURI).dirName;

	if (rmFx_cDirectory.isMailList)  { return;} // terminate if on 'List'		

	switch (op) {
	
	case "Reminder":  { // this is to set a reminder from a selected card 
		var rmFx_cCard = GetSelectedCard();	
		if (rmFx_cCard == null) {
         rmFxUtil.PromptAlert(reminderFox_getBundle().getString("rf.contacts.abcard.single"));
			return;
		}
		
		// --- setup the reminder -----
        var time = new Date();
        //time.getTime();
        var timeString = reminderFox_mail_getTimeString( time );

        var dateVariableString;
        try { dateVariableString = reminderFox_getUnicodePref(REMINDER_FOX_PREF + "." + REMINDER_FOX_LIST_DATE_LABEL);
        	} catch(e) {}           
        var remFoxDate =reminderFox_getDateVariable( null, time, dateVariableString ) + "  " + timeString;
        
		var newDate = new Date();
		newDate.setDate( newDate.getDate() + 1 );  // default to using tomorrow's date for reminder

		var reminderId = reminderFox_generateUniqueReminderId( newDate );

		if (gRmFx_AB3) {  // if TB/AB3 then add an "UUID" element to the card
						
			// alert ("we are in reminderFox_addReminder4Contact ... ")
			// rmFx_cCard.setProperty("UUID", reminderId);
		}
		
		
		var remFoxSummary  = "[" + rmFx_itemName ("LabelContact") + "] " 
				+ rmFx_cCardItem(rmFx_cCard, "DisplayName");

		var	newReminderToBeAdded 	= new ReminderFoxEvent( reminderId, newDate, remFoxSummary );

		newReminderToBeAdded.extraInfo = "X-REMINDERFOX-CONTACT:"
			+ rmFx_selectedABURI + "::" + rmFx_cDirectory 
			+ "::" + rmFx_cCard.displayName;
		
		var cNotes = '[' + rmFx_cDirectory  +  ']\n';

		var custItems ="";
		var labelStr = "";
		
		// +++++ read  all card-items to be added +++++
		var rmFx_cardItems = rmFx_readABcardPref();   	/* -- get values  -- */								 

		var cardItems = rmFx_cardItems.split(";");
		
		for (var i=0;i<cardItems.length;i++) { 

			var anyValue = false;	
			var currentLine = cardItems[i]; 
			
			if (cardItems[i].indexOf( "Label" ) != -1 ) {
				if (cardItems[i].charAt(0) != "X") {
					
					labelStr =  "\n" + rmFx_itemName (cardItems[i])
							+ ":\n";
				}
			} else {
				if ((currentLine != "") 
				  && (currentLine.substring(0,2) != "//")) {
				  
				  	var usAdr= false;
				  	if (	currentLine.indexOf("WorkCity,WorkState") != -1  ||
				  	 		currentLine.indexOf("HomeCity,HomeState") != -1  
				  		) usAdr = true;
				  
					var cItems = currentLine.split(",");  
					
					for (var j=0; j<cItems.length; j++) { /* one item */
						var namString = cItems[j]; 
				
						//  process  cardItem 
						if (namString.charAt(0) == "!") {
							// this needs to fetch the namString
							var iName = namString.substring(1);
						} else {iName = namString;} 
						
						if (iName == "HomeWebPage") iName ="WebPage1";
						if (iName == "WorkWebPage") iName ="WebPage2";
						var iname = iName.substring(0,1).toLowerCase() + iName.substring(1);

						if (iname.charAt(0) != "x") {
							var thisItem = rmFx_cCardItem(rmFx_cCard, iName);
							
							if (iName.indexOf("Custom") != -1) {
								if ( thisItem != -1 && thisItem != "") {
									cNotes +=  labelStr + "    " + rmFx_itemName(iName) + " : " 
														+ thisItem + "; "
									anyValue = true;
									labelStr = "";
								}
							} else {
								if (namString.charAt(0) == "!") {
									if ( thisItem != -1 && thisItem != "") {								
										cNotes += labelStr + "    " + rmFx_itemName(iName) + ":\t";
										anyValue = true;
										labelStr = "";
									}
								}		
								if ( thisItem != -1 && thisItem != "")  {
									if (labelStr != "" && thisItem != "") {
										cNotes += labelStr;
										labelStr = "";
									}
									if (anyValue == false) 	cNotes +=  "    ";								
									
									cNotes +=  thisItem ; 
									if (usAdr == false) { cNotes +=  "   ";}
										else {  cNotes +=  ",  "; 
									} usAdr = false;
									anyValue = true;
								}
							} 
						}
					}
				}
				if (anyValue == true) cNotes += "\n";
			}
		}	

		newReminderToBeAdded.notes = cNotes;	
		if (custItems != "") newReminderToBeAdded.notes  += "\n" + custItems + "\n";	

		// --- add ABcard-items to rmFx-fields ---
		
		// add address to 'Location' for search with Google Maps  
			var workAddr ="";
			
			var w = rmFx_cCardItem(rmFx_cCard, "WorkAddress"); 	if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkAddress2"); if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkCity"); 	if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkAddress"); 	if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkState"); 	if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkZipCode"); 	if (w != "") workAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "WorkCountry"); 	if (w != "") workAddr += w + " ";

			var locAddr ="";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeAddress"); 	if (w != "") locAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeAddress2"); if (w != "") locAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeCity"); 	if (w != "") locAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeState"); 	if (w != "") locAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeZipCode"); 	if (w != "") locAddr += w + " ";
			var w = rmFx_cCardItem(rmFx_cCard, "HomeCountry"); 	if (w != "") locAddr += w + " ";

			if (locAddr == null || locAddr == "") locAddr = workAddr;
			
	//  .location does NOT accept local chars like ÃƒÂ– in 'KÃƒÂ–LN'  ==> so normalize the string
			newReminderToBeAdded.location = rmFx_normalizeNameString(locAddr);
		
		var cItem = rmFx_cCard.primaryEmail;
		if (cItem != "") newReminderToBeAdded.url = "mailto" + ":" + cItem ;	

		cItem = rmFx_cCardItem(rmFx_cCard, "Category");	
		if (cItem != "") newReminderToBeAdded.categories =  rmFx_cCard.category; 

//gWTEST AB: add Birthday infos  2010-02-06
//gWtodo check AB functions with TB2, SM, PB!!		
		
		var bYear = (rmFx_cCardItem(rmFx_cCard, "BirthYear"));
		
		if (bYear != "")  {  // need a year as string, if not skip birthday
			newReminderToBeAdded.summary += '   <' + bYear + '>';
			
			// set the StartDate for the reminder to the Birthday Month/Day
			var newDate = new Date();
			var month = parseInt(rmFx_cCardItem(rmFx_cCard, "BirthMonth"))-1;
			newDate.setMonth(month);
			newDate.setDate(parseInt(rmFx_cCardItem(rmFx_cCard, "BirthDay")));
			newReminderToBeAdded.date = newDate;
			
			// set 'repeat yearly' and 'allDay'
			newReminderToBeAdded.recurrence.type  = 0 ; //REMINDER_RECURRENCE_YEARLY; 
			newReminderToBeAdded.allDayEvent  = true ; 			
		}
		rmFx_writeABcardPref();
		
		//  .... and go to display it .... w 'edit'  to get recurrence + allDay
		var added = reminderFox_addReminderHeadlessly( newReminderToBeAdded, true, true /*edit*/ );		

	}
	case "Copy": {  // copy mailadr of selected cards to clipboard
			//    with mailName <mailadr@xxx.yy>, etc
		var rmFx_Cards = GetSelectedAbCards();
		var xAttendees="";
		for (var n=0; n < rmFx_Cards.length; n++) {
			xAttendees += rmFx_Cards[n].lastName + rmFx_Cards[n].firstName
			+ "<" + rmFx_Cards[n].primaryEmail + ">,";
		}
		// del last comma	
		xAttendees = xAttendees.substring(0, xAttendees.length-1)	
		rmFx_abookMini();  
		rmFxUtil.copytoClipboard(xAttendees);
		rmFx_insertAttendees(xAttendees);
		
		return;
	}
	
	} // switch
}


function rmFx_cCardItem(rmFx_cCard,iName) {
// ---------------- get item Value or set to -1 if invalid " 
		
	try {	
		if(!gRmFx_AB3) {
			iName = iName.substring(0,1).toLowerCase() + iName.substring(1); 
			!rmFx_cCard[iName].length;
			return rmFx_cCard[iName];
		} else {
			var iValue = rmFx_cCard.getProperty(iName, "");
			return iValue;
		}

	} 	catch(ex) {
		alert(  rmFx_ABerrMsg + "\n1: " + iName); 				
		reminderFox_logMessageLevel(rmFx_ABerrMsg + "\n[" + gRmFx_Messenger + "] "
		       + rmFx_ABerrMsg + iName, 2);
		return -1;
	}						
}



function rmFx_itemName (namItem) {
/* ---------- access the properties ... if relevant  -------------
*/
try {
	// .... access 'address.properties'	
	if (  namItem == "DisplayName" ||
		  namItem == "NickName"	   ||
		  namItem == "PrimaryEmail"||
		  namItem == "SecondEmail" ||
		  namItem == "ScreenName"    	) 				
		return rmFx_ABbundle.getString("property"+namItem); 		  	  
	  
	  
	if (  namItem == "LabelContact" || namItem == "HomeAddress" 		)  	
		return reminderFox_getBundle().getString(rmFx_ABprop + namItem);

	if (  namItem.indexOf("Label") != -1) 	
		return rmFx_ABbundle.getString("heading"+ namItem.substring(5)); 

	if (  namItem.indexOf("Number") != -1) 	
		return rmFx_ABbundle.getString("property"+ namItem.substring(0,namItem.indexOf("N"))); 

	
	// ... access morecols.properties  ... if there else addressbook.p
	if (  namItem.indexOf("Custom") != -1)
		return rmFx_getCustomLabel (namItem);

	// ... now no entries ... need to set it here (without 'locale' translation)
	if (  namItem.indexOf("Name") != -1 )	return namItem;

	if (  namItem == "JobTitle"			)	return "Job";
	if (  namItem == "Department"		)	return "Department";
	if (  namItem == "Company"			)	return "Company";
			  
	if (  namItem == "HomeWebPage" || 
		  namItem == "WorkWebPage"		)	return "WebPage";
	
	if (  namItem.indexOf("Address2") != -1) return "";

	//  ... delete 'Phone'  from item-name and return it 
	if (	namItem.indexOf("Phone") != -1)
		return namItem.substring(0,4); 

	// ... delete 'Work' or 'Home' from item-name and return it  
	if (	(namItem.indexOf("Work") != -1)
		||  (namItem.indexOf("Home") != -1) )
		return namItem.substring(4); 


	}
	catch(ex) {				
      reminderFox_logMessageLevel(rmFx_ABerrMsg + "\n[" + gRmFx_Messenger + "] "
         + rmFx_ABerrMsg2 + namItem, 2);
	}
				
	return namItem;
}



function rmFx_getCustomLabel (iName) {
// ---------- work with Custom 1..4 individual entries  -------------

	var cLabel="";
	var moreColsPrefs = Components.classes["@mozilla.org/preferences-service;1"]
			.getService(Components.interfaces.nsIPrefBranch);
			
	var cLabelid = 	"morecols." 
				+ iName.substring(0,1).toLowerCase() + iName.substring(1)+".label";	
	try { 
		cLabel = moreColsPrefs.getComplexValue
			(cLabelid, Components.interfaces.nsISupportsString).data;
   	} catch(e) { 
   		cLabel = "Custom " + iName.substring(6,7);
   	}
   		
   	return cLabel;
}

function rmFx_readABcardPref() {
// ------------------------------------------------ READ  PREFS
	var prefService = Components.classes["@mozilla.org/preferences-service;1"]
			.getService(Components.interfaces.nsIPrefBranch);

	var abCardPrefVersion = "US";
	try { abCardPrefVersion = prefService.getCharPref
			("rmFx.abCardItems.version");
   	} catch(e) {}
   	
   	prefService.setCharPref("rmFx.abCardItems.version", abCardPrefVersion);   	

   	
	try { rmFx_cardItems = prefService.getComplexValue
			("rmFx.abCardItems", Components.interfaces.nsISupportsString).data;
	} catch(e) {
		
		if (abCardPrefVersion == "US") {
			rmFx_cardItems = rmFx_cardItemsUS;   // set to US default
	   		prefService.setCharPref("rmFx.abCardItems.version", "US");
		}
		
		if (abCardPrefVersion == "EU") {
			rmFx_cardItems = rmFx_cardItemsEU;   // set to EU default
	   		prefService.setCharPref("rmFx.abCardItems.version", "EU");
		}
	}
	return rmFx_cardItems;
}


function rmFx_writeABcardPref() {
// ------------------------------------------------ WRITE  PREFS
	var prefService = Components.classes["@mozilla.org/preferences-service;1"]
			.getService(Components.interfaces.nsIPrefBranch);

	var abCardPrefVersion = "US";
	try { abCardPrefVersion = prefService.getCharPref
			("rmFx.abCardItems.version");
	} catch(e) {
		prefService.setCharPref("rmFx.abCardItems.version", abCardPrefVersion);
	}
	prefService.setCharPref("rmFx.abCardItems", rmFx_cardItems);
}


/**
 * From the reminderlist open the associated TB/AB card
<br> * This requires the contact was added before from the TB/AB card or list selection
<br> * The reminder has these paramters to define the card:
<br>     reminder.url    {mail address} foo@nowhere.moc
<br>     reminder.extraInfo with 'X-REMINDERFOX-CONTACT:{directory}::{AB title}::{DisplayName})'
<br>   @todo REWORK: with getting a UUID for the card/contact; 
	    see bug https://bugzilla.mozilla.org/show_bug.cgi?id=444093 

	 * @param event -- the selected reminder or todo (only one allowed!)
	 * @return opens the TB/AB card 
	 */
function rmFxOpenABcard(event) {
//------------------------------------------------------------------------------
	var selectedEvents;
	
	if (event.currentTarget.id == "treechildren-contextmenu-reminder-openABcard")  {
		selectedEvents = getAllSelectedReminders();	// from 'reminder list' context menu
	}
	if (event.currentTarget.id == "treechildren-contextmenu-todo-openABcard")  {
		selectedEvents = getAllSelectedTodos();	// from 'reminder list' context menu
	}
	
	if (selectedEvents.length != 1)  {
		rmFxUtil.PromptAlert(reminderFox_getBundle().getString("rf.contacts.abcard.single"));
		return;
	}
	/*----
	let allAddressBooks = abManager.directories; 
	
	while (allAddressBooks.hasMoreElements()) {
		  let addressBook = allAddressBooks.getNext();
		  if (addressBook instanceof Components.interfaces.nsIAbDirectory) {

			  rmFxUtil.dump2Console('AB', "AB : " + abManager.getDirectory(addressBook.URI).URI 
					  + " " + abManager.getDirectory(addressBook.URI).dirName);
//reminderFox: AB : moz-abmdbdirectory://abook.mab
//reminderFox: AB : moz-abmdbdirectory://abook-1.mab
//reminderFox: AB : moz-abmdbdirectory://history.mab
		  
		  }
	}
	--------- */


	// X-REMINDERFOX-CONTACT:moz-abmdbdirectory://abook.mab::Personal Address Book::Werny Nigger\\nDTSTAMP:20090722T114039
	                                                         
	var abManager =
		  Components.classes["@mozilla.org/abmanager;1"].
		  getService(Components.interfaces.nsIAbManager); 

	var exPos = selectedEvents[0].extraInfo.indexOf("X-REMINDERFOX-CONTACT:");
	
	if (exPos != -1) {

		var contactInfo = selectedEvents[0].extraInfo.substring(22);
		var contactStr = contactInfo.split("\\n")[0];
		var contactDetails = contactStr.split("::");
		var abURI = contactDetails[0];
		
		if (selectedEvents[0].url != null) {
			var thisMailAdr = selectedEvents[0].url.substring(7);
			var thisCard = abManager.getDirectory(abURI)
					.cardForEmailAddress(thisMailAdr);
		} else {
				// search for element as stored with "DisplayName"
				var thisCard = abManager.getDirectory(abURI)
					.getCardFromProperty("DisplayName", contactDetails[2], false);
		}
		
		if (thisCard != null) 
			window.openDialog("chrome://messenger/content/addressbook/abEditCardDialog.xul",
		            "",
		            "chrome,resizable=no,modal,titlebar,centerscreen",
		            {abURI:abURI, card:thisCard});
	}
}
	
	/**
	 * imported from "Duplicate Contact Manager" by   Marian Steinbach, 2006   
	 * normalizeNameString
<br> 
	 * Strips some characters from a name so that different spellings (e.g. with and
	 * without accents, can be compared. Works case insensitive.
	 *
	 * @param	String		the string to be normalized
	 * @return	String		normalized version of the string
	 */
function rmFx_normalizeNameString(str) {
//------------------------------------------------------------------------------
		// remove punctiation
		//str = str.replace(/[\"\-\_\'\.\:\,\;\&\+]+/g, '');
		
		// replace funny letters
		str = str.replace(/[ÃÃÃÃÃ¨Ã©ÃªÃ«ÄÄÄÄÄÄÄÄÄÄ]/g, 'e');
		str = str.replace(/[ÃÃÃÃÃÃ¢Ã¡Ã Ã£Ã¥ÄÄÄÄÄÄÇºÇ»]/g, 'a');
		str = str.replace(/[ÃÃÃÃÃ¬Ã­Ã®Ã¯Ä¨Ä©ÄªÄ«Ä¬Ä­Ä®Ä¯Ä°Ä±]/g, 'i');
		str = str.replace(/[ÃÃÃÃÃÃ²Ã³Ã´ÃµÃ¸ÅÅÅÅÅÅÇ¾Ç¿]/g, 'o');
		str = str.replace(/[ÃÃÃÃ¹ÃºÃ»Å¨Å©ÅªÅ«Å¬Å­Å®Å¯Å°Å±Å²Å³Æ¡Æ¯Æ°]/g, 'u');
		str = str.replace(/[ÃÃ½Ã¿Å¶Å·Å¸]/g, 'y');
		
		str = str.replace(/[ÃÃ§ÄÄÄÄÄÄÄÄ]/g, 'c');
		str = str.replace(/[ÃÃ°ÄÄÄ]/g, 'd');
		str = str.replace(/[ÄÄÄÄÄ Ä¡Ä¢Ä£]/g, 'g');
		str = str.replace(/[Ä¤Ä¥Ä¦Ä§]/g, 'h');
		str = str.replace(/[Ä´Äµ]/g, 'j');
		str = str.replace(/[Ä¶Ä·Ä¸]/g, 'k');
		str = str.replace(/[Ä¹ÄºÄ»Ä¼Ä¿ÅÅÅ]/g, 'l');
		str = str.replace(/[ÃÃ±ÅÅÅÅÅÅÅÅÅ]/g, 'n');
		str = str.replace(/[ÅÅÅÅÅÅ]/g, 'r');
		str = str.replace(/[ÅÅÅÅÅÅÅ Å¡]/g, 's');
		str = str.replace(/[Å¢Å£Å¤Å¥Å¦Å§]/g, 't');
		str = str.replace(/[Å´Åµ]/g, 'w');
		str = str.replace(/[Å¹ÅºÅ»Å¼Å½Å¾]/g, 'z');
		
		// replace ligatures
		str = str.replace(/[ÃÃÃ¤Ã¦Ç¼Ç½]/g, 'ae');
		str = str.replace(/[ÃÃ¶ÅÅ]/g, 'oe');
		str = str.replace(/[ÃÃ¼]/g, 'ue');
		str = str.replace(/[Ã]/g, 'ss');
		str = str.replace(/[Ä²Ä³]/g, 'ij');
		
		// remove single letters (like initials)
	/*	str = str.replace(/ [A-Za-z0-9] /g, ' ');
		str = str.replace(/^[A-Za-z0-9] /g, '');
		str = str.replace(/ [A-Za-z0-9]$/g, '');
	*/	
		// remove multiple white spaces
		str = str.replace(/[\s]{2,}/, ' ');
		
		// remove leading and trailing space
		str = str.replace(/[\s]{2,}/g, ' ');
		str = str.replace(/^[\s]+/, '');
		str = str.replace(/[\s]+$/, '');
		
		str = str.toLowerCase();
		return str;
	} 