/*
	This javascript class provides features for easily managing form
	fields that can have 0 or more instances, such as 0-5 email
	addresses for a contact. In order to enable the repeatable field
	management features, instantiate a new RepeatableField object and
	pass it: a template from which new instances of the field or
	fields can be cloned, the minimum number of instances allowed,
	the maximum number of instances allowed (or -1 for no maximum),
	and the number of instances present at the time the object is
	instantiated. Here's an example:

	var emailAddressRepeater =
		new RepeatableField( 'emailAddressTemplate', 1, 5, 0 );

	In your template, you can use a button or link with an onclick
	handler that calls 'emailAddressRepeater.remove(this)' to remove
	the	instance. (It must be in your template so that it can find its
	parent element to know what to remove.) In your template or
	outside of it, you can use a button or link with an onclick
	handler that calls 	'emailAddressRepeater.add()' to create a new
	instance of the field.

	The constructor also takes an options hash as the final parameter.
	Valid options include:
		objectSingular: word/phrase used to describe a singular
			instance of the field (eg: 'email address'). This is used in
			error messages when the maximum or minimum is exceeded. The
			default is 'object'.
		objectPlural: word/phrase used to describe a plural
			instance of the field (eg: 'email aesddress'). This is used in
			error messages when the maximum or minimum is exceeded. The
			default is 'objects'.
		cloneIdSuffix: used to help make id attributes in the template
			unique. The default is '_' which should generally be
			sufficient in most cases.

	Here's an example that uses the options hash:

	var emailAddressRepeater =
		new RepeatableField( 'emailAddressTemplate', 1, 5, 0, {
			objectSingular: 'email address',
			objectPlural: 'email addresses',
			cloneIdSuffix: '_foo_' } );
*/
var RepeatableField = Class.create();

RepeatableField.prototype = {
	initialize: function ( template, minRepeats, maxRepeats, currentRepeats, options ) {
		this.template = $(template);
		this.minClones = (!minRepeats) ? 0 : minRepeats;
		this.maxClones = maxRepeats || -1;
		this.cloneCount = currentRepeats;
		this.initializeOptions( options );
		this.disableTemplateFields();
	},
	initializeOptions: function ( options ) {
		this.options = {
			objectSingular: "object",
			objectPlural: "objects",
			cloneIdSuffix: "_",
      afterClone: function(clone) {}
		};
		Object.extend( this.options, options )
	},
	add: function () {
		if ( this.maxClones > 0 && this.cloneCount >= this.maxClones ) {
			alert( this.getMaxClonesMessage() );
			return false;
		}
		var myClone = this.template.cloneNode( true );
    var cloneCount = this.cloneCount;
    var cloneIdSuffix = this.options.cloneIdSuffix;
    var setupElement = function(element) {
			if ( 1 == element.nodeType ) {	// nodeType 1 is Element
				if ( "" != element.id ) {
					element.id = element.id + cloneIdSuffix + cloneCount;
				}
				var tagName = element.tagName.toLowerCase();
				if ( "input" == tagName || "select" == tagName || "textarea" == tagName ) {
					element.name = element.name.replace( /\[XXX\]/, "["+cloneCount+"]" );
          if ( "input" == tagName) {
            element.value = element.value.replace( /\[XXX\]/, cloneCount + 1);
          }
					$(element).enable();
				}
        if(element.onclick) {
          var onclick = $(element).readAttribute('onclick').replace( /XXX/, cloneCount);
          // This is necessary because of the way IE handles cloned events (which is to say, it doesn't handle them at all).
          element.onclick = function() { eval(onclick); };
        }
        
        if(/template-text/.test(element.className)) {
          element.innerHTML = element.innerHTML.replace( /\[XXX\]/, cloneCount + 1);
        }
			} 
		}
    setupElement(myClone);
    var elements = myClone.getElementsByTagName("*");
    for(var ii = 0; ii < elements.length; ii++) setupElement(elements[ii]);
		myClone.style.display = "";
		this.template.parentNode.insertBefore( myClone, this.template );
		this.cloneCount++;
    this.options.afterClone(myClone);

		return true;
	},
	remove: function ( element ) {
		if ( this.cloneCount <= this.minClones ) {
			alert( this.getMinClonesMessage() );
			return false;
		}
		var pattern = new RegExp( "^" + this.template.id + this.options.cloneIdSuffix + '[0-9]+$' );
		while ( element && ! ( element.id && element.id.match( pattern ) ) ) {
			element = element.parentNode;
		}
		if ( ! element ) {
			alert( this.getDeleteErrorMessage() );
			return false;
		}

		element.parentNode.removeChild( element );
		this.cloneCount--;

		return true;
	},
	getMaxClonesMessage: function () {
		return 'Only ' + this.maxClones + ' ' +
			   this.getNumberedObjectNoun( this.maxClones ) + ' can be created.';
	},
	getMinClonesMessage: function () {
		return 'At least ' + this.minClones + ' ' +
			   this.getNumberedObjectNoun( this.minClones ) + ' must remain.'
	},
	getDeleteErrorMessage: function () {
		return "Couldn't figure out owner of this " +
			   this.getNumberedObjectNoun( 1 ) + '. Unable to delete.';
	},
	getNumberedObjectNoun: function ( count ) {
		if ( 1 == count )
			return this.options.objectSingular;
		else
			return this.options.objectPlural;
	},
	disableTemplateFields: function () {
		var tagTypes = [ 'input', 'select', 'textarea' ];
		for ( var j = 0; j < tagTypes.length; j++ ) {
			var childElements = $A( this.template.getElementsByTagName( tagTypes[j] ) );
			for ( var i = 0; i < childElements.length; i++ ) {
				childElements[i].disabled = true;
			}
		}
	}
};
