var AjaxForm = new Class({
	Implements: [Options, Events],
	options: {
		onSuccess: $empty,
		onSubmit: $empty
	},
	initialize: function(formId, options) {
   		this.setOptions(options);

		this.formId = formId;
		this.form = $(formId);
		
		// disable form submit
		/*
		$$(formId+' input[type=submit]').each(function(el) {
			this.disabled = 'disabled';
		});
		*/
		
		this.formFocus();
		this.initSubmit();
	},
	/* init form submit event */
	initSubmit: function() {
		// add submit event
		this.form.addEvent('submit', function(e) {
			// lose current focus (when using enter to send the form)
			this.elements.fireEvent('blur');		

			// prevent page reloading
			new Event(e).stop();
			if(!this.loading) {					
				// init ajax request
				this.fireEvent('submit');
				this.form.set('send', {
					onRequest: function() { // show indicator
						this.toggleLoader();
					}.bind(this),
					onSuccess: function(response) {
						// remove previous errors
						(function(){
							this.cleanErrors();

							var r = JSON.decode(response);

							if(r.status == 'SUCCESS') { // passed
								this.success();
							} else if(r.status == 'ERROR') { // failed
								// remove former errors
								$$('em.error').destroy();
								// add error messages
								for(error in r.errors) {
									this.addError(error, r.errors[error]);
								}
								this.toggleLoader()
							}
							// some delay to avoid blinking
							
						}.bind(this)).delay(1000);

					}.bind(this)
				});
				// submit form
				this.form.send();
			}
		}.bind(this));
	},
	addError: function(id, error) {
		var errorTag = new Element('em',{'class': 'form-error', 'text': error});
		var el = $(id);
		if(el) {
			var parent = el.getParent();

			parent.grab(errorTag);
			parent.addClass('form-error');
		} else {
			console.log('le champ '+id+' n\'existe pas !');
		}
	},
	cleanErrors: function() {
		$$('div.form-error').removeClass('form-error');
		$$('em.form-error').destroy();
	},
	formFocus: function() { // add some styles on focus
		this.elements = $$(
			'#'+this.formId+' input[type=text]',
			'#'+this.formId+' input[type=password]',
			'#'+this.formId+' select',
			'#'+this.formId+' textarea'
		);
		this.elements.each(function(el) {
			el.addEvents({
				'focus': function() {
					this.getParent().addClass('form-focus');
				},
				'blur': function() {
					this.getParent().removeClass('form-focus');
				}
			});

		});
	},
	success: function() { // what do we do next ?
		this.fireEvent('success');
	},
	toggleLoader: function() {
		var submit = this.form.getElements('input[type=submit]');

		// append indicator
		if(!this.loader) {
			this.loader = new Element('span',{
				'class': 'ajax-loader',
				'styles': {
					'display': 'none'
				}
			});
			submit.getParent().grab(this.loader);
		}	
		

		if(this.loading) {
			this.loader.setStyle('display','none');
			submit.setStyle('display','block');
			this.loading = false;
		} else {
			submit.setStyle('display','none');
			this.loader.setStyle('display','block');
			this.loading = true;
		}
	},
	showMessage: function(message) { // replace the submit button by a message
		this.msg = new Element('p', {
			'class':'form-success-message',
			'text': message
		});
		this.toggleLoader();
		this.submit = this.form.getElements('input[type=submit]');
		this.submit.setStyle('display','none');
		this.submit.getParent().grab(this.msg);
	},
	reset: function() { // reinit the form
		(function() {
			this.msg.destroy();
			this.submit.setStyle('opacity', 0);
			this.submit.show();
			this.submit.fade('in');
		}.bind(this)).delay(1500);
	},
	empty: function() { // empty a form
		this.elements.set('value','');
	},
	formId: '',
	form: null,
	loader: null,
	loading: false,
	msg: null,
	submit: null,
	elements: []
});


var AjaxFormMulti = new Class({
	Implements: [Options, Events],
	options: {
		onSuccess: $empty
	},
	initialize: function(container, options) {
   		this.setOptions(options);
		this.container = container;

		this.form = this.container.getElement('form');
		this.fakeForm = this.container.getElement('.fake-form');
		
		this.errors = new Element('ul', {
			'class': 'form-errors',
			'styles': {
				'position': 'relative',
				'overflow': 'hidden'
			}
		}).inject(this.fakeForm, 'before');
		this.errorsFx = new Fx.Tween(this.errors);

		this.formFocus();
		this.initSubmit();
	},
	/* init form submit event */
	initSubmit: function() {
		// add submit event

		this.form.addEvent('submit', function(e) {
			// lose current focus (when using enter to send the form)
			//this.elements.fireEvent('blur');
			this.hideErrors();
			// prevent page reloading
			new Event(e).stop();
			// hide errors

			if(!this.loading) {
				// init ajax request
				this.form.set('send', {
					onRequest: function() { // show indicator
						this.toggleLoader();
					}.bind(this),
					onSuccess: function(response) {

						// remove previous errors
						(function(){
							this.cleanErrors();
							var r = JSON.decode(response);


							if(r.status == 'SUCCESS') { // passed
								//console.log('success')
								this.success();
							} else if(r.status == 'ERROR') { // failed
								// add error messages

								for(error in r.errors) {
									this.addError(error, r.errors[error]);
								}

								this.showErrors();

								this.toggleLoader()

							}
							// some delay to avoid blinking

						}.bind(this)).delay(1000);

					}.bind(this)
				});
				// submit form
				this.form.send();
			}
		}.bind(this));
	},
	addError: function(id, error) {
		new Element('li',{'class': 'form-error', 'text': error}).inject(this.errors);
	},
	cleanErrors: function() {
		this.errors.empty();
	},
	showErrors: function() {
		this.errors.setStyle('height', 'auto');
		var height = this.errors.getSize().y;
		this.errors.setStyle('height', '0');
		var lis = this.errors.getElements('li');
		lis.setStyles({
			'position': 'relative',
			'left': -this.errors.getSize().x+'px'
		});
		var duration = 0;
		lis.each(function(el) {
			var fx = new Fx.Tween(el);
			(function() { fx.start('left', 0) }).delay(duration);
			duration += 200;
		});


		this.errorsFx.start('height', height+'px');
	},
	hideErrors: function() {
		this.errorsFx.start('height', 0);
	},
	formFocus: function() { // add some styles on focus
		this.elements = this.fakeForm.getElements('input[type=text]',
			'#'+this.formId+' input[type=password]',
			'#'+this.formId+' select',
			'#'+this.formId+' textarea'
		);

		this.elements.each(function(el) {
			el.addEvents({
				'focus': function() {
					this.getParent().addClass('form-focus');
				},
				'blur': function() {
					this.getParent().removeClass('form-focus');
				}
			});

		});
	},
	success: function() { // what do we do next ?
		this.fireEvent('success');
	},
	toggleLoader: function() {
		var submit = this.form.getElement('input[type=submit]');

		// append indicator
		if(!this.loader) {
			this.loader = new Element('span',{
				'class': 'ajax-loader',
				'styles': {
					'display': 'none'
				}
			});
			submit.getParent().grab(this.loader);
		}


		if(this.loading) {
			this.loader.setStyle('display','none');
			submit.setStyle('display','block');
			this.loading = false;
		} else {
			submit.setStyle('display','none');
			this.loader.setStyle('display','block');
			this.loading = true;
		}
	},
	showMessage: function(message) { // replace the submit button by a message
		this.msg = new Element('p', {
			'class':'form-success-message',
			'text': message
		});
		this.toggleLoader();
		this.submit = this.form.getElements('input[type=submit]');
		this.submit.setStyle('display','none');
		this.submit.getParent().grab(this.msg);
		(function() {
			this.submit.setStyle('display', 'block');
			this.msg.destroy();
		}.bind(this)).delay(2000);
	},
	reset: function() { // reinit the form
		(function() {
			this.msg.destroy();
			this.submit.setStyle('opacity', 0);
			this.submit.show();
			this.submit.fade('in');
		}.bind(this)).delay(1500);
	},
	empty: function() { // empty a form
		this.elements.set('value','');
	},
	container: null,
	form: null,
	loader: null,
	loading: false,
	msg: null,
	submit: null,
	elements: [],
	errors: null,
	fakeForm: null,
	errorsFx: null
});

