/*
---
DESCRIPTION: For GrossmütterRevolution Registration Forms.

LICENSE: Closed license

AUTHORS:
- Rajeev J. Sebastian
- Nathan Querido

COPYRIGHT:
- QUERIDODESIGN, Switzerland - http://www.queridodesign.net/

DEPENDENCIES:
- MooTools-Core 1.2.4

- MooTools-More 1.2.4
...
*/

//  STYLED CHECKBOX + RADIO CLASS :: insanekane
var StyledCheckbox = new Class({
	Implements: [Events, Options],
	options: {
		animate: false, // Whether the widget should be animated :: insanekane
		animationOptions: {duration:300, link: 'chain'}, // "link: chain" is important for the animation :: insanekane
		animationStateNormal: {'background-color': '#FFF'},
		animationStatePressed: { 'background-color': '#FFF' },
		group: null, //$$('elements'), // Group of elements to process; used with radio-button groups :: insanekane
		onAction: $empty, // Event fired when this value changes :: insanekane
		saveUnchecked: false //Whether to save the unchecked state when POSTing the form.
	},

	initialize: function(element, options) {
		this.setOptions(options);
		this.element = element;
		this.element.store('__widget__', this);
		this.build();
		if(this.options.animate) this.buildAnimation();
	},

	// FADE EFFECT, LABELS :: nfq
	buildAnimation: function() {
		var anim = new Fx.Morph(this.element, this.options.animationOptions );
		anim.set(this.options.animationStateNormal);
		this.element.store('EF.widget.animation', anim);
	},

	startAnimation: function() {
		var anim = this.element.retrieve('EF.widget.animation');
		anim.start(this.options.animationStatePressed);
		anim.start(this.options.animationStateNormal);
	},

	// CUSTOM CHECKS + RADIOS :: nfq, JanK
	build: function() {
		var e = this.element;
		var ec = e.getElement('input');

		this.check(e);
		ec.style.display = 'none';
		var isCheckbox = ec.get('type') == 'checkbox';
		var isFileCheck = e.hasClass('');
		if (this.options.saveUnchecked && isCheckbox && !isFileCheck) {
			// This hidden input is absolutely necessary for Ether.Flex to work
			// Apparently, EF requires a value "0" when the checkbox is unchecked, which by default will not be sent
			// by the browser. So, we have this here hack, which mirrors the checked status of checkbox, *and* sends "0"
			// when the checkbox is unchecked :: insanekane
			// NOTE: For Independent city chooser, we DO NOT send the value if its unchecked; so we manipulate the checkbox directly.
			var hidden = new Element('input', {
					type: 'text',
					'class': 'custominput_valueholder',
					value: ec.get('checked')?1:0,
					name: ec.get('name')
				}).inject(ec, 'after');
				ec.set('name', '');
		}
		this.value = isCheckbox ? ec.get('checked') : ec.get('value');
		this.checked = ec.get('checked');
		var clicker = function (event){
			event.stop();
			if(this.options.animate && event.target == ec) this.startAnimation();
			// IE(7) doesnt transfer the event to the input when clicking on the label, so we have to set it manually
			if(event.target != ec ) {
				
				if (isCheckbox) {
					ec.checked = !ec.checked; 
					this.check(e);
					if (this.options.saveUnchecked && !isFileCheck) { hidden.set('value', ec.get('checked')?1:0); }
				} else {
					if(!ec.checked) ec.checked = true
					$$(this.options.group).each(function(j){
						if(j.getElement('input').type == 'radio') {
							this.check(j); //reset visuals for all items in the radio group
						}
					}.bind(this));
				}
				if(!isFileCheck && event.target == ec) {
					// Two events are generated, apparently one by the label (e) and one by the checkbox (ec)
					// this causes issues with the tags widgets send method being called twice, the first with wrong data
					// so, we have an extra guard on the target :: insanekane
					this.value = isCheckbox ? ec.get('checked') : ec.get('value');
					this.checked = ec.get('checked');
					this.fireEvent('action', ec.get('value'));
				}
			}
		}.bind(this)
		e.addEvent('click',clicker);
		if(isCheckbox) {
			$$('label[for="'+ec.id+'"]').addEvent('click', clicker);
		}
	},

	check: function(el){
		el = $(el) || $(this.element);
		var input = el.getElement('input');
		var type = input.get('type');
		if(input.id == 'male_1') console.log('toggling', el, input, input.checked);
		if (input.checked) {
			el.addClass(type + '_on');
			el.removeClass(type + '_off');
		} else {
			el.addClass(type + '_off');
			el.removeClass(type + '_on');
		}
		this.fireEvent('action', [input.checked]);
	},

	setChecked: function(val) {
		var el = $(el) || $(this.element);
		var input = el.getElement('input');
		input.checked = val;
		this.check();
	},

	isChecked: function() {
		var el = $(el) || $(this.element);
		var input = el.getElement('input');
		return input.checked;
	}

});

StyledCheckbox.extend({
	assign: function(selector, options) {
		return $$(selector).map(function(el) {
			return new StyledCheckbox(el, options);
		});
	}
});

var Form = new Class({

	Implements: [Events, Options],

	options: {
		classNormal: 'normal',
		classFocus: 'focus',
		classError: 'error',
		sendJSON: false, //shall we send the form data via Request.JSON or regular submit ?
		signalSubmit: false //don't send or submit; fireEvent('submit') instead
	},

	
	Regex: {
		email: /\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i,
		telephone: /^(\+|\d|\(|\)|\s)+$/i
	},

	initialize: function(el, options){
		this.setOptions(options);
		console.log(el, $(el));
		this.elements = $H({});
		this.voptions = $H({});
		this.constraints = $H({});

		this.el = $(el).addEvent('submit', this.submit.bindWithEvent(this));

		this.els = this.el.getElements('input[type!=submit][type!=reset], textarea').filter(function(el){
			var title = el.get('title');

			el.addEvents({
				focus: this.focus.bind(this, el),
				blur: this.blur.bind(this, el)
			});

			if(!title) return false;

			this.elements.set(el.id, el);
			this.voptions.set(el.id, title.split(',').map(String.trim).map(String.toLowerCase));

			el.erase('title');

			return true;
		}, this);
	},

	setInvalid: function(el){
		el.morph(el.get('tag')+'.'+this.options.classError);
	},
	validate: function(){
		this.error = false;
		this.elements.each(function(el){
			this.check(el);
		}, this);
		
		if(this.error){
			return false;	
		}
		return true;
	},
	submit: function(e){
		console.log('form submitted');
		this.error = false;
		this.elements.each(function(el){
			this.check(el);
		}, this);
		
		if(this.error){
			e.stop();
			return false;	
		}

		var obj = {};

		this.el.getElements('input[type!=submit][type!=reset], textarea').each(function(el){
			obj[el.name] = el.get('value');
		});
		
		if(this.options.signalSubmit) {
			this.fireEvent.delay(0, this, ['submit', [this.el]]);
			e.stop();
			return false;
		}
		if(this.options.sendJSON) {
			new Request.JSON({
				url: this.el.get('action'),
				onComplete: (function(j){
					if(!j || !j.msg) return;
	
					this.el.getElements('input[type=submit], input[type=reset], li.required').set('tween', {duration: 200}).fade(0);
					//this.el.set('tween', {duration: 200}).fade(0);
	
					// $('message_sent').getElement('div.contact_msg_'+j.msg).setStyle('display', 'block');
	
					$('message_sent').setStyles({
						opacity: 0,
						display: 'block'
					}).set('tween', {duration: 800}).fade(1);
				}).bind(this)
			}).post(obj);
			return false;
		}
		
		return true;
	},

	focus: function(el){
		el.morph(el.get('tag')+'.'+this.options.classFocus);
	},

	blur: function(el){
		el.morph(el.get('tag')+'.'+this.options.classNormal);
		if(this.voptions.has(el.id) && this.voptions.get(el.id).contains('autocheck')) this.check(el);
	},

	check: function(el){
		var error = false,
			value = el.get('value');
		if(this.voptions.has(el.id)) {
			var inputText = el.retrieve('inputText', false);
			if(inputText) {
				console.log('before getting inptext value in form.check');
				value = inputText.value();
				error = !inputText.isValid();
				console.log('after getting inptext value in form.check', inputText.value());
			}
			if(this.voptions.get(el.id).contains('required') && (!value || value.test(/^\s+$/))){
				error = true;
			}
			$H(this.Regex).each(function(v,i){
				if(!this.voptions.get(el.id).contains(i)) return;
				if(!value.test(v)) error = true;
			}.bind(this));
		}
		if(this.constraints.has(el.id)) {
			var type = this.constraints.get(el.id).type;
			var data = this.constraints.get(el.id).data;
			if(!error) error = Form.Validators[type](el, data);
		}
		// if(!error) el.set('value', value.trim());
		if(error){
			this.error = error;
			el.morph(el.get('tag')+'.'+this.options.classError);
		} else {
			el.morph(el.get('tag')+'.'+this.options.classNormal);
		}
	},
	
	addConstraint: function(type, el, data) {
		if(!this.elements.has(el.id)) this.elements.set(el.id, el);
		this.constraints.set(el.id, {'type': type, 'data': data});
	},

	reset: function(){
		this.els.fireEvent('keydown');
		this.error = false;
		this.el.getElements('input[type!=submit][type!=reset], textarea').set('value', '');
	}
});

Form.Validators = {}

Form.Validators.requiredIfNot = function(el, data) {
	var value = el.get('value');
	if(!$(data).get('checked') && (!value || value.test(/^\s+$/))) return true;
	return false;
}

Form.Validators.requiredEqual = function(el, data){
	var value = el.get('value');
	var value2 = data.get('value');
	if(value && value2 == value) return true;
	return false;
}

Form.Validators.requiredEqualPassShark = function(el, el2) {
	var value = el.retrieve('originalElement').value;
	var value2 = el2.retrieve('originalElement').value;
	if(value && value2 == value) return false;
	return true;
}


Form.Validators.equalPassShark = function(el, el2) {
	//value is not required, but should be equal in both fields
	var value = el.retrieve('originalElement').value;
	var value2 = el2.retrieve('originalElement').value;
	if(value2 == value) return false;
	return true;
}


var GMRequest = new Class({
	Extends: Request,
	
	processHTML: function(text){
		var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
		text = (match) ? match[1] : text;

		var container = new Element('div');

		return $try(function(){
			var root = '<root>' + text + '</root>', doc;
			if (Browser.Engine.trident){
				doc = new ActiveXObject('Microsoft.XMLDOM');
				doc.async = false;
				doc.loadXML(root);
			} else {
				doc = new DOMParser().parseFromString(root, 'text/xml');
			}
			root = doc.getElementsByTagName('root')[0];
			if (!root) return null;
			for (var i = 0, k = root.childNodes.length; i < k; i++){
				var child = Element.clone(root.childNodes[i], true, true);
				if (child) container.grab(child);
			}
			return container;
		}) || container.set('html', text);
	}
})
