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

var EditBehaviors = {
	observeSmallList: function(listId, listModel, labelsModel, newFunction){
		var list = this.controller.get(listId);
		var addHandler = this.handleAdd.bind(this, list, newFunction, listModel, labelsModel);
		list.observe(Mojo.Event.listAdd, addHandler);
		list.observe(Mojo.Event.listTap, this.handleListEditClick.bindAsEventListener(this, listId));
		list.observe(Mojo.Event.listDelete, this.swipeDelete.bindAsEventListener(this, listId, listModel));
		list.observe(Mojo.Event.propertyChange, this.propertyChanged.bindAsEventListener(this));
		list.observe("DOMFocusOut", this.handleListBlur.bindAsEventListener(this, list, listModel));
		list.observe("keyup", this.handleListInputEvents.bindAsEventListener(this, list, listModel));
	},
	
	validKeyCodes: [8, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57],
	
	renderLabels: function(){
		if (!this.editRules) {
			return;
		}
		this.phoneLabels.choices = this.editRules.phonePopupLabels;
		this.phoneLabels.choices = this.editRules.phonePopupLabels;
		this.messagingLabels.choices = this.editRules.messagingPopupLabels;
		this.emailLabels.choices = this.editRules.emailPopupLabels;
		this.addressLabels.choices = this.editRules.addressPopupLabels;
	},
	
	handleAdd: function(listDiv, makeNew, list, labels, e){
		var newModel = makeNew();
		this.findContactPointLabel(newModel, labels.choices);
		
		//need versions of setDirty() and removeFunction() on the model, so use it to save value until we save the model to the contact
		newModel.setDirty = function() {
			this.isDirty = true;
		};
		newModel.removeFunction = function() {
			this.hasBeenDeleted = true;
		};
		
		list.items.push(newModel);
		listDiv.mojo.noticeAddedItems(list.items.length, [newModel]);
		listDiv.mojo.focusItem(newModel);
		
		listDiv.observe("DOMFocusOut", this.handleListBlurAfterAdd.bindAsEventListener(this, newModel));
		
		/* fancy behavior!
		 * 1. hide the add div when initially adding a new item
		 * 2. reveal the add div if the user ever enters any text in the new field
		 * 3. if the user ever leaves a field blank delete or do not save the item
		 */
		/* hide the add item div */
		e.target.mojo.showAddItem(false);
		
		return newModel;
	},
	
	/*
	 * This is called whenever a property is changed on a widget in one of the contact poitn lists
	 * It could be a text field being changed or a list selector changing.
	 * Usually we just need to set the contact as dirty, but for addresses and phonenumbers we have to parse them
	 */
	propertyChanged: function(e){
		if (e.model.isAddress) {
			e.model.parseAddress(e.target.value);
		}
		if (e.model.isPhoneNumber) {
			e.model.displayValue = PhoneNumber.format(e.model.value);
			e.model.value = e.model.displayValue;
			e.target.mojo.setText(e.model.value); // TODO this shoudl just change the value of the textfield.
			//Awaiting fix on NOV-43372
		}
		//Property should be changed automatically, just need to set the contact as dirty
		e.model.setDirty();
		e.model.working = false;
	},
	
	addItemToContact: function(contact, item){
		if (item.removeFunction) {
			item.removeFunction(); //Remove it if it's already been added to someone else
		}
		var type;
		if (item.isPhoneNumber) {
			type = "phoneNumbers";
		}
		if (item.isEmailAddress) {
			type = "emailAddresses";
		}
		if (item.isUrl) {
			type = "urls";
		}
		if (item.isImAddress) {
			type = "imNames";
		}
		if (item.isAddress) {
			type = "addresses";
		}
		contact[type].push(item);
		contact.dirty = true;
		item.newContact = contact.newContact;
		//Tag this item as having been added to this contact, and be able to remove it in the future if necessary
		item.removeFunction = function(contact, item){
			if (item.id) {
				item.toDelete = true;
				contact.dirty = true;
			}
			else {
				contact[type] = Utilities.removeFromArray(contact[type], item);
				contact.dirty = true;
			}
		}.curry(contact, item);
	},
	
	createContactWithAccount: function(accountId, syncSource){
		var newContact = new Contact();
		newContact.accountId = accountId;
		newContact.dirty = true;
		var primary = this.linkedContacts[0];
		newContact.firstName = primary.firstName;
		newContact.lastName = primary.lastName;
		newContact.middleName = primary.middleName;
		newContact.newContact = "newContact";
		newContact.accountDomain = syncSource;
		this.linkedContacts.push(newContact);
		return newContact;
	},
	
	//Find a contact that can handle this item.  If no contact exists (they are read only, don't accept that type, are full)
	//create a new contact that will link to it and add it to that.  Use the edit rules to make sure the primary type accepts this
	//and if not, fall back to a local contact
	findAvailableContact: function(item){
		var available = null;
		this.linkedContacts.each(function(contact){
			if (contact.readOnly || contact.accountDomain == "simphonebook") {
				return;
			}
			available = contact;
			throw $break;
		});
		if (!available) {
			available = this.createContactWithAccount(AppAssistant.defaultAccountId);
		}
		return available;
	},
	
	
	findAvailableContacts: function(item){
		var contacts = [];
		this.linkedContacts.each(function(contact){
			if(!contact.readOnly){
				contacts.push(contact);
			}
		});
		if (contacts.length === 0) {
			var c = this.createContactWithAccount(AppAssistant.defaultAccountId);
			contacts.push(c);
		}
		return contacts;
	},
	
	findEditRule: function(source){
		var rule = EditRules.find(function(i){
			return (i.serviceName.include(source.accountDomain || source.domain));
		});
		if (!rule) {
			rule = EditRules[0];//Use the defaults
		}
		rule.phoneLabels = EditRules.staticPhoneLabels;
	},
	
	handleListEditClick: function(e, listId){
		e.item.working = true;
		var choices = this.linkedContacts.findAll(function(c){
			return (!c.disabled && c.accountDomain != "simphonebook");
		}); //Thiss was removed by HI.  If we want the ability to add new contacts linked, uncomment this.concat([{label: 'Or Add A New Linked Contact'}]).concat(this.accounts);
		//Check if you clicked on the transport type picker
		if (e.originalEvent.target.hasClassName('dev-sync-source-picker') || e.originalEvent.target.up('.dev-sync-source-picker')) {
			if (e.item.id) {
				return; //Don't allow this on contact points that have been saved
			}
			this.controller.popupSubmenu({
				items: choices,
				placeNear: e.originalEvent.target,
				toggleCmd: e.item.accountId + "," + e.item.accountDomain,
				onChoose: this.chooseAccountForItem.bind(this, e.item, e.model, listId)
			});
		}
		var target = null;
		if (e.originalEvent.target.hasClassName('dev-label-selector')) {
			target = e.originalEvent.target;
		} else {
			target = e.originalEvent.target.up('.dev-label-selector');
		}
		if (target) {
			if(e.item.readOnly){
				return;
			}
			var toggleCmd = (e.item.isImAddress)? e.item.serviceName:e.item.label;
			this.controller.popupSubmenu({
				items:e.model.choices,
				placeNear: e.originalEvent.target,
				toggleCmd: toggleCmd,
				onChoose:this.chooseNewLabelForItem.bind(this, e.item, e.model.choices, target.select('.label')[0])
			});
		}
	},
	
	chooseNewLabelForItem:function(item, choices, target, newLabel){
		if (!newLabel) {
			return;
		}
		item.setDirty();
		if (item.isImAddress) {
			item.serviceName = newLabel;
			item.displayLabel = IMName.labels[newLabel];
		}
		else {
			item.label = newLabel;
		}
		this.findContactPointLabel(item, choices);
		target.innerHTML = item.displayLabel;
	},
	findContactPointLabel: function(model, choices){
		var label = model.label;
		if (!label) {
			return; //urls don't have labels
		}
		if(model.isImAddress) {
			label = model.serviceName;
		}
		model.displayLabel = choices.find(function(item){
			return item.value == label;
		}).label;
	},
	
	chooseAccountForItem: function(item, model, listId, account){
		if (!account) {
			return;
		}
		item.working = false;
		var acctDetails = account.split(",");
		var contact = null;
		if (acctDetails[0] == 'c') {
			contact = this.linkedContacts.find(function(lc){
				return lc.id == acctDetails[1];
			});
		}
		else {
			var accountId = acctDetails[1];
			var syncSource = acctDetails[2];
			contact = this.createContactWithAccount(accountId, syncSource);
		}
		this.addItemToContact(contact, item);
		item.accountDomain = acctDetails[2];
		item.iconPath = contact.iconPath;
		this.controller.modelChanged(model);
		this.controller.get(listId).mojo.focusItem(item);
	},
	
	popupContactChooser: function(e){
		var callback = null;
		var choices = [];
		
		if (this.isNewScene) {
			this.accounts.each(function(acct){
				if (acct.accountDataIsReadOnly == "0" && acct.domain != "simphonebook") {
					choices.push(acct);
				}
			});
			callback = this.changeNewContactAccount.bind(this);
		}
		else {
			this.linkedContacts.each(function(c){
				c = Object.extend({}, c);
				c.disabled = false;
				choices.push(c);
			});
			callback = this.editSpecificContact.bind(this);
		}
		this.controller.popupSubmenu({
			items: choices,
			placeNear: e.target,
			toggleCmd: e.id,
			onChoose: callback
		});
	},
	
	changeNewContactAccount: function(accountId){
		Mojo.Log.info("Set to accountId: ", accountId);
		if (!accountId) {
			return;
		}
		var acctDetails = accountId.split(",");
		accountId = acctDetails[1];
		this.contact.accountId = accountId;
		var account = this.accounts.find(function(acct){
			return acct.accountId == accountId;
		});
		this.contact.accountDomain = account.iconClass;

		this.nameSyncPicker.setStyle({"background":"url(" + Utilities.iconJSONToIconPath(account.accountSpecificIcons) + ") center center no-repeat"});
	},
	
	editSpecificContact: function(account){
		if (!account) {
			return;
		}
		this.saveContact(this.contact);
		var acctDetails = account.split(",");
		var contact = this.linkedContacts.find(function(lc){
			return lc.id == acctDetails[1];
		});
		this.renderSpecificContact(contact);
	},
	
	handleListBlur: function(e, list, listModel){
		var item = list.mojo.getItemByNode(e.target);
		if (!item) {
			return; // This occurs when you blur by focusing into another item
		}
		if (item.isAddress) {
			item.parseAddress(e.target.value);
			if (item.working) {
				//don't automatically remove this yet, we'll do that on the callback if necessary
				return;
			}
		}
		var value = e.target.value.strip();
		if(item.isPhoneNumber){
			value = PhoneNumber.strip(e.target.value);
		}
		
		if ((e.type === "blur" || e.type === 'DOMFocusOut') && value.length <= 0) {
			if(item.isPhoneNumber && PhoneNumber.strip(e.target.value).length === 0){
				
			}
			// remove an item from the list if it has no content
			var index = listModel.items.indexOf(item);
			list.mojo.noticeRemovedItems(index, 1);
			listModel.items = Utilities.removeFromArray(listModel.items, item);
			list.mojo.showAddItem(true);
			if (item.removeFunction) {
				item.removeFunction();
			}
		}
	},
	
	handleListBlurAfterAdd: function(e, newModel) {
		if (e.target.value && !newModel.hasBeenDeleted) {
			var contact = this.findAvailableContact(newModel);
			newModel.isNewContactPoint = "new-contact-point";
			newModel.setDirty = function(c, andSave){
				c.dirty = true;
				if (andSave) {
					this.handleSave();
				}
			}.bind(this, contact);
			
			//if these happened before save, handle them now
			if (newModel.isDirty) {
				newModel.setDirty();
			}
			this.addItemToContact(contact, newModel);
			
			newModel.accountDomain = contact.accountDomain;
			newModel.iconPath = contact.iconPath;
		}
	},
	
	//Handles the typing and blurring in the text fields.
	//Should hide/show the add item label when there is/isn't text, and if you blur it when it's empty, it should remove the item
	handleListInputEvents: function(e, list, listModel){
		
		var item = list.mojo.getItemByNode(e.target);
		if (!item) {
			return; // This occurs when you blur by focusing into another item
		}
		if (item.isAddress) {
			var property = e.target.up("[x-mojo-element='TextField']").getAttribute('x-contacts-property-name');
			item[property] = e.target.value;
			item.value = item[property];
		}
		else {
			item.value = e.target.value; //Quick hack to fix adding/editing of items until they fix it in list
		}
		list.listTarget = list.listTarget || e.target.up("[x-mojo-element='List']");
		if (list.listTarget) {
			// select list and show add div
			list.listTarget.mojo.showAddItem(item.value.length > 0);
		}
	},
	
	handleNameFieldChange: function(e){
		e.stop();
		this.contact[e.target.name] = e.target.value;
		this.contact.dirty = true;
		
		this.contact.freeformName = this.contact.getFullName();
		this.controller.modelChanged(this.contact);
	},
	
	textFieldChanged: function(event){
		this.contact.dirty = true;
		this.contact[event.property] = event.value || null;
	},
	
	nameChanged: function(event){
	
		event.model.dirty = true;
		event.model.parseName(event.model.freeformName);
		this.controller.modelChanged(event.model);
	},
	
	handleViewFullName: function(){
		this.controller.get("drawer-opener").toggleClassName("open");
		// this.stopEditing();
		var div = this.controller.get("name-fields-drawer");
		var isOpen = !div.mojo.getOpenState();
		div.mojo.setOpenState(isOpen);
		return;
	},
	
	reminderChanged: function(e){
		this.person.dirty = true;
		this.person.reminder = e.value;
		if(!this.person.reminder || this.person.reminder.blank()) {
			this.person.reminder = null;
		}
	},
	
	birthdayChanged: function(e) {
		this.saveMoreDetails("birthday", e.value);
	},
	
	spouseChanged: function(e) {
		this.saveMoreDetails("spouse", e.value);
	},
	
	childrenChanged: function(e) {
		this.saveMoreDetails("children", e.value);
	},
	
	nicknameChanged: function(e) {
		this.saveMoreDetails("nickname", e.value);
	},
	
	saveMoreDetails: function(property, value) {
		var contacts = this.findAvailableContacts();
		contacts.each(function(c){
			c[property] = value;
			c.dirty = true;				
		});
	},
	
	notesChanged: function(e){
		e.model.dirty = true;
		if (e.model.newNote) {
			//we need to set this new note to whoever will take it
			var contact = this.findAvailableContact();
			contact.notes = e.model.notes;
			contact.dirty = true;
		}
	},
	
	getIconPathForDefaultAccount: function() {
		var defaultAccountID = AppAssistant.defaultAccountId;
			
		 var defaultAccount = AppAssistant.accountsList.find(function(account){
			if (account.accountId == defaultAccountID) {
				return account;
			}
		});
		
		return Utilities.iconJSONToIconPath(defaultAccount.accountSpecificIcons);
	},
	
	getIconPathForContactChooser: function() {
		var accountToUse = this.linkedContacts.find(function(contact){
			if (!contact.readOnly) {
				return contact;
			}
		});	
		
		if (!accountToUse) {
			return this.getIconPathForDefaultAccount();
		}
		else {
			return accountToUse.iconPath;
		}
		
	},
	
	makeNewPhone: function(){
		var ret = new PhoneNumber();
		ret.label = 3;
		ContactPointDecorator.phoneFormatter(ret);
		ret.iconPath = this.getIconPathForContactChooser();
		return ret;
	},
	
	makeNewIm: function(){
		var ret = new IMName();
		ret.serviceName = "gmail";
		ContactPointDecorator.messagingFormatter(ret);
		ret.iconPath = this.getIconPathForContactChooser();
		return ret;
	},
	
	makeNewEmail: function(){
		var ret = new Email();
		ret.label = 0;
		ContactPointDecorator.emailFormatter(ret);
		ret.iconPath = this.getIconPathForContactChooser();
		return ret;
	},
	
	makeNewURL: function(){
		var ret = new URLModel("");
		ContactPointDecorator.urlFormatter(ret);
		ret.iconPath = this.getIconPathForContactChooser();
		return ret;
	},
	
	makeNewAddress: function(){
		var newAddress = new Address();
		newAddress.label = 1;
		newAddress.iconPath = this.getIconPathForContactChooser();
		return newAddress;
	},
	
	swipeDelete: function(e, listId, listModel){
		e.item.setDirty();
		e.item.toDelete = true;
		if (e.item.removeFunction) {
			e.item.removeFunction();
		}
		listModel.items = Utilities.removeFromArray(listModel.items, e.item);
		this.controller.get(listId).mojo.showAddItem(true);
	},
	
	notToDelete: function(item){
		return !item.toDelete;
	},
	
	setSpeedDial: function(){
		var cb = function(phone){
			this.phoneModel.items.each(function(ph){
				if (ph != phone && phone.quickDial == ph.quickDial) {
					ph.quickDial = null;
					ph.hasQuickDial = "";
				}
			});
			phone.setDirty(true);
			this.controller.modelChanged(this.phoneModel);
		}.bind(this);
		this.controller.stageController.pushScene("speeddialchoice", {
			numbers: this.phoneModel.items,
			person: this.contact,
			cb: cb,
			popto: 'edit'
		});
		return;
	}
};



EditAssistant.addMethods(EditBehaviors);


