/*
 * FormHelper - implementation of standard form helpers (similar to common_tags_helper.rb)
 */

function FormFieldElement(cell, content) {
	this.cell = cell;
	this.content = content;
}

FormFieldElement.prototype = {
	markError: function() {
		this.cell.addClass('FieldWithErrors');
		this.cell.find("input, select, textarea").addClass('ErrorField');
	},
	clearError: function() {
		this.cell.removeClass('FieldWithErrors');
		this.cell.find("input, select, textarea").removeClass('ErrorField');
	}
};

FormCommonHelper = {
	formField: function(label, content, field_name, field_class, attrs) {
		var row = $j("<tr class='"+field_class+" FormField'>");
		this.appendField(row);
		if( label || label=="" ) {
			var label_cell = $j("<td class='Label'>").appendTo(row);
			this.labelTag(label, field_name).appendTo(label_cell);
		}
		var cell = $j("<td class='"+field_class+" Field'>").appendTo(row);
		if( attrs!==undefined ) {
			cell.attr(attrs);
		}
		if( content && content.append!==undefined ) { // JQuery element
			cell.append(content);
		} else if( typeof content === 'String' ) {
			cell.html(content);
		} else if( $j.isFunction(content) ) {
			content.call(cell);
		}
		return new FormFieldElement(cell, content);
	},

	section: function(title) {
		var row = $j("<tr class='Section'>");
		this.appendField(row);
		return $j("<td class='Section' colspan='2'>").html(title).appendTo(row);
	},

	description: function(description) {
		var row = $j("<tr class='Description'>");
		this.appendField(row);
		row.append("<td></td>");
		return $j("<td class='Description'>").html(description).appendTo(row);
	},

	textField: function(label, name, value, attrs) {
		var input = this.textTag(name, value, this.extractFieldTagAttrs(attrs));
		return this.formField(label, input, name, 'Text', attrs);
	},

	selectField: function(label, name, options, value, attrs) {
		var select = this.selectTag(name, options, value, this.extractFieldTagAttrs(attrs));
		return this.formField(label, select, name, 'Select', attrs);
	},

	checkBoxField: function(label, name, checked, attrs) {
		var field_tags = $j("<input type='hidden' value='0'>").attr('name', name);
		$j.merge(field_tags, this.checkBoxTag(name, checked, "1", this.extractFieldTagAttrs(attrs)));
		$j.merge(field_tags, this.labelTag(label, name));
		return this.formField("", field_tags, name, 'CheckBox', attrs);
	},

	customField: function(label, content, attrs) {
		return this.formField(label, content, null, 'Custom', attrs);
	},

	/** Tag helpers **/
	labelTag: function(label, field_name) {
		var label_tag = $j("<label>").html(label);
		if( field_name ) {
			label_tag.attr('for', field_name);
		}
		return label_tag;
	},

	textTag: function(name, value, attrs) {
		var id = (attrs && attrs.id) || name;
		var tag_classes = this.extractFieldTagClass(attrs, 'Select');
		var input = $j("<input type='text' class='"+tag_classes+"'>").attr({id: id, name: name});
		if( value!==undefined ) {
			input.val(value);
		}
		return input;
	},

	selectTag: function(name, options, value, attrs) {
		var id = (attrs && attrs.id) || name;
		var tag_classes = this.extractFieldTagClass(attrs, 'Select');
		var select = $j("<select class='"+tag_classes+"'>").attr({id: id, name: name});
		for(var i=0; i<options.length; i++) {
			var option = $j("<option>").attr('value', options[i][1]).html(options[i][0]).appendTo(select);
			if( value==options[i][1] ) {
				option.attr('selected', 'selected');
			}
		}
		return select;
	},

	checkBoxTag: function(name, checked, value, attrs) {
		var id = (attrs && attrs.id) || name;
		if( value == undefined ) {
			value = "1";
		}
		var tag_classes = this.extractFieldTagClass(attrs, 'CheckBox');
		var check_box = $j("<input type='checkbox' class='"+tag_classes+"'>").attr({id: id, name: name}).val(value);
		if( checked ) {
			check_box.attr('checked', true);
		}
		return check_box;
	},

	extractFieldTagAttrs: function(attrs) {
		var field_attrs = {};
		if( attrs ) {
			field_attrs.id = attrs.id;
			delete attrs.id;
			field_attrs.className = attrs.filedClass;
			delete attrs.filedClass;
		}
		return field_attrs;
	},

	extractFieldTagClass: function(attrs, class_name) {
		var field_classes = (attrs ? attrs.className : undefined);
		return field_classes ? field_classes + " " + class_name : class_name;
	},

	appendField: function(field_element) {
		this.getFormFieldsContainer().append(field_element);
	}
};

/** Form fields containers **/

// FormFieldsContainer is a factory for other containers
FormFieldsContainer = {
	create: function(params) {
		if($j.isObject(params.table)) {
			return new FormTableContainer(params.table);
		} else if($j.isObject(params.before)) {
			return new FormBeforeFieldContainer(params.before);
		} else {
			return null;
		}
	}
};

// FormTableContainer appends fields to the table end
function FormTableContainer(form_table) {
	this.form_table = form_table;
}

FormTableContainer.prototype = {
	append: function(field_element) {
		this.form_table.append(field_element);
	}
}

// FormBeforeFieldContainer appends fields before given field
function FormBeforeFieldContainer(before_field) {
	this.before_field = before_field;
}

FormBeforeFieldContainer.prototype = {
	append: function(field_element) {
		this.before_field.before(field_element);
	}
}

/** FormHelper - main helper class **/
function FormHelper(form, container_params) {
	this.form = form;
	if( container_params!==undefined ) {
		this.fields_container = FormFieldsContainer.create(container_params);
	} else {
		this.fields_container = this.createTableContainer();
	}
}

jQuery.extend(FormHelper.prototype, FormCommonHelper);
jQuery.extend(FormHelper.prototype, {
	createTableContainer: function() {
		var form_table = new FormTableHelper(this.form).draw();
		return FormFieldsContainer.create({table: form_table});
	},

	getFormFieldsContainer: function() {
		return this.fields_container;
	}
});


function FormTableHelper(container) {
	this.container = container;
}
jQuery.extend(FormTableHelper.prototype, FormCommonHelper);
jQuery.extend(FormTableHelper.prototype, {
	draw: function() {
		this.table = $j("<table class='Form'>").appendTo(this.container);
		this.fields_container = FormFieldsContainer.create({table: this.table});
		return this.table;
	},

	getFormFieldsContainer: function() {
		return this.fields_container;
	}
});

/** Other helpers **/

var ErrorPopup = function(popup, link) {
	$j("#"+popup).hide();
	$j("#"+link).mouseover(function() {
		$j(".ErrorMessage").stop(true, true);
		$j(".ErrorMessage").hide();
		$j("#"+popup).delay(100).show(200);
	});
	$j("#"+link).mouseout(function() {
		$j(".ErrorMessage").stop(true, true);
		$j(".ErrorMessage").hide();
	});
};

/** Extensions Support **/

function ExtensionsSupport() {
	this.extensions = $j([]);
	if( this.constructor._extensions!==undefined ) {
		for(var i=0; i<this.constructor._extensions.length; i++) {
			this.extensions.push( new this.constructor._extensions[i](this) );
		}
	}
	this.triggerExtensions = ExtensionsSupport.prototype.triggerExtensions;
}

ExtensionsSupport.prototype = {
	triggerExtensions: function(event, data) {
		this.extensions.trigger(event, data);
	}
};

ExtensionsSupport.addTo = function(constructor) {
	constructor.addExtension = ExtensionsSupport.addExtension;
};

ExtensionsSupport.addExtension = function(extension) {
	this.prototype.constructor = this; // ensure we have private constructor
	if( this._extensions===undefined ) {
		this._extensions = [];
	}
	this._extensions.push(extension);
};


