/**
 * This library allows us to manage field sets with much less code
 * It assumes some naming conventions such as:
 *		The "template" field set uses the convention <set prefix>_<member name>   (notice the "_" delimiter and it has NO suffix)
 *		New "Field Set" fields will use the convention <set prefix>_<member name>_<index>    (this object will manage the "index" value for you)
 *
 * 
 * This library is dependent on 2 other libraries:
 *		lib_domHelper.js
 *		json.js		
 */
function fieldSetManager(config) {

	// Public Functions
	this.getRecords = getRecords;
	this.serializeAndSave = serializeAndSave;
	this.getSerializedValue = getSerializedValue;
	this.newFieldSet = newFieldSet;

	
	// Normal Data Members / Config Values	ALL ARE REQUIRED except numFieldSetsToStart
	var containerID = '';		// The ID of the container the bounds a group of field sets
	var setClassName = '';		// The className that identifies the top-level element of a field set within the group of field sets
	var templateID = '';		// The ID of the fieldSet that is the TEMPlATE field set. The set we COPY each time we add a new field set to the group
	var insertBeforeID = '';	// The ID of the element that new rows should be inserted BEFORE  (only ONE of either insertBefore or insertAfter should be specified)
	var insertAfterID = '';		// The ID of the element that new rows should be inserted AFTER  (only ONE of either insertBefore or insertAfter should be specified)
	var saveToFieldID = '';		// The ID of the field the serialized version of the fields should be saved to (it's also where the initial data set should be stored)
	var numFieldSetsToStart = 1; // The number of field sets that should initially be created if no pre-existing field sets exist

	// Callback Functions / Config Values
	// Any callback functions need to accept a parameter (arg) which is a reference to THIS object
	// i.e.   beforeInit: function(arg) { alert(arg.containerID); }
	// this.beforeNewFieldSet(this)
	var callbacks = [];
	callbacks['beforeInit'] = function(arg) { };
	callbacks['afterInit'] = function(arg) { };
	callbacks['beforeNewFieldSet'] = function(arg) { };
	callbacks['afterNewFieldSet'] = function(arg) { };
	callbacks['beforeSerialize'] = function(arg) { };
	callbacks['afterSerialize'] = function(arg) { };
	callbacks['beforeDeserialize'] = function(arg) { };
	callbacks['afterDeserialize'] = function(arg) { };
	callbacks['beforeGetRecords'] = function(arg) { };
	callbacks['afterGetRecords'] = function(arg) { };
	

	// PRIVATE DATA MEMBERS
	var records = [];
	var serializedString = '';
	var dh = new domHelper();
	
	
	init(config);
	
	// ------------------------------------------------------------------------------------


	/**
	 * Initialize this object using the configuration passed in
	 * @param config	A structure of values
	 */
	 function init(config) {
		containerID = config['containerID'];
		setClassName = config['setClassName'];
		templateID = config['templateID'];
		saveToFieldID = config['saveToFieldID'];

		if(config['insertBeforeID']) insertBeforeID = config['insertBeforeID'];
		if(config['insertAfterID']) insertAfterID = config['insertAfterID'];
		if(config['numFieldSetsToStart']) numFieldSetsToStart = parseInt(config['numFieldSetsToStart']);

		if(config['beforeInit']) callbacks['beforeInit'] = config['beforeInit'];
		if(config['afterInit']) callbacks['afterInit'] = config['afterInit'];
		if(config['beforeNewFieldSet']) callbacks['beforeNewFieldSet'] = config['beforeNewFieldSet'];
		if(config['afterNewFieldSet']) callbacks['afterNewFieldSet'] = config['afterNewFieldSet'];
		if(config['beforeSerialize']) callbacks['beforeSerialize'] = config['beforeSerialize'];
		if(config['afterSerialize']) callbacks['afterSerialize'] = config['afterSerialize'];
		if(config['beforeDeserialize']) callbacks['beforeDeserialize'] = config['beforeDeserialize'];
		if(config['afterDeserialize']) callbacks['afterDeserialize'] = config['afterDeserialize'];
		if(config['beforeGetRecords']) callbacks['beforeGetRecords'] = config['beforeGetRecords'];
		if(config['afterGetRecords']) callbacks['afterGetRecords'] = config['afterGetRecords'];
		
		doCallback('beforeInit');	 	
		initFieldSets();
		doCallback('afterInit');
	 }
	 
	 
	 function initFieldSets() {
		var initRecords = deserialize();
		var	numRecords = initRecords.length;

		if(numRecords == 0) {
			if(numFieldSetsToStart > 0) {
				for(var i=0; i<numFieldSetsToStart; i++) {
					newFieldSet(i+1, null, false);
				}			
			}
		}		
		for(var i=0; i<numRecords; i++) {
			newFieldSet(i+1, initRecords[i], false);
		}	 
	 }


	/**
	 * Returns an array of structures containing data for each field set in the group
	 * This is the data that gets serialized and saved.
	 */
	function getRecords() {
		doCallback('beforeGetRecords');
		records = dh.getFieldSetStructs(containerID, setClassName);			
		doCallback('afterGetRecords');
		return records;		
	}


	/**
	 * Get the current set of field values, serialize them into a JSON string, and save that value to the saveToFieldID form field
	 */
	function serialize() {
		doCallback('beforeSerialize');
		serializedString = JSON.stringify(getRecords());				
		doCallback('afterSerialize');
		return serializedString;
	}
	
	
	/**
	 *	Deserialize the value in the saveToFieldID and convert it into a records array
	 */	 
	function deserialize() {
		doCallback('beforeDeserialize');

		var jsonText = document.getElementById(saveToFieldID).value;
		if(jsonText != '') {
			records = eval(jsonText);		
		}

		doCallback('afterDeserialize');
		
		return records;
	}	
	
	
	/**
	 * Get the current set of field values, serialize them into a JSON string, and save that value to the saveToFieldID form field
	 */
	function serializeAndSave() {
		document.getElementById(saveToFieldID).value = getSerializedValue();
	}
	
	
	/**
	 * Get the JSON string for the serialized field set
	 */
	function getSerializedValue() {
		return serialize();
	}
	
	
	/**
	 * Add a new field set
	 */
	function newFieldSet() {
		doCallback('beforeNewFieldSet');
		
		var newIndex = 1;
		if(arguments.length > 0) {
			newIndex = parseInt(arguments[0]);
		} else {
			newIndex = getRecords().length+1;		
		}

		var dataSet = null;
		if(arguments.length >= 2) {
			dataSet = arguments[1];
		}
		
		var setFocus = true;
		if(arguments.length >= 2) {
			setFocus = arguments[2];
		}
		
		var insertPoint = insertBeforeID;
		var insertMethod = 'before';		
		if(insertAfterID != '') {
			insertPoint = insertAfterID;
			insertMethod = 'after';
		}
		dh.duplicateFieldSet2(templateID, '', newIndex, insertPoint, insertMethod, dataSet, setFocus);

		serializeAndSave();

		doCallback('afterNewFieldSet');
	}
	
	
	function doCallback(id) {	
		callbacks[id](records);
	}


}
