/*
 * Copyright (c) 2009 The Olympos Development Team.
 * 
 * http://sourceforge.net/projects/olympos/
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html. If redistributing this code, this
 * entire header must remain intact.
 */
Ext.namespace("cwe.editor.control");

cwe.editor.control.TagField = function() {

};

cwe.editor.control.TagField = Ext.extend(Ext.ux.form.SuperBoxSelect, {
	initComponent : function() {
		var self = this;

		this.tagsToCreate = [];
		this.tagsToRemove = [];
		this.origValue = [];

		this.modelDescription = chi.model.ModelDescriptionContainer.getInstance().getDescription("Tag");

		Ext.apply(this, {
		    allowBlank : true,
		    width : 805,
		    emptyText : chi.Dict.translate("Enter your tags"),
		    store : new Ext.data.SimpleStore( {
		        fields : [ "key", "val" ],
		        proxy : new chi.editor.control.ComboBoxProxy( {
		            fullOid : true,
		            prependWildcard : true,
		            modelDescription : self.modelDescription
		        })
		    }),
		    allowAddNewData : true,
		    mode : "remote",
		    displayField : "val",
		    valueField : "key"
		});

		cwe.editor.control.TagField.superclass.initComponent.apply(this, arguments);

		this.on("newitem", function(tagField, value) {
			var localRecord = self.createRecord( {
			    key : Ext.id(),
			    val : value
			});

			self.store.add(localRecord);
			self.tagsToCreate.push(localRecord);
			self.addRecord(localRecord);

			self.dirty = true;
		});
		this.on("removeitem", function(tagField, value, record) {
			self.tagsToRemove.push(record);
		});
	}
});

/**
 * Sets the value of this form field.
 * 
 * @param {chi.model.ModelReferenceList}
 *            value The new value of this form field.
 */
cwe.editor.control.TagField.prototype.setValue = function(value) {
	var self = this;
	this.dirty = true;

	if (value) {
		this.origValue = value;

		for ( var i = 0; i < value.length; i++) {
			var currRecord = value[i];

			if (currRecord.isModelRecord) {
				var localRecord = self.createRecord( {
				    key : currRecord.getOid(),
				    val : currRecord.getLabel()
				});

				self.store.add(localRecord);
				this.addRecord(localRecord);
			}
		}
	} else {
		this.origValue = [];
		this.removeAllItems().resetStore();
	}
};

/**
 * Returns the value of this form field.
 * 
 * @return The value of this form field.
 * @type chi.model.ModelReferenceList
 */
cwe.editor.control.TagField.prototype.getValue = function() {
	var self = this;

	return {
		commit : function(parentRecord, actionSet) {
			return self.commit(parentRecord, actionSet);
		}
	};
};

cwe.editor.control.TagField.prototype.commit = function(parentRecord, actionSet) {
	var self = this;

	var tagsToCreate = this.tagsToCreate;
	var origValue = this.origValue;
	var currValue = [];
	this.items.each(function(item) {
		currValue.push(item.value);
	});

	var dirty = false;

	// Extract created ids
	var tagsToCreateIds = [];
	for ( var i = 0; i < tagsToCreate.length; i++) {
		var newTag = tagsToCreate[i];
		tagsToCreateIds.push(newTag.get("key"));
	}

	var toCreate = chi.Util.intersect(tagsToCreateIds, currValue);

	// Create and associate newly created tags
	for ( var i = 0; i < tagsToCreate.length; i++) {
		var newTag = tagsToCreate[i];

		if (toCreate.indexOf(newTag.get("key")) != -1) {

			actionSet.addCreate(this.modelDescription.getId());
			var replacementId = "{" + this.modelDescription.getId() + ":?}";
			actionSet.addUpdate(replacementId, {
				title : newTag.get("val")
			});
			actionSet.addAssociate(parentRecord.getOid(), replacementId, this.dataIndex);

			dirty = true;
		}
	}

	// Associate added existings tags
	var toAssociateTmp = chi.Util.except(currValue, origValue);
	var toAssociate = chi.Util.except(toAssociateTmp, tagsToCreateIds);

	for ( var i = 0; i < toAssociate.length; i++) {
		var oid = chi.Util.getOidOrValue(toAssociate[i]);

		actionSet.addAssociate(parentRecord.getOid(), oid, this.dataIndex);

		dirty = true;
	}

	// Disassociate removed tags
	var toDisassociateTmp = chi.Util.except(origValue, currValue);
	var toDisassociate = chi.Util.except(toDisassociateTmp, tagsToCreateIds);

	for ( var i = 0; i < toDisassociate.length; i++) {
		var oid = chi.Util.getOidOrValue(toDisassociate[i]);

		actionSet.addDisassociate(parentRecord.getOid(), oid, this.dataIndex);

		dirty = true;
	}

	this.tagsToCreate = [];
	this.tagsToRemove = [];
	this.origValue = currValue;

	return dirty;
};
