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

var Contact = Class.create({
    initialize: function(toCopy) {
        this.phoneNumbers = [];
        this.addresses = [];
        this.emailAddresses = [];
        this.imNames = [];
        this.urls = [];
        Object.extend(this, toCopy);
        this.fixup();
    },
    
    getFullName: function() {
        return Contact.getFullName(this);
    },
    
    fixup: function() {
        Contact.fixup(this);
    },
	
    nameCharacterBlacklist: "[]!@#$^*()-%1234567890=*/.",
	
    setFullName: function(name) {
        this.parseName(name);
    },
	
    parseName: function(name) {
        this.prefix = null;
        this.suffix = null;
        this.firstName = null;
        this.middleName = null;
        this.lastName = null;
        if (!name) {
            return; //There's no way to delete someones name so i took this out so we could
		}
		
        var result = name.strip().split(' ');
        var actualParts = [];
        var blacklist = this.nameCharacterBlacklist;
        
        result.each(function(part) {
			//if the user types multiple spaces accidentally, ignore them
			if (part.strip().length !== 0) {
				if (blacklist.indexOf(part.charAt(0)) === -1) {
	                actualParts.push(part);
	            } else {
	                if (actualParts[actualParts.length - 1]) {
	                    actualParts[actualParts.length - 1] = actualParts[actualParts.length - 1] + " " + part;
	                } else {
	                    actualParts.push(part);
	                }
	            }
			}
        });
		
        var that = this;
        if (actualParts.length > 1) {
            Contact.PREFIXES.each(function(prefix) {
                var lowered = actualParts[0].toLowerCase();
                if (lowered == prefix || lowered == prefix + ".") {
                    that.prefix = actualParts.shift();
                    throw $break;
                }
            });
            Contact.SUFFIXES.each(function(suffix) {
                var lastItem = actualParts.last();
                lastItem = lastItem.strip().gsub(/\./, "").toLowerCase();
                if (suffix == lastItem) {
                    that.suffix = actualParts.pop();
                    throw $break;
                }
            });
        }
		
		//in spain and mexico, we parse names differently than in the rest of the world
		var countryCode = Mojo.Locale.getCurrentLocale().slice(-2).toLowerCase();
		if (countryCode === "es" || countryCode === "mx") {
			this.parseSpanishName(actualParts);
		} else {
			this.parseEnglishName(actualParts);
		}
	},
	
	/*
	 * This is how names are parsed for Spanish names:
	 *    1
	 *    F
	 *
	 *    1 2
	 *    F L
	 *
	 *    1 2 3
	 *    F L L
	 *
	 *    1 2 3 4
	 *    F F L L 
	 *
	 *    1 2 3 4 5
	 *    F F L L L
	 * 
	 * Unless there's one of { 'and', 'or', '&', '+' }, in which case it's:
	 *     1
	 *     F
	 * 
	 *     1 2
	 *     F L
	 * 
	 *     1 2 3
	 *     F A F
	 *     A L L
	 *     F L L
	 * 
	 *     1 2 3 4
	 *     A L L L
	 *     F A F L
	 *     F F A F
	 *     F F F A
	 * 
	 *     1 2 3 4 5
	 *     A L L L L
	 *     F A F L L
	 *     F F A F L
	 *     F F F A F
	 *     F F F F A
     */
	parseSpanishName: function(nameParts) {
        if (nameParts.length === 1) {
			//we do F
            this.firstName = nameParts[0];
        } else if (nameParts.length === 2) {
			//we do FL
            this.firstName = nameParts[0];
            this.lastName = nameParts[1];
        } else if (nameParts.length === 3) {
			var andIndex = this.findLastAnd(nameParts);
			//if there's an 'and' in the middle spot, put everything in the first name
			if (andIndex === 1) {
				this.firstName = nameParts[0] + " " + nameParts[1] + " " + nameParts[2];
			} else {
				//else, do FLL
				this.firstName = nameParts[0];
				this.lastName = nameParts[1] + " " + nameParts[2];
			}
		} else if (nameParts.length > 3) {
			//there are at least 4 parts to this name
			
			var andIndex = this.findLastAnd(nameParts);
			if (andIndex > 0) {
				//if there's an 'and' that's not the first token, put everything up to and including the token after it into the first name and everything else in to the last
				this.parseFFAFLLName(nameParts, andIndex);
			} else {
				//put the first two parts into the first name and everything else into the last name - FFLLLL
				
	            this.firstName = nameParts[0] + " " + nameParts[1];
				
	            this.lastName = "";
				for (var i = 2; i < nameParts.length; i++) {
					this.lastName += nameParts[i] + " ";
				}
				this.lastName = this.lastName.strip();
			}
        }
	},
	
	/*
	 * This is how names are parsed for English names:
	 *     1
	 *     F
	 * 
	 *     1 2
	 *     F L
	 * 
	 *     1 2 3
	 *     F M L
	 * 
	 *     1 2 3 4
	 *     F M L L 
	 * 
	 *     1 2 3 4 5
	 *     F M L L L
	 * 
	 * Unless there's one of { 'and', 'or', '&', '+' }, in which case it's:
	 *     1
	 *     F
	 * 
	 *     1 2
	 *     F L
	 * 
	 *     1 2 3
	 *     A F F
	 *     F A F
	 *     F F A
	 * 
	 *     1 2 3 4
	 *     A M L L
	 *     F A F L
	 *     F F A F
	 *     F F F A
	 * 
	 *     1 2 3 4 5
	 *     A M L L L
	 *     F A F L L
	 *     F F A F L
	 *     F F F A F
	 *     F F F F A
	 */
	parseEnglishName: function(nameParts) {
        if (nameParts.length == 1) {
			//we do F
            this.firstName = nameParts[0];
        } else if (nameParts.length == 2) {
			//we do FL
            this.firstName = nameParts[0];
            this.lastName = nameParts[1];
        } else if (nameParts.length >= 3) {
			//find the first instance of 'and' in the name
			var andIndex = this.findLastAnd(nameParts);
			
			if (andIndex > 0) {
				//if there's an 'and' that's not the first token, put everything up to and including the token after it into the first name and everything else in to the last
				this.parseFFAFLLName(nameParts, andIndex);
			} else {
				//since there's no viable 'and', we do FMLLL
				
				this.firstName = nameParts[0];
				this.middleName = nameParts[1];
				
	            this.lastName = "";
	            for (var i = 2; i < nameParts.length; i++) {
	                this.lastName += nameParts[i] + " ";
	            }
	            this.lastName = this.lastName.strip();
			}
        }
    },
	
	//this sets the first name to be up to and including the token after the andIndex, with everything else going into the last name
	parseFFAFLLName: function(nameParts, andIndex) {
        this.firstName = "";
		var i;
		for (i = 0; i <= andIndex + 1; i++) {
			if (i >= nameParts.length) {
				break;
			}
			
			this.firstName += nameParts[i] + " ";
		}
		this.firstName = this.firstName.strip();
		
		this.lastName = "";
		for (/* use val of i from above */; i < nameParts.length; i++) {
			this.lastName += nameParts[i] + " ";
		}
		this.lastName = this.lastName.strip();
	},
	
	//find the last instance of 'and' in the name
	findLastAnd: function(nameParts) {
		var andIndex = -1;
		nameParts.each(function(part, index) {
			if (($L({key: "and1", value: "and"}).toLowerCase() === part.toLowerCase()) 
				|| ($L({key: "and2", value: "and"}).toLowerCase() === part.toLowerCase()) 
				|| ($L({key: "or1", value: "or"}).toLowerCase() === part.toLowerCase()) 
				|| ($L({key: "or2", value: "or"}).toLowerCase() === part.toLowerCase()) 
				|| ("&" === part) 
				|| ("+" === part)) {
				andIndex = index;
			}
		});
		return andIndex;
	},
    
    deepClone: function() {
        var c = Object.clone(this);
        if (this.phoneNumbers) {
            c.phoneNumbers = this.phoneNumbers.clone();
		}
        if (this.emailAddresses) { 
            c.emailAddresses = this.emailAddresses.clone();
		}
        if (this.addresses) {
            c.addresses = this.addresses.clone();
		}
        return c;
    }
    
});

Contact.numberFields = ['imAvailability', 'contactCount', 'isMe'];

Contact.fixup = function(c) {
    // initialize some commonly used formatted properties
    if (c.fullName) {
        c.parseName(c.fullName);
    }
    // fix up the number->string munging that returnStrings does
    for (var i = 0; i < Contact.numberFields.length; i++) {
        var str = c[Contact.numberFields[i]];
        if (str) {
            c[Contact.numberFields[i]] = parseInt(str);
        }
    }
    
    c.pic = null;
    if (c.pictureLocSquare) {
        c.pic = c.pictureLocSquare;
    } else if (c.imAvatarLoc) {
        c.pic = c.imAvatarLoc;
    }
    if (!c.pic) {
        c.pic = "";
        c.listPic = Contact.DEFAULT_LIST_AVATAR;
    } else {
        c.listPic = c.pic;
    }
    
    if (c.contactCount > 1) {
        c.isClipped = "clipped";
        c.listFrame = Contact.FRAME_CLIPPED_DEFAULT;
    } else {
        c.listFrame = Contact.FRAME_SINGLE;
    }
};

Contact.nameFields = ['prefix', 'firstName', 'middleName', 'lastName', 'suffix'];

Contact.getFullName = function(c) {
    var name = '';
    var first = true;
    for (var i = 0; i < Contact.nameFields.length; i++) {
        var val = c[Contact.nameFields[i]];
        if (val) {
            if (first) {
                first = false;
            } else {
                name += ' ';
            }
            name += val;
        }
    }
    
    if (name.blank()) {
        name = c.displayText || "";
    }
    
    return name;
};

Contact.setAllPicturePaths = function(contact, smallpic, bigpic) {
    contact.pictureLoc = smallpic;
    contact.listPic = smallpic || Contact.DEFAULT_LIST_AVATAR;
    contact.pictureLocSquare = smallpic;
    contact.pictureLocBig = bigpic;
    contact.pic = smallpic;
};

Contact.getWorkInfoLine = function(c) {
    var workItems = ['jobTitle', 'deptName', 'companyName'];
    var workInfoLine = workItems.inject('', function(acc, n) {
        if (c[n]) {
            acc += c[n] + ', ';
        }
        return acc;
    });
    return workInfoLine.substr(0, workInfoLine.length - 2); // remove the last comma
};
/*
 * Copies contact points from the "from" contact, onto the "to" contact
 * 
 * Both must be valid extended contacts, or some copying might not occur
 */
Contact.copyContactPoints = function(to, from) {
	Contact.contactPointArrays.each(function(type) {
		if (to[type] === undefined) {
			to[type] = from[type];
		} else {
			from[type].each(function(item) {
				to[type].push(item);
			});
		}
	});
};

Contact.copyProperties = function(to, from) {
    Contact.copyContactPoints(to, from);
};

Contact.contactPointArrays = ["phoneNumbers", "emailAddresses", "imNames", "urls", "addresses"];

Contact.DEFAULT_LIST_AVATAR = "images/list-avatar-default.jpg";
Contact.FRAME_CLIPPED_DEFAULT = "images/list-avatar-frame-clipped-default.png";
Contact.FRAME_SINGLE ="images/list-avatar-frame-single.png";
Contact.DEFAULT_DETAILS_AVATAR ="images/generic-details-view-avatar.png";  
Contact.PREFIXES = ["mr", "miss", "mrs", "ms", "dr"];
Contact.SUFFIXES = ["jr", "sr", "i", "ii", "iii", "iv", "v", "vi", "phd", "md"];
