fabrikForm = new Class( {
	
	initialize: function( ) {
		this.elements = $H({});
		this.delGroupJS = $H({});
		this.duplicateGroupJS = $H({});
		this.duplicatedGroups = {};
		this.periodicals ={};
		this.clickDeleteGroup = this.deleteGroup.bindAsEventListener(this);
		this.clickDuplicateGroup = this.duplicateGroup.bindAsEventListener(this);
		//put here as in IE in admin watchgroups doesnt work on domready event
		window.addEvent('load', function(){
			this.watchGroupButtons();
		}.bind(this));
	},
		
	addElement: function( oEl ){
		if(oEl.element){
			elId = oEl.element.id.replace('[]', '').replace('_0', '');
			this.elements.set(elId, oEl);
		}
	},

	dispatchEvent: function( elementType, elementId, action, js){
		var el = this.elements.get(elementId);
		
		if(el){
			action = action.replace('on', '');
			el.addNewEvent( action, js );
			//clear periodical
			var bin = $clear(this.periodicals[elementId]);
			//store that the periodical if used is done
			this.periodicals[elementId] = true; 
		}else{
			//lets try setting up a periodical to continue to try to attach the event
			// attempt to fix issue where this.elemenets doesnt conatin elementId in safari and ie
		
			if(!this.periodicals[elementId]){
				this.periodicals[elementId] = this.dispatchEvent.periodical(2500, this, [elementType, elementId, action, js]);
			}
		}
	},

	action: function( task, element ){
		var oEl = this.elements.find( function( oEl ){
			return (oEl.element.id == element);
		})
		eval('oEl.' + task + '()');
	},

	watchGroupButtons: function(){
		this.unwatchGroupButtons();
		$$('.deleteGroup').each(function(item, index){
			item.addEvent('click', this.clickDeleteGroup);
		}, this);
		$$('.addGroup').each(function(item, index){
			item.addEvent('click', this.clickDuplicateGroup);
		}, this);
	},

	unwatchGroupButtons: function(){
		$$('.deleteGroup').each(function(g){
		  g.removeEvent('click', this.clickDeleteGroup);
		}, this);
		$$('.addGroup').each(function(g){
		  g.removeEvent('click', this.clickDuplicateGroup);
		}, this);
	},

	addGroupJS: function(groupId, e, js){
		if(e == 'delete'){
			this.delGroupJS.set(groupId, js);
		}else{
			this.duplicateGroupJS.set(groupId, js);
		}
	},

	deleteGroup: function(e){
		var event = new Event(e);
		var b = event.target;
		var i = b.id.replace('delGroup_', '');
		var subgroups = $$('#group' + i + ' .fb_sub_group');
		var endSubGroup = subgroups.pop();
		var js = this.delGroupJS.get(i);
		var myFx = new Fx.Style(endSubGroup, 'opacity', {duration:300,
			onComplete : function(){
				if(subgroups.length != 0){
					endSubGroup.remove();
				}
				eval(js);
			}});
		myFx.start(1, 0);
		event.stop();
		$('fabrik_repeat_group_' + i + '_counter').value = subgroups.length;
		return false;
	},

	/* duplicates the groups sub group and places it at the end of the group */ 

	duplicateGroup: function(e){
		var event = new Event(e);
		var b = event.target;
		var i = b.id.replace('addGroup_', '');
		var js = this.duplicateGroupJS.get(i);
		var group = $('group'+i);
		var subgroups = $$('#group' + i + ' .fb_sub_group');
		var c = subgroups.length;
		$('fabrik_repeat_group_' + i + '_counter').value = c + 1;
		if(group.style.display == 'none'){
			group.style.display = 'block';	
		}else{
			var subgroup = $('subgroup'+i+'_0');
			var clone = null;
			var found = false;
			for (var j in ofabrik.duplicatedGroups)
			{
			 if(j == i){
				found = true;
				}
			}
			if(!found){
				this.duplicatedGroups[i] = clone;
				clone = subgroup.cloneNode(true);
			}else{
				if(!subgroup){
					clone = this.duplicatedGroups[i];
				}else{
					clone = subgroup.cloneNode(true);
				}
			}

			group.appendChild(clone);
			clone.id = 'subgroup'+i+'_' + c;
			var children = $(clone.id).getElements('[rel^=fabrik]') 

			//remove values and increment ids
			children.each(function(cNode){
				if(cNode.nodeType == 1 && cNode.id != ''){
					var oldId = cNode.id;
					if(cNode.id.indexOf('[]') != -1){
						cNode.id = cNode.id.replace('[]', '') + c + '[]';
					}else{
						cNode.id = cNode.id + c;
					}
					if(cNode.name){
						r = eval('/\[' + '0' + ']/');
						cNode.name = cNode.name.replace(r, '1');
					}
					cNode.value = '';
				}
			});
			c = c + 1;
			var myFx = new Fx.Style(clone, 'opacity', {duration: 500}).set(0);
			myFx.start(1);
		}
		eval(js);
		this.watchGroupButtons();
		event.stop();
		return false;
	}
});
	
ofabrik = new fabrikForm();

// JS Calendar
var fabrikCalendar = null; // remember the calendar object so that we reuse
// it and avoid creating another

// This function gets called when an end-user clicks on some date
function fabrikSelected(cal, date) {
	cal.sel.value = date; // just update the value of the input field
}

// And this gets called when the end-user clicks on the _selected_ date,
// or clicks the "Close" (X) button.  It just hides the calendar without
// destroying it.
function fabrikCloseHandler(cal) {
	cal.hide();			// hide the calendar

	// don't check mousedown on document anymore (used to be able to hide the
	// calendar when someone clicks outside it, see the showCalendar function).
	Calendar.removeEvent(document, "mousedown", fabrikCheckCalendar);
	// $$$ hugh - refocus in the target field, otherwise custom JS events
	// won't fire (like onchange and onblur)
	cal.sel.focus();
}

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown.  If the click was outside the open
// calendar this function closes it.
function fabrikCheckCalendar(ev) {
	var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
	for (; el != null; el = el.parentNode)
	// FIXME: allow end-user to click some link without closing the
	// calendar.  Good to see real-time stylesheet change :)
	if (el == fabrikCalendar.element || el.tagName == "A") break;
	if (el == null) {
		// calls closeHandler which should hide the calendar.
		fabrikCalendar.callCloseHandler();
		Calendar.stopEvent(ev);
	}
}

// This function shows the calendar under the element having the given id.
// It takes care of catching "mousedown" signals on document and hiding the
// calendar if the click was outside.
function fabrikShowCalendar(id,format) {
	var button_id = id + '_button';
	
	var options = Object.extend({
			showsTime:       false
	}, arguments[2] || {});
		
	var el = document.getElementById(id);
	if (fabrikCalendar != null) {
		// we already have one created, so just update it.
		fabrikCalendar.hide();		// hide the existing calendar
		fabrikCalendar.setDateFormat(format);
		fabrikCalendar.parseDate(el.value); // set it to a new date
	} else {
		// first-time call, create the calendar
		/*
		var cal = Calendar.setup({
			button: button_id,
			inputField: id,
			showsTime: true,
			onClick: fabrikSelected,
			onClose: fabrikCloseHandler,
			daFormat: format,
			ifFormat: format,
			range: [1900,2070]
		});
		*/
		var cal = new Calendar(true, null, fabrikSelected, fabrikCloseHandler);
		//var cal = Calendar(0,el.value, fabrikSelected, fabrikCloseHandler);
		fabrikCalendar = cal;		// remember the calendar in the global
		fabrikCalendar.setRange(1900, 2070);	// min/max year allowed
		fabrikCalendar.showsTime = options.showsTime;
		fabrikCalendar.setDateFormat(format);
		fabrikCalendar.create();		// create a popup calendar
		fabrikCalendar.parseDate(el.value); // set it to a new date
	}
	fabrikCalendar.sel = el;		// inform it about the input field in use
	fabrikCalendar.showAtElement(el);	// show the calendar next to the input field

	// catch mousedown on the document
	Calendar.addEvent(document, "mousedown", fabrikCheckCalendar);
	return false;
}
