﻿/*  Typically called from Action site, fields first and last name, but also for street, etc. See second parameter.
		
	The value of the given field will be handled as follows:
	- remove leading and attached spaces,
	- remove too many spaces,
	- change "<n spaces>-<n spaces>" to "<one space>-<one space>"

	- Starts with Dr.  : Change "dr<X><space>"             to "Dr.<X><space>"          where <X> is "nothing", "." or "-"
	- Dr. inbetween    : Change "<space>dr<X><space>"      to "<space>Dr.<X><space>"   where <X> is "nothing", "." or "-"    
	- Ends with Dr.    : Change "<space>dr<X>"             to "<space>Dr.<X>"          where <X> is "nothing", "." or "-"

	- Starts with Prof.: Change "prof<X><space>"         to "Prof<X><space>"         where <X> is "nothing", "." or "-"
	- Prof. inbetween  : Change "<space>prof<X><space>"  to "<space>Prof<X><space>"  where <X> is "nothing", "." or "-"   
	- Ends with Prof.  : Change "<space>prof<X>"         to "<space>Prof<X>"         where <X> is "nothing", "." or "-"

	- only if field type set to "isStreetField"
		- add a dot if value ends with "str" (keyinsensitive)
		- change "strasse" to "straße"       (keyinsensitive, n-time checked )
		- change "str" to "Str" when field value ends with "er str", "-str" or "<space>str"     (condition 1 is subcondition of condition 3!)

	- split based on "val_Delimiter", 
	- the resulting array elements cleaned based on "val_PartsToKick"
	and
	- the first letter of the resulting array elements will be changed to capital letter and all following characters to lower letters

	Input: 
		First parameter:
			"this" or the ID of an field which value should be handled as described above.
			like
				ValidateAddressData(this);
				or
				ValidateAddressData("#PersonData_PersonalDataView_Familyname");


		Second parameter:
			Defines the type of the given field.
				"ValidateAddressFieldTypes.isStandardField" is for example used for first and last name validation (of Action site)
				"ValidateAddressFieldTypes.isStreetField"   used to run the standard logic plus special validations/changes for street fields.


	This test value contains most part which must be changed:
		"   mueller   -    luedenscheid prof prof. prof dr. dr   dr.   dr   med., von und zu     geborene van der maehr   Fhr. auf dem deich "

*/


var ValidateAddressFieldTypes = {   "isStandardField" : 0,
									"isStreetField"   : 1
								};

var val_Delimiter = [   ' ',
						'-',
						'.',
						'/'
					];

var val_PartsToKick = [ 'auf',
						'del',
						'dem',
                        'den',
						'der',
						'des',
						'Fhr',
						'med',
                        'str',
                        'und',
                        'van',
                        'vom',
                        'von',
                        'zum',
                        'zur',
						'Firma',
						'GbR',
						'GmbH',
						'geb',
						'geboren',
						'geborene',
						'geborener'
					  ];

function ValidateAddressData(senderOrSenderID, fieldType) {
	var field;
	var fieldValue = null;

	var typeTest = (typeof (senderOrSenderID)).toLowerCase();
	switch (typeTest) {
		case 'string':
			{
				var addHash = '';
				if (!startsWith(senderOrSenderID, '#', true))
					addHash = "#";

				field = $(addHash + senderOrSenderID);
				if ((!field) || (typeof field == 'undefined'))
					return;

				fieldValue = field.val();
				break;
			}
		case 'object':
			{
				field = $(senderOrSenderID);
				fieldValue = field.val();
				break;
			}
		default:
			{
				return;
			}
	}

	if ((!fieldValue) || (fieldValue == '') || (typeof fieldValue == 'undefined'))
		return;

	if ((!val_Delimiter) || (typeof val_Delimiter == 'undefined'))
		return;

	if (val_Delimiter.length < 1)
		return;

	if ((!val_PartsToKick) || (typeof val_PartsToKick == 'undefined'))
		return;


	// Some interesting testing values
	// fieldValue = "aaa.bbb/ccc ddd/eee.fff";
	// fieldValue = "mueller-lüdenscheid dr. med., von und zu geborene van der maehr Fhr. auf dem deich";
	// fieldValue = "deich-deich";


	// 1.) General changes
	fieldValue = $.trim(fieldValue);    // Remove leading and attached spaces

	var lenBefore = 0;

	do {                                // Remove too many spaces 
		lenBefore = fieldValue.length;
		fieldValue = fieldValue.replace("  ", " ");
	}
	while (lenBefore != fieldValue.length)

	do {                                // Changing "<n spaces>-<n spaces>" to "<1 space>-<1 space>"    where n = {0, 1, ... }
		lenBefore = fieldValue.length;
		fieldValue = fieldValue.replace(" - ", "-").replace(" -" , "-").replace("- ", "-");
	}
	while (lenBefore != fieldValue.length)


	
	// "Dr" handling
    fieldValue = handleProfAndDr(fieldValue, "dr", "Dr");
	


	/*
		1 "prof Mayer"          -> "Prof. Mayer"
		2 "prof-dr Mayer"       -> "Prof.-Dr. Mayer"
		3   "prof - dr Mayer"   -> based on " - " already changed to "prof-dr Mayer" and thats case 2
			"prof- dr Mayer"    -> based on "- "  already changed to "prof-dr Mayer" and thats case 2
			"prof -dr Mayer"    -> based on " -"  already changed to "prof-dr Mayer" and thats case 2

		  "xxx prof yyy"        -> xxx Prof. yyy
		  "xxx prof. yyy"       -> xxx Prof. yyy
    	  "xxx prof- yyy"       -> xxx Prof.-yyy

		4 "Mayer, prof"         -> "Mayer, Prof."
		5 "Mayer, prof-dr"      -> "Mayer, Prof.-Dr."
		6   "Mayer, prof - dr"  -> based on " - " already changed to "Mayer, prof-dr" and thats case 5
			"Mayer, prof- dr"   -> based on "- "  already changed to "Mayer, prof-dr" and thats case 5
			"Mayer, prof -dr"   -> based on " -"  already changed to "Mayer, prof-dr" and thats case 5
	*/
    // "Prof" handling
    fieldValue = handleProfAndDr(fieldValue, "prof", "Prof");



	if (fieldType == ValidateAddressFieldTypes.isStreetField) {
		if (endsWith(fieldValue, "str", true))                                  // Add a dot if value ends with "str" (keyinsensitive)
			fieldValue += ".";

		// test value: "StRasSE    -  der sTRAsSEn"
		// looping because theoretically possible that field value contains "strasse" more than once
		do {                                                                    //  Change "strasse" to "straße" (keyinsensitive)
			lenBefore = fieldValue.length;

			var posStr = fieldValue.toUpperCase().indexOf("STRASSE");           
			if (posStr != -1) {
				var oriStrValue = fieldValue.substr(posStr, "strasse".length);
				var oriFirstCharacterStr = fieldValue.substr(posStr, 1);
				var changedStrValue = oriFirstCharacterStr + "traße";
				fieldValue = fieldValue.replace(oriStrValue, changedStrValue);
			}
		}
		while (lenBefore != fieldValue.length)

		// "er str" or "er str." keyinsensitive, like "barer str" -> "Barer Str." and "barer str." -> "Barer Str."
		if (    (endsWith(fieldValue, "er str.", true))             // "er str. abc def barER sTR."
				||
				(endsWith(fieldValue, "-str.", true))               // "qq-str. abc def bahnHOf-sTR."
				||
				(endsWith(fieldValue, " str.", true))               // "hugo  str.  erika  mann   sTR."
		   )
		{
			var posErStr = fieldValue.length - "str.".length;          
			var beforeERStr = fieldValue.substr(0, posErStr);           // "er str. abc def barER "
			fieldValue = beforeERStr + "Str.";
		}
	}



	// 2.) Split
	var parts = fieldValue.split(val_Delimiter[0]);
	if (val_Delimiter.length > 1) {
		if (val_Delimiter.length > 0) {
			for (var a = 1; a < val_Delimiter.length; a++) {
				var parts = mainSplit(parts, val_Delimiter[a]);
			}
		}
	}

	if ((!parts) || (typeof parts == 'undefined'))
		return;

	if (parts.length < 1)
		return;


	// 3.) Remove
	var cleanArray = new Array();
	for (var b = 0; b < parts.length; b++) {
		var addIt = true;

		if (parts[b].length < 3)                                                        // less then n letters
			continue;
		else if ((parts[b].length == 3) && (parts[b].toUpperCase() == parts[b]))        // exact n letters and all n letters are capital 
			continue;
		else {
			for (var c = 0; c < val_PartsToKick.length; c++) {
				if (parts[b].toLowerCase() == val_PartsToKick[c].toLowerCase()) {       // part is in exclude list
					addIt = false;
					break;
				}
			}
		}

		if (addIt)
			cleanArray.push(parts[b]);
	}


	// 4.) Change
	/*  Original value = "mueller-luedenscheid dr. med., von und zu geborene van der maehr Fhr. auf dem deich"
	cleanArray will then contain only for elements 
	cleanArray[0] = "mueller"
	cleanArray[1] = "lüdenscheid"
	cleanArray[2] = "maehr"
	cleanArray[3] = "deich"
	*/
	var oriValue = '';
	var firstCharacter = '';
	var after = '';
	var changedValue = '';
	for (var d = 0; d < cleanArray.length; d++) {
		oriValue = cleanArray[d];
		firstCharacter = cleanArray[d].substr(0, 1);    // "0" means first character becasue of zero based counting

		after = '';
		if (cleanArray[d].length > 1)                   // Based on rule that a "part"/"array element" has a minimum length of three characters will this alwyas be true, but to be on safe side...
			after = cleanArray[d].substr(1);

		changedValue = firstCharacter.toUpperCase() + after.toLowerCase();
		
		// replace the changed value at the correct palce in field value
		fieldValue = fieldValue.replace(oriValue, changedValue);
	}

	field.val(fieldValue);
}

function mainSplit(partsArray, oneDelimiter) {
	if ((partsArray == null) || (partsArray == ''))
		return;

	if (partsArray.length == 0)
		return;

	if ((oneDelimiter == null) || (oneDelimiter == ''))
		return;

	if (oneDelimiter.length != 1)
		return;

	var retArray = new Array();
	for (var a = 0; a < partsArray.length; a++) {
		var tmpArray = partsArray[a].split(oneDelimiter);

		for (var b = 0; b < tmpArray.length; b++) {
			retArray.push(tmpArray[b]);
		}
	}

	return retArray;
}

function handleProfAndDr(fieldValue, searchTitle, correctTitle) {
    // Looping because its possible that field value contains multiple "dr"
    var pos = fieldValue.indexOf(searchTitle);
	while ( pos != -1 ) {
        var oneCharacterBefore = '';
        var allCharactersBefore = '';
        if (pos > 0) {
            oneCharacterBefore = fieldValue.substr(pos - 1, 1);     // take exact one character before "prof"
            allCharactersBefore = fieldValue.substr(0, pos);        // take all chracters before "prof"
        }

        var oneCharacterAfter = '';
        var allCharactersAfter = '';
        if ((pos + searchTitle.length) < fieldValue.length) {
            oneCharacterAfter = fieldValue.substr(pos + searchTitle.length, 1); // take exact one character after "prof"
            allCharactersAfter = fieldValue.substr(pos + searchTitle.length);   // take all characters after "prof"
        }
        
        switch (oneCharacterBefore) {
            case '':
            case ' ':
            case '.':
            case '-':
                {
                    var addThisAfterTitle = '';
                    switch (oneCharacterAfter) 
                    {
                        case '':
                        case ' ':
                        case '-':
                            addThisAfterTitle = '.';
                        case '.':
                            fieldValue = allCharactersBefore + correctTitle + addThisAfterTitle + allCharactersAfter;
                            break;
                    }
                    break;
                }
        }

        pos = fieldValue.indexOf(searchTitle, pos + 1);
    }
   
    return fieldValue;
}
