/**
 * Handles creation of forms from FormField and FormFieldGroup Objects
 */

var FormFields = {};

/**
 * Takes a hash containing an array of form field groups or form field pages and applies the proper classes to each group
 * Use on, for example, JSON Form objects
 *
 * @param array fieldGroups
 * @return array
 */
FormFields.objectifyFormFieldGroups = function(fieldGroups) {
	$H(fieldGroups).each(function(pair) {
		if (pair.value._pages != undefined) {
			fieldGroups[pair.key] = FormFields.objectifyFormFieldPageGroup(pair.value);
		} else if (pair.value._groups != undefined) {
			fieldGroups[pair.key] = FormFields.objectifyFormFieldPage(pair.value);
		} else {
			fieldGroups[pair.key] = FormFields.objectifyFormFieldGroup(pair.value);
		}
	});
	
	return fieldGroups;
}

/**
 * Takes a hash and converts it to a FormFieldGroup object
 * Use on, for example, JSON FormFieldGroups
 *
 * @param array fieldgroup
 * @return FormFieldGroup
 */
FormFields.objectifyFormFieldGroup = function(fieldgroup) {
	var fieldgroup = new FormFieldGroup(fieldgroup);
	$A(fieldgroup.fields).each(function(field, key) {
		fieldgroup.fields[key] = FormFields.objectifyFormField(field);
	});
	return fieldgroup;
}

/**
 * Takes a hash and converts it to a FormFieldPage object
 * Use on, for example, JSON FormFieldGroups
 *
 * @param array fieldpage
 * @return FormFieldPage
 */
FormFields.objectifyFormFieldPage = function(fieldpage) {
	var fieldpage = new FormFieldPage(fieldpage);
	$H(fieldpage.groups).each(function(pair) {
		fieldpage.groups[pair.key] = FormFields.objectifyFormFieldGroup(pair.value);
	});
	return fieldpage;
}

/**
 * Takes a hash and converts it to a FormFieldPage object
 * Use on, for example, JSON FormFieldGroups
 *
 * @param array fieldpagegroup
 * @return FormFieldPageGroup
 */
FormFields.objectifyFormFieldPageGroup = function(fieldpagegroup) {
	var fieldpagegroup = new FormFieldPageGroup(fieldpagegroup);
	$A(fieldpagegroup.pages).each(function(item, index) {
		fieldpagegroup.pages[index] = FormFields.objectifyFormFieldPage(item);
	});
	return fieldpagegroup;
}

/**
 * Takes a hash and converts it to a FormField object
 * Use on, for example, JSON FormFieldGroups
 *
 * @param array field
 * @return FormField
 */
FormFields.objectifyFormField = function(field) {
	field = new FormField(field);
	if (field.getValidationRule()) {
		field.setValidationRule(new ValidationRule(field.getValidationRule()));
	}
	return field;
}

/**
 * Takes an array of fieldgroups and uses them to create form elements inside the supplied container
 *
 * The options parameter may contain the following
 * - showLabels: Determines whether labels will be shown for each form field. Default is true
 * - addBR: Determines whether a line break will be added after each form field. Default is true.
 * - pageListContainer: The container element for the list of form field pages.
 * - pageListItemElement: The element each form field page item should be contained within. Default is 'li'
 * - showGroupHeaders: Determines whether headers will be displayed above field groups. Default is true
 * - showGroupDescriptions: Determines whether descriptions will be displayed above field groups. Default is true
 * - groupContainerElement: The element type used to contain each field group. Default is 'div'
 * - groupContainerClass: The className used for each field group container element. Default is 'cbb solid'
 *
 * @param string|element container
 * @param array fieldgroups
 * @param array options (optional)
 * @return bool
 */
FormFields.createForm = function(container, fieldgroups, options) {
	container = $(container);
	if (!container) {
		return false;
	}
	
	if (options == undefined) {
		options = {};
	}
	if (options.showLabels == undefined) {
		options.showLabels = true;
	}
	if (options.addBR == undefined) {
		options.addBR = true;
	}
	
	if (options.callbacks == undefined) {
		options.callbacks = {};
	}
	
	options.pageList = null;
	options.pageLists = [];
	if (options.pageListContainer != undefined) {
		$(options.pageListContainer).innerHTML = '';
	}
	if (options.pageListDivider != undefined) {
		$(options.pageListDivider).hide();
	}
	if (options.pageListHeaderElement == undefined) {
		options.pageListHeaderElement = 'h2';
	}
	if (options.pageListElement == undefined) {
		options.pageListElement = 'ul';
	}
	if (options.pageListItemElement == undefined) {
		options.pageListItemElement = 'li';
	}
	if (options.pageListClass == undefined) {
		options.pageListClass = '';
	}
	if (options.pageListItemClass == undefined) {
		options.pageListItemClass = '';
	}
	if (options.pageListItemSelectedClass == undefined) {
		options.pageListItemSelectedClass = 'selected';
	}
	
	if (options.showGroupHeaders == undefined) {
		options.showGroupHeaders = true;
	}
	if (options.showGroupDescriptions == undefined) {
		options.showGroupDescriptions = true;
	}
	if (!options.groupContainerElement) {
		options.groupContainerElement = 'div';
	}
	if (options.groupContainerClass == undefined) {
		options.groupContainerClass = 'cbb solid';
	}
	
	// Add Field Groups
	$H(fieldgroups).each(function(pair) {
		pair.value.create(container, options);
	});
	
	if (typeof cbb != 'undefined') {
		cbb.init();
	}
	
	return true;
}

FormFields.persistValues = function(newelements, oldelements) {
	oldelements.each(function(oldelement) {
		// Don't persist values for property type dropdown or submit button
		if (oldelement.id != 'property_type' && oldelement.id != 'add_property_submit') {
			newelements.each(function(newelement) {
				if ((oldelement.id == newelement.id && oldelement.id != '') || (oldelement.name == newelement.name && oldelement.name != '') && oldelement.type == newelement.type) {
					switch (oldelement.type) {
						case 'text':
						case 'textarea':
							newelement.value = oldelement.value;
							break;
						case 'checkbox':
							newelement.checked = oldelement.checked;
							break;
						case 'select-one':
							for (var i = 0; i < newelement.options.length; i++) {
								if (newelement.options[i].value === oldelement.value) {
									newelement.selectedIndex = i;
									break;
								}
							}
							break;
						case 'hidden':
							// Only persist values of hidden date fields and the property id field
							if (
								oldelement.name == 'property[property_id]' || 
								oldelement.name.indexOf('[day]') != -1 || 
								oldelement.name.indexOf('[month]') != -1 || 
								oldelement.name.indexOf('[year]') != -1
								) {
								newelement.value = oldelement.value;
							}
							break;
						case 'image':
						case 'submit':
							break;
						default:
							alert ("Error\nValue transfer not implemented for: " + oldelement.type);
							break;
					}
				}
			});
		}
		oldelement = null;
	});
}

FormFields.validateForm = function(form, options) {
	if (options == undefined) {
		options = {};
	}
	
	form = $(form);
	
	var validated = true;
	$A(form.getElements()).each(function(element) {
		if (element.validate) {
			if (!element.validate()) {
				validated = false;
			}
		}
	});
	
	if (!validated) {
		if (options.onFailure) {
			options.onFailure('Some fields failed to validate correctly.');
		}
	}
	
	return validated;
}

FormFields.formFieldArrayNames = {};
FormFields.formatFieldName = function(name) {
	if (name.indexOf('[]') != -1) {
		if (FormFields.formFieldArrayNames[name] == undefined) {
			FormFields.formFieldArrayNames[name] = 0;
		} else {
			FormFields.formFieldArrayNames[name]++;
		}
		name = name.replace('[]', '[' + FormFields.formFieldArrayNames[name] + ']');
	}
	return name;
}