var WdElement = {};

WdElement.Form = new Class
({
	Implements: [ Options, Events ],

	options:
	{
		url: null,
		usingRequest: false
	},

	initialize: function(el, options)
	{
		this.element = $(el);
		this.setOptions(options);

		if (this.options.usingRequest || (options && (options.onRequest || options.onComplete || options.onFailure || options.onSuccess)))
		{
			this.element.addEvent
			(
				'submit', function(ev)
				{
					ev.stop();

					this.submit();
				}
				.bind(this)
			);
		}
	},

	log: function(messages, type)
	{
		var target = this.element.getElement('ul.' + type) || new Element('ul.' + type);

		if (target.hasClass('missing'))
		{
			target.addClass('alert-message');
			target.addClass('error');
		}

		if (typeOf(messages) == 'string')
		{
			messages = [ messages ];
		}
		else if (typeOf(messages) == 'object')
		{
			var original = messages;

			messages = [];

			Object.each
			(
				original, function(message, id)
				{
					if (typeOf(id) == 'string')
					{
						var el = this.element.elements[id];

						if (typeOf(el) == 'collection')
						{
							var parent = el[0].getParent('div.radio-group');

							if (parent)
							{
								parent.addClass('missing');
							}
							else
							{
								for (var i = 0, j = el.length ; i < j ; i++)
								{
									el[i].addClass('missing');
								}
							}
						}
						else
						{
							el.addClass('missing');
						}
					}

					if (!message)
					{
						return;
					}

					messages.push(message);
				},

				this
			);
		}

		if (!messages.length)
		{
			return;
		}

		messages.each
		(
			function(message)
			{
				target.adopt(new Element('li', { html: message }));
			}
		);

		if (!target.parentNode)
		{
			target.inject(this.element, 'top');
		}
	},

	resetFeedback: function()
	{
		var log = this.element.getElement('ul.missing');

		if (log)
		{
			log.destroy();
		}

		var log = this.element.getElement('ul.success');

		if (log)
		{
			log.destroy();
		}

		this.element.getElements('.missing').removeClass('missing');
	},

	submit: function()
	{
		this.fireEvent('submit', {});
		this.getOperation().send(this.element.toQueryString());
	},

	getOperation: function()
	{
		if (this.operation)
		{
			return this.operation;
		}

		return this.operation = new Request.JSON
		({
			url: this.options.url || this.element.action,

			onRequest: this.request.bind(this),
			onComplete: this.complete.bind(this),
			onSuccess: this.success.bind(this),
			onFailure: this.failure.bind(this)
		});
	},

	request: function()
	{
		this.resetFeedback();
		this.fireEvent('request', arguments);
	},

	complete: function()
	{
		this.fireEvent('complete', arguments);
	},

	success: function(response)
	{
		this.log(response.log.done, 'success');
		this.fireEvent('success', arguments);
	},

	failure: function(xhr)
	{
		var response = JSON.decode(xhr.responseText);

		this.log(response ? (response.exception || response.log.form || response.log.error) : xhr.responseText, 'missing');
		this.fireEvent('failure', arguments);
	}
});


/*
 * This file is part of the BrickRouge package.
 *
 * (c) Olivier Laviale <olivier.laviale@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

var BrickRouge = {

	Utils: {

		Busy: new Class({

			startBusy: function()
			{
				if (++this.busyNest == 1)
				{
					return;
				}

				this.element.addClass('busy');
			},

			finishBusy: function()
			{
				if (--this.busyNest)
				{
					return;
				}

				this.element.removeClass('busy');
			}
		})
	},

	Widget: {

	},

	Form: new Class({

		Implements: [ Options, Events ],

		options:
		{
			url: null,
			useXHR: false
		},

		initialize: function(el, options)
		{
			this.element = $(el);
			this.setOptions(options);

			if (this.options.useXHR || (options && (options.onRequest || options.onComplete || options.onFailure || options.onSuccess)))
			{
				this.element.addEvent
				(
					'submit', function(ev)
					{
						ev.stop();

						this.submit();
					}
					.bind(this)
				);
			}
		},

		alert: function(messages, type)
		{
			var alert = this.element.getElement('div.alert-message.' + type) || new Element('div.alert-message.' + type, { html: '<a href="#close" class="close">×</a>'});

			if (typeOf(messages) == 'string')
			{
				messages = [ messages ];
			}
			else if (typeOf(messages) == 'object')
			{
				var original = messages;

				messages = [];

				Object.each
				(
					original, function(message, id)
					{
						if (typeOf(id) == 'string' && id != '_base')
						{
							var el = this.element.elements[id], field;

							if (typeOf(el) == 'collection')
							{
								var parent = el[0].getParent('div.radio-group');
								field = parent.getParent('.field');

								if (parent)
								{
									parent.addClass('error');
								}
								else
								{
									for (var i = 0, j = el.length ; i < j ; i++)
									{
										el[i].addClass('error');
									}
								}
							}
							else
							{
								el.addClass('error');
								field = el.getParent('.field');
							}

							if (field)
							{
								field.addClass('error');
							}
						}

						if (!message || message === true)
						{
							return;
						}

						messages.push(message);
					},

					this
				);
			}

			if (!messages.length)
			{
				return;
			}

			messages.each
			(
				function(message)
				{
					alert.adopt(new Element('p', { html: message }));
				}
			);

			if (!alert.parentNode)
			{
				alert.inject(this.element, 'top');
			}
		},

		clearAlert: function()
		{
			var alerts = this.element.getElements('div.alert-message');

			if (alerts)
			{
				alerts.destroy();
			}

			this.element.getElements('.error').removeClass('error');
		},

		submit: function()
		{
			this.fireEvent('submit', {});
			this.getOperation().send(this.element);
		},

		getOperation: function()
		{
			if (this.operation)
			{
				return this.operation;
			}

			return this.operation = new Request.JSON
			({
				url: this.options.url || this.element.action,

				onRequest: this.request.bind(this),
				onComplete: this.complete.bind(this),
				onSuccess: this.success.bind(this),
				onFailure: this.failure.bind(this)
			});
		},

		request: function()
		{
			this.clearAlert();
			this.fireEvent('request', arguments);
		},

		complete: function()
		{
			this.fireEvent('complete', arguments);
		},

		success: function(response)
		{
			if (response.success)
			{
				this.alert(response.success, 'success');
			}

			this.onSuccess(response);
		},

		onSuccess: function(response)
		{
			this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
		},

		failure: function(xhr)
		{
			var response = JSON.decode(xhr.responseText);

			if (response && response.errors)
			{
				this.alert(response.errors, 'error');
			}

			this.fireEvent('failure', arguments);
		}
	})
};

/**
 * Destroy the alert message when its close icon is clicked. The "error" class is also removed from
 * elements.
 */
$(document.body).addEvent('click:relay(div.alert-message a.close)', function(ev, target){

	ev.stop();

	var form = target.getParent('form');

	if (form) {

		form.getElements('.error').removeClass('error');
	}

	target.getParent('div.alert-message').destroy();
});
