/*
 * Copyright 2005 - 2009  Zarafa B.V.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3, 
 * as published by the Free Software Foundation with the following additional 
 * term according to sec. 7:
 *  
 * According to sec. 7 of the GNU Affero General Public License, version
 * 3, the terms of the AGPL are supplemented with the following terms:
 * 
 * "Zarafa" is a registered trademark of Zarafa B.V. The licensing of
 * the Program under the AGPL does not imply a trademark license.
 * Therefore any rights, title and interest in our trademarks remain
 * entirely with us.
 * 
 * However, if you propagate an unmodified version of the Program you are
 * allowed to use the term "Zarafa" to indicate that you distribute the
 * Program. Furthermore you may use our trademarks where it is necessary
 * to indicate the intended purpose of a product or service provided you
 * use it in accordance with honest practices in industrial or commercial
 * matters.  If you want to propagate modified versions of the Program
 * under the name "Zarafa" or "Zarafa Server", you may only do so if you
 * have a written permission by Zarafa B.V. (to acquire a permission
 * please contact Zarafa at trademark@zarafa.com).
 * 
 * The interactive user interface of the software displays an attribution
 * notice containing the term "Zarafa" and/or the logo of Zarafa.
 * Interactive user interfaces of unmodified and modified versions must
 * display Appropriate Legal Notices according to sec. 5 of the GNU
 * Affero General Public License, version 3, when you propagate
 * unmodified or modified versions of the Program. In accordance with
 * sec. 7 b) of the GNU Affero General Public License, version 3, these
 * Appropriate Legal Notices must retain the logo of Zarafa or display
 * the words "Initial Development by Zarafa" if the display of the logo
 * is not reasonably feasible for technical reasons."
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *  
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

contactitemmodule.prototype = new ItemModule;
contactitemmodule.prototype.constructor = contactitemmodule;
contactitemmodule.superclass = ItemModule.prototype;

function contactitemmodule(id)
{
	if(arguments.length > 0) {
		this.init(id);
	}
}

contactitemmodule.prototype.init = function(id)
{
	// display name prefixes
	var titles = new Object();
	titles["none"] = "";
	titles["dr."] = _("Dr.");
	titles["miss"] = _("Miss");
	titles["mr."] = _("Mr.");
	titles["mrs."] = _("Mrs.");
	titles["ms."] = _("Ms.");
	titles["prof."] = _("Prof.");
	this.titleOptions = titles;

	// display name suffixes
	var suffix = new Object();
	suffix["none"] = "";
	suffix["I"] = "I";
	suffix["II"] = "II";
	suffix["III"] = "III";
	suffix["jr."] = _("Jr.");
	suffix["sr."] = _("Sr.");
	this.suffixOptions = suffix;

	// address types
	var address_type = new Object();
	address_type["home"] = _("Home");
	address_type["business"] = _("Business");
	address_type["other"] = _("Other");
	this.address_type = address_type;

	// phone number types
	var phone_type = new Object();
	phone_type["assistant"] = _("Assistant");	phone_type["office"] = _("Business");
	phone_type["business2"] = _("Business 2");	phone_type["business_fax"] = _("Business Fax");
	phone_type["callback"] = _("Callback");		phone_type["car"] = _("Car");
	phone_type["company"] = _("Company");		phone_type["home"] = _("Home");
	phone_type["home2"] = _("Home 2");			phone_type["home_fax"] = _("Home Fax");
	phone_type["isdn"] = _("ISDN");				phone_type["cellular"] = _("Mobile");		
	phone_type["other"] = _("Other");			phone_type["primary_fax"] = _("Other Fax");
	phone_type["pager"] = _("Pager");			phone_type["primary"] = _("Primary");
	phone_type["radio"] = _("Radio");			phone_type["telex"] = _("Telex");
	phone_type["ttytdd"] = _("TTY/TDD");
	this.phone_type = phone_type;

	contactitemmodule.superclass.init.call(this, id);
}

contactitemmodule.prototype.executeOnLoad = function()
{
	initContact();
}

contactitemmodule.prototype.save = function(props, email_addresses, dialog_attachments)
{
	var data = new Object();
	if(this.storeid) {
		data["store"] = this.storeid;
	}
	
	if(this.parententryid) {
		data["parententryid"] = this.parententryid;
	}
	
	data["props"] = props;
	data["dialog_attachments"] = dialog_attachments;
	data["email_addresses"] = email_addresses;
	
	if(parentWebclient) {
		parentWebclient.xmlrequest.addData(this, "save", data, webclient.modulePrefix);
		parentWebclient.xmlrequest.sendRequest(true);
	} else {
		webclient.xmlrequest.addData(this, "save", data);
		webclient.xmlrequest.sendRequest();
	}
}

/**
 * Function will get data from advprompt dialog and store it in html elements
 * @param array data[element id] => value
 * @param string value can be full_name, address or phone_number
 * @param boolean stored info should be only stored or displayed to user
 */
contactitemmodule.prototype.storeDetailedInfo = function (data, type, show) {
	var display_name = "", address = "", address_prefix = "", phone_number = "";

	switch(type) {
		case "full_name":
			// check for missing field values
			data["title"] = typeof data["title"] != "undefined" ? data["title"] : "";
			data["first_name"] = typeof data["first_name"] != "undefined" ? data["first_name"] : "";
			data["middle_name"] = typeof data["middle_name"] != "undefined" ? data["middle_name"] : "";
			data["last_name"] = typeof data["last_name"] != "undefined" ? data["last_name"] : "";
			data["suffix"] = typeof data["suffix"] != "undefined" ? data["suffix"] : "";

			// save result to hidden variables
			dhtml.getElementById("display_name_prefix").value = data["title"];
			dhtml.getElementById("given_name").value = data["first_name"];
			dhtml.getElementById("middle_name").value = data["middle_name"];
			dhtml.getElementById("surname").value = data["last_name"];
			dhtml.getElementById("generation").value = data["suffix"];

			if(typeof show != "undefined" && show == true) {
				display_name = (data["title"] != "") ? data["title"] + NBSP : "";
				display_name += (data["first_name"] != "") ? data["first_name"] + NBSP : "";
				display_name += (data["middle_name"] != "") ? data["middle_name"] + NBSP : "";
				display_name += (data["last_name"] != "") ? data["last_name"] + NBSP : "";
				display_name += (data["suffix"] != "") ? data["suffix"] : "";

				// remove white spaces
				display_name = display_name.trim();

				// set value for display name input box
				dhtml.getElementById("display_name").value = display_name;
			}

			// convert true/false boolean type values to string type to store it in settings
			webclient.settings.set("addressbook/show_detailed_name_dialog", (data["setting"] == true) ? "true" : "false");

			// set value for fileas field
			setFileAs();
			break;
		case "phone_number":
			// check for missing field values
			data["country_code"] = typeof data["country_code"] != "undefined" ? data["country_code"] : "";
			data["city_code"] = typeof data["city_code"] != "undefined" ? data["city_code"] : "";
			data["local_number"] = typeof data["local_number"] != "undefined" ? data["local_number"] : "";
			data["extension"] = typeof data["extension"] != "undefined" ? data["extension"] : "";

			phone_number = (data["country_code"] != "")? data["country_code"] + NBSP: "";
			phone_number += (data["city_code"] != "")? "(" + data["city_code"] + ")" + NBSP: "";
			phone_number += (data["local_number"] != "")? data["local_number"] + NBSP: "";
			phone_number += (data["extension"] != "")? "x" + NBSP + data["extension"]: "";

			// remove white spaces
			phone_number = phone_number.trim();

			// set value for phone number input box
			dhtml.getElementById(this.selectedPhoneInputID).value = phone_number;
			break;
		case "address":
			// check which address is selected
			address_prefix = "business";
			switch(dhtml.getElementById("selected_address").value)
			{
				case "1":
					address_prefix = "home";
					break;
				case "3":
					address_prefix = "other";
					break;
			}

			// check for missing field values
			data["street"] = typeof data["street"] != "undefined" ? data["street"] : "";
			data["city"] = typeof data["city"] != "undefined" ? data["city"] : "";
			data["state"] = typeof data["state"] != "undefined" ? data["state"] : "";
			data["zip"] = typeof data["zip"] != "undefined" ? data["zip"] : "";
			data["country"] = typeof data["country"] != "undefined" ? data["country"] : "";

			// save result to hidden variables
			dhtml.getElementById(address_prefix + "_address_street").value = data["street"];
			dhtml.getElementById(address_prefix + "_address_city").value = data["city"];
			dhtml.getElementById(address_prefix + "_address_state").value = data["state"];
			dhtml.getElementById(address_prefix + "_address_postal_code").value = data["zip"];
			dhtml.getElementById(address_prefix + "_address_country").value = data["country"];

			if(typeof show != "undefined" && show == true) {
				address = (data["street"] != "") ? data["street"] + CRLF : "";
				address += (data["city"] != "") ? data["city"] + NBSP : "";
				address += (data["state"] != "") ? data["state"] + NBSP : "";
				address += (data["zip"] != "") ? data["zip"] + CRLF : "";
				address += (data["country"] != "") ? data["country"] : "";

				// remove white spaces
				address = address.trim();

				dhtml.getElementById(address_prefix + "_address").value = address;
				// set value for address textarea
				dhtml.getElementById("address").value = address;
			}

			// convert true/false boolean type values to string type to store it in settings
			webclient.settings.set("addressbook/show_detailed_address_dialog", (data["setting"] == true) ? "true" : "false");
			break;
	}
}

/**
 * Function will parse data from html elements and give results to advprompt dialog
 * @param array data[element id] => value
 * @param string value can be full_name, address or phone_number
 * @param boolean result should be returned or not
 * @return object result[key] => value
 */
contactitemmodule.prototype.parseDetailedInfo = function (data, type, returnResult) {
	var result = new Object();
	this.showDialog = false;

	// @TODO improve parsing logic
	switch(type) {
		case "full_name":
			// parse full name and return an object with all fields
			if(data.length >= 1) {
				result = this.parseDetailedFullNameInfo(data);
			}

			// check that dialog should be displayed when field is incomplete or unclear
			var settingValue = webclient.settings.get("addressbook/show_detailed_name_dialog", "true");
			// convert true/false string type values to boolean type
			settingValue = (settingValue == "true") ? true : false;
			result["setting"] = settingValue;

			if(returnResult == false && this.showDialog == true) {
				if(settingValue == true) {
					dhtml.executeEvent(dhtml.getElementById("fullname_button"), "click");
				}
				this.showDialog = false;
			}

			// store different field values to appropriate hidden variables
			this.storeDetailedInfo(result, type, false);
			break;
		case "phone_number":
			// parse phone number and return an object with all fields
			if(data.length >= 1) {
				result = this.parseDetailedPhoneNumberInfo(data);
			}
			break;
		case "address":
			// parse address and return an object with all fields
			if(data.length >= 1) {
				result = this.parseDetailedAddressInfo(data);
			}

			// check that dialog should be displayed when field is incomplete or unclear
			var settingValue = webclient.settings.get("addressbook/show_detailed_address_dialog", "true");
			// convert true/false string type values to boolean type
			settingValue = (settingValue == "true") ? true : false;
			result["setting"] = settingValue;

			if(returnResult == false && this.showDialog == true) {
				if(settingValue == true) {
					dhtml.executeEvent(dhtml.getElementById("address_button"), "click");
				}
				this.showDialog = false;
			}

			// store different field values to appropriate hidden variables
			this.storeDetailedInfo(result, type, false);
			break;
	}

	if(typeof returnResult != "undefined" && returnResult == true) {
		return result;
	}
}

/**
 * Function will parse data and return an object with different fields
 * @param array data[element id] => value
 * @return object result[key] => value
 */
contactitemmodule.prototype.parseDetailedFullNameInfo = function (data) {
	var result = new Object();
	var displayNameParts = new Array();
	var firstElement, lastElement;

	// split display name ([0] => title, [1] => first_name, [2] => middle_name,
	//						[3] => last_name, [4] => suffix)
	displayNameParts = data.split(/\xA0|\x20/g); // \u0020 => space, \u00a0 => No-break space

	// Remove white spaces in array
	var tmpParts = displayNameParts;
	displayNameParts = new Array();
	for(var key in tmpParts)
	{
		if(tmpParts[key].length > 0 && tmpParts[key].trim() != "") {
			displayNameParts.push(tmpParts[key].trim());
		}
	}

	switch(displayNameParts.length) {
		case 5:
			result["title"] = displayNameParts.shift();
			result["first_name"] = displayNameParts.shift();
			result["middle_name"] = displayNameParts.shift();
			result["last_name"] = displayNameParts.shift();
			result["suffix"] = displayNameParts.shift();
			break;
		case 4:
			// search for display name prefix in name
			firstElement = displayNameParts.shift();
			for(var key in this.titleOptions) {
				if(this.titleOptions[key].toLowerCase() == firstElement.toLowerCase()) {
					result["title"] = firstElement;
					break;
				} else {
					result["title"] = "";
				}
			}

			// search for suffix in name
			lastElement = displayNameParts.pop();
			for(var key in this.suffixOptions) {
				if(this.suffixOptions[key].toLowerCase() == lastElement.toLowerCase()) {
					result["suffix"] = lastElement;
					break;
				} else {
					result["suffix"] = "";
				}
			}

			result["first_name"] = ( result["title"] != "" ) ? displayNameParts.shift() : firstElement;
			result["last_name"] = ( result["suffix"] != "" ) ? displayNameParts.pop() : lastElement;
			result["middle_name"] = ( displayNameParts.length > 0 ) ? displayNameParts.shift() : "";
			break;
		case 3:
			// search for display name prefix in name
			firstElement = displayNameParts.shift();
			for(var key in this.titleOptions) {
				if(this.titleOptions[key].toLowerCase() == firstElement.toLowerCase()) {
					result["title"] = firstElement;
					break;
				} else {
					result["title"] = "";
				}
			}

			// search for suffix in name
			lastElement = displayNameParts.pop();
			for(var key in this.suffixOptions) {
				if(this.suffixOptions[key].toLowerCase() == lastElement.toLowerCase()) {
					result["suffix"] = lastElement;
					break;
				} else {
					result["suffix"] = "";
				}
			}

			if(result["title"] == "" && result["suffix"] == "") {
				result["first_name"] = firstElement;
				result["middle_name"] = displayNameParts.shift();
				result["last_name"] = lastElement;
			} else if(result["title"] != "" && result["suffix"] == "") {
				result["first_name"] = displayNameParts.shift();
				result["middle_name"] = "";
				result["last_name"] = lastElement;
			} else if(result["title"] == "" && result["suffix"] != "") {
				result["first_name"] = firstElement;
				result["middle_name"] = "";
				result["last_name"] = displayNameParts.shift();
			}
			break;
		case 2:
			// search for display name prefix in name
			firstElement = displayNameParts.shift();
			for(var key in this.titleOptions) {
				if(this.titleOptions[key].toLowerCase() == firstElement.toLowerCase()) {
					result["title"] = firstElement;
					break;
				} else {
					result["title"] = "";
				}
			}

			// search for suffix in name
			lastElement = displayNameParts.pop();
			for(var key in this.suffixOptions) {
				if(this.suffixOptions[key].toLowerCase() == lastElement.toLowerCase()) {
					result["suffix"] = lastElement;
					break;
				} else {
					result["suffix"] = "";
				}
			}

			if(result["title"] == "" && result["suffix"] == "") {
				result["first_name"] = firstElement;
				result["last_name"] = lastElement;
			} else if(result["title"] == "" && result["suffix"] != "") {
				result["last_name"] = firstElement;
				this.showDialog = true; // information entered is incomplete or unclear
			} else if(result["title"] != "" && result["suffix"] == "") {
				result["last_name"] = lastElement;
				this.showDialog = true; // information entered is incomplete or unclear
			}
			break;
		case 1:
			result["first_name"] = displayNameParts.shift();
			this.showDialog = true; // information entered is incomplete or unclear
			break;
		default:
			result["title"] = displayNameParts.shift();
			result["first_name"] = displayNameParts.shift();
			result["suffix"] = displayNameParts.pop();
			result["last_name"] = displayNameParts.pop();
			result["middle_name"] = displayNameParts.join(NBSP);
			break;
	}

	return result;
}

/**
 * Function will parse data and return an object with different fields
 * @param array data[element id] => value
 * @return object result[key] => value
 */
contactitemmodule.prototype.parseDetailedAddressInfo = function (data, type, returnResult) {
	var result = new Object();
	var addressParts = new Array();
	var singleLine;

	// split address ([0] => street, [1] => city state zip, [2] => country)
	addressParts = data.split(/\x0D|\x0A|\x0D\x0A/g); // \u000D => '\r' or carriage return
													  // \u000A => '\n' or new line

	// Remove white spaces in array
	var tmpParts = addressParts;
	addressParts = new Array();
	for(var key in tmpParts)
	{
		if(tmpParts[key].length > 0 && tmpParts[key].trim() != "") {
			addressParts.push(tmpParts[key].trim());
		}
	}

	switch(addressParts.length) {
		case 3:
			result["street"] = addressParts.shift();
			result["country"] = addressParts.pop();
			singleLine = addressParts.shift();
			break;
		case 2:
			result["street"] = addressParts.shift();
			singleLine = addressParts.shift();
			this.showDialog = true; // information entered is incomplete or unclear
			break;
		case 1:
			singleLine = addressParts.shift();
			this.showDialog = true; // information entered is incomplete or unclear
			break;
	}

	if(typeof singleLine != "undefined" && singleLine.length >= 1) {
		// split address ([0] => city, [1] => state, [2] => zip)
		addressParts = singleLine.split(/\xA0|\x20/g);

		// Remove white spaces in array
		var tmpParts = addressParts;
		addressParts = new Array();
		for(var key in tmpParts)
		{
			if(tmpParts[key].length > 0 && tmpParts[key].trim() != "") {
				addressParts.push(tmpParts[key].trim());
			}
		}

		switch(addressParts.length) {
			case 3:
				if(!isNaN(parseInt(addressParts[addressParts.length - 1]))) {
					result["zip"] = addressParts.pop();
				}
				result["state"] = addressParts.pop();
				result["city"] = addressParts.join(NBSP);
				break;
			case 2:
				result["city"] = addressParts.shift();
				result["state"] = addressParts.shift();
				break;
			case 1:
				result["city"] = addressParts.shift();
				break;
			default:
				if(!isNaN(parseInt(addressParts[addressParts.length - 1]))) {
					result["zip"] = addressParts.pop();
				}
				result["state"] = addressParts.pop();
				result["city"] = addressParts.join(NBSP);
		}
	}

	return result;
}

/**
 * Function will parse data and return an object with different fields
 * @param array data[element id] => value
 * @return object result[key] => value
 */
contactitemmodule.prototype.parseDetailedPhoneNumberInfo = function (data, type, returnResult) {
	var result = new Object();
	var phoneNumberParts = new Array();
	var tmpElement;

	// check for extension number
	if(data.indexOf("x") != -1) {
		result["extension"] = data.slice(data.indexOf("x"));
		// remove extension from phone number
		data = data.replace(result["extension"], "");

		// remove x character from extension
		result["extension"] = result["extension"].replace("x", "").trim();
	} else if(data.indexOf("/") != -1) {
		result["extension"] = data.slice(data.indexOf("/"));
		// remove extension from phone number
		data = data.replace(result["extension"], "");

		// remove / character from extension
		result["extension"] = result["extension"].replace("/", "").trim();
	}

	// split phone number ([0] => country_code, [1] => area_code, [2] => local_number)
	phoneNumberParts = data.split(/\xA0|\x20/g); // \u0020 => space, \u00a0 => No-break space

	// Remove white spaces in array
	var tmpParts = phoneNumberParts;
	phoneNumberParts = new Array();
	for(var key in tmpParts)
	{
		if(tmpParts[key].length > 0 && tmpParts[key].trim() != "") {
			phoneNumberParts.push(tmpParts[key].trim());
		}
	}

	switch(phoneNumberParts.length) {
		case 3:
			result["country_code"] = phoneNumberParts.shift();
			result["city_code"] = phoneNumberParts.shift().replace(/\(|\)/g, "");	// remove brackets from area code
			result["local_number"] = phoneNumberParts.shift();
			break;
		case 2:
			tmpElement = phoneNumberParts.shift();
			result["country_code"] = (tmpElement.indexOf("+") != -1) ? tmpElement : "";
			result["city_code"] = (result["country_code"] == "") ? tmpElement.replace(/\(|\)/g, "") : "";
			result["local_number"] = phoneNumberParts.shift();
			break;
		case 1:
			result["local_number"] = phoneNumberParts.shift();
			break;
		default:
			result["country_code"] = phoneNumberParts.shift();
			result["city_code"] = phoneNumberParts.shift().replace(/\(|\)/g, "");	// remove brackets from area code
			result["local_number"] = phoneNumberParts.join(NBSP);
			break;
	}

	return result;
}