/* -*- mode: c; tab-width: 2; c-tab-always-indent: t; c-basic-offset: 2; comment-column: 0 -*- */
if (typeof Yuku != 'object'){
	new Error('Required objects missing');
}

yut.Form = {
	tabify_fieldsets: function($form){
		var prefix = '<div class="ka-local-nav"><ul class="ka-nav">';
		var sufix = '</ul></div>';

		var first = true;
		var getId = yut.Dom.getId;
		lis = $form.find('.ka-legend').map(function(){
				var li = ['<li'];
				if (first){
					li.push(' class="ka-first ka-active"');
					first = false;
				}
				else {
					$j(this).parent().addClass('ka-hidden-fieldset');
				}
				li.push('>','<a href="#',getId(this.parentNode),'">',this.innerHTML, '</a></li>');
				return  li.join('');
			});

		var join = Array.prototype.join;
		var $tabs = $j(prefix+join.call(lis, '')+sufix).prependTo($form);
		/* switching active links on navigation menus */
		$tabs.find('ul.ka-nav > li > *').click(function(e){
			var $this = $j(this);
			$this.parents('ul.ka-nav:first').children().removeClass('ka-active');
			$this.parent().addClass('ka-active');
		});
		return $tabs;
	},

	errors: {
		general_notice: function($form, notice){
			var div, $content = $form.find('.ka-content:first');
			if ($content.length == 0)
				$content = $form.find(":first");
			if (!$content.find('> div.ka-error-notice').length){
				$div = $j(['<div class="ka-error-notice">',
										 '<div class="ka-nw"></div><div class="ka-ne"></div>',
										 '<div class="ka-error-content">'+notice+'</div>',
										 '<div class="ka-sw"></div><div class="ka-se"></div>',
									 '</div>'].join(''));
				$div.prependTo($content);
			}	else {
				$content.find('div.ka-error-content').html('<br>' + notice);
			}
		},

		remove_all: function($form){
			$form.find('.ka-error-notice').remove();
			$form.find('.ka-error').removeClass('ka-error');
		},

		remove: function($form, field){
			field = $form[0][field];
			if (!field){
				return;
			};
			yutf.errors.remove_for_field($j(field));
		},

		remove_for_field: function($field){
			var $parent = $field.parent();
			$parent.find('.ka-error-notice').remove();
			$parent.removeClass('ka-error');
		},

		show: function($form, field, msg){
			field = $form[0][field];
			if (!field){
				Yuku.Util.Form.errors.general_notice($form, msg);
				return;
			}
			yutf.errors.show_for_field($j(field), msg);
		},

		show_for_field: function($field, msg){
			var $parent = $field.parent();
			$parent.addClass('ka-error');
			$j('<span class="ka-error-notice">*</span>').appendTo($parent.find('label:first'));
			$j('<span class="ka-error-notice">'+msg+'</span>').prependTo($parent);
			$field.focus();
		}
	}
};

var yutf = yut.Form;
yutf.clone_field = function($field) {
	var $cloned = $field.clone();
	var uni = yut.String.unique;
	$cloned.find('label').each(function(){
		var _for = this.htmlFor;
		$cloned.find('#'+_for).attr('id', this.htmlFor = uni());
	});
	return $cloned;
};
yutf.update_field_from_clone = function($field, $clone) {
	var changed = false;
	var $c_els = $clone.find('input, select');
	var $f_els = $field.find('input, select');
	var l = $c_els.length;
	if (l != $f_els.length)
		throw "This should not have happened.";
	for (var c, f, i = 0; i < l; i++){
		var c = $c_els[i];
		var f = $f_els[i];
		if (c.name != f.name)
			throw "This should not have happened.";
		if (c.value != f.value){
			changed = true;
			f.value = c.value;
		}
	}
	return changed;
}

yutf.modalize = {};
(function() {
	yutf.modalize.field = function($field, callback, title) {
		var $cloned = yutf.clone_field($field);
		var $wrapper = $j('<div class="ka-section"><h2>'+(title || '')+'</h2><form></form></div>');
		var $w = $j('<div class="ka-content"></div>').appendTo($wrapper.find('form'));
		$w.append($cloned)
			.append('<div class="ka-form-actions"><button type="button" class="ka-submit"><span>save</span></button>'+
							'<a class="ka-cancel ka-close">cancel</a></div>');

		yut.Modal.open();
		yut.Modal.setContent($wrapper);

		$wrapper.find('input[type=text]').bind('keypress', function(e){
			if (e.isKeyPressed('Enter')) {
				submit();
				return false;
			}
			return true;
		});

		function submit() {
			if (callback($wrapper.find('form'), $cloned, $field))
				yut.Modal.close();
			return false;
		}
		$wrapper.find('button.ka-submit').click(submit);
	}

	function update_value($field, $value_field){
		$value_field.find('span.ka-value').text($field.find('input:first').attr('value'));
	}

	function edit($field, $value_field, title){
		yutf.modalize.field($field, function($wrapper, $cloned){
			if (!yutf.validate($wrapper, {email: 'is-email, confirmation-required'}))
				return false;
			if (!yutf.update_field_from_clone($field, $cloned))
				return false;
			$j.post('/settings/changeemail', $wrapper.serialize(), function(obj){

					if (obj && obj.error)
						return yut.Form.errors.general_notice($wrapper, obj.error);

			$wrapper.replaceWith(
'<form style="padding: 10px"> We have sent a verification email to: <p><strong>'+
$cloned.find('input').attr('value')+
'</strong></p> Click the validation link in the email to \
verify your email adress. Once verified, your email will be changed and you will \
need to log in with your new email.\
<div class="ka-form-actions"><button type="button" class="ka-submit ka-close"><span>Close</span></button></div>\
</form>'
);

			}, 'json');

			return false;
		}, title);
	}

	yutf.modalize.email = function(email_el, title){
		$field = $j(email_el).parents('div.ka-field');
		$field.addClass('ka-modalized-email-field');
		$value_field = $j('<p class="ka-field ka-value-field"><label>Email</label><span class="ka-value">'+$j(email_el).attr('value')+'</span></p>').insertAfter($field);
		$j('<a class="ka-edit">edit</a>').click(function(){
			edit($field, $value_field, title || 'Email');
		}).appendTo($value_field);
/* 		update_value($field, $value_field); */
	};
})();


/* to be replaced by the fancy jquery validator that Mauvis recomended/will introduce. */
/* Usage:
	var validate = yut.Form.validate;
	var validatemap = {'avatar': 'not-empty, html-safe, has-image-extention',
										 'terms': 'checked'};

	$j('#ka-my-form').bind('submit', function(){
		return validate($j(this), validatemap);
	});
*/
yutf.validate = function($form, elementsMap){
	yutf.errors.remove_all($form);
	var form = $form[0];
	var errors = yutf.errors;
	var field_val = yutf.validate.field;
	for (var key in elementsMap) {
		if (!form[key]) {
			throw 'Required form element missing -- Yuku.Util.Form.validate.field.';
			return false;
		}
		if (!field_val($j(form[key]), elementsMap[key]))
			return false;
	}
	return true;
};

yutf.validate.field = function($field, props, messages){
	if ($field.parent().hasClass('ka-error')) /* tmp */
		yutf.errors.remove_for_field($field);
	var field = $field[0];
	var validators = yutf.validate.validators;
	props = props.split(/[,\s]+/g);
	for (var key, i = 0, l = props.length; i < l; i++) {
		key = props[i];
		/* FIX ME:
			 the is atleast part is a bit ugly, and it's akward here.
			 Provide a better way to pass conditional information to the validators.
		 */
		var rxv, is_atleast = key.indexOf('is-atleast') != -1 ;
		if (is_atleast) {
			key = key.replace(/is-atleast-([^-]+)-/, 'is-atleast-N-');
			var rxv = RegExp.$1;
		}
		if ((is_atleast && !rxv) || !(key in validators))
			throw "Unknown validator specified -- Yuku.Util.Form.validate.field";
		else if (!validators[key](field, rxv)) {
			/* FIX ME: the adding messages functionality should be moved to the actual validators. */
			var msg = '';
			if (rxv)
				msg = yut.String.replaceFromDict((messages || yutf.errorMessages)[key], {'N':rxv});
			else
				msg = (messages || yutf.errorMessages)[key];

				yutf.errors.show_for_field($field, msg);
			return false;
		}
	}
	return true;
};


yutf.validate.validators = {
	'not-empty': function(field){
		return $j.trim(field.value) != '';
	},
	'checked': function(field){
		return !!field.checked;
	},
	'html-safe': function(field){
		return !/<[^>]+>/.test(field.value);
	},
	'alpha-numeric': function(field){
		return !/[^0-9a-zA-Z ]/.test(field.value);
	},
	'has-image-extention': function(field){
		return /\.(?:gif|(?:jpe?|pn)g)$/i.test(field.value);
	},
	'is-atleast-N-chars': function(field, n){
		return $j.trim(field.value).length >= (+n);
	},
	'is-valid-password': function(field){
		var res;
		$j.ajax({
			url: '/account/validatepassword/',
			type: 'POST',
			data:'passwd='+encodeURIComponent(field.value),
			success: function(result) {
				res = +$j.trim(result);
			},
			async: false
		});
		return res;
	},
	'is-email': function(field){
		var rx = /^[A-Z0-9\.\_\-\+]+@[A-Z0-9]([A-Z0-9.-]{0,61}[A-Z0-9])?\.[A-Z.]{2,6}$/i;
		return rx.test(field.value);
	},
	'confirmation-required': function(field){
		var t = field.form;
		if (t)
			t = t[field.name+'-confirm'];
		else {
			t = document.getElementsByName(field.name+'-confirm');
			t = t[0];
		}
		if (!t)
			return false;

		return t.value == field.value;
	}
};

/* these should probably be under diferent namespace and global or some such. */
yutf.errorMessages = {
	'not-empty': 'Field can not be empty',
	'checked': 'Field must be checked',
	'html-safe': 'HTML is not allowed',
	'alpha-numeric': 'Field value can be only alpha-numeric',
	'has-image-extention': 'Input does not have an image extention',
	'is-email': 'Not a valid email',
	'confirmation-required': 'Confirmation field does not match',
	'is-atleast-N-chars': 'Field must have at least #{N} characters',
	'is-valid-password': 'Please make sure your password is valid'
};
