
// Tip a Friend
UB.TAF = new Class({
	Extends: UB,
	
	el: null,
	formEl: null,
	elements: {
		taf: {},
		captcha: {}
	},
	
	isShown: null,
	isReady: null,
	updateCaptchaRequest: null,
	viewState: null,
	
	options: {
		formType: 'general',
		resetOnShow: true
	},
	
	initialize: function (el, options) {
		// taf el
		this.el = $(el);
		
		// inherit
		this.parent(options);
				
		// IE z-index bug fix
		this.overTextOptions = {wrap: true};
		if (Browser.Engine.trident && Browser.Engine.version < 5) {
			this.el.setStyle('position', 'static');
			this.el.setStyle('overflow', 'hidden');
			this.overTextOptions.wrap = false;
		}
		
		// form
		this._initForm();
		
		// type
		this.formType(this.options.formType);
		
		// states
		this._initViewStates();

		// form send btn
		this.sendBtnEl = this.formEl.getElement('.btn'); 
		this.sendBtnEl.addEvent('click', this.sendForm.bind(this));
		
		// captcha
		this.captchaEl = this.formEl.getElement('.captcha');
		this.updateCaptcha();
		
		// clear prev
		this.resetFormSate(true);
		
		// remove el from dom 
		//this.el.dispose();
		//this.el.show();
		
		// set viewState
		this.viewState = 'form';
	},
	
	_initForm: function () {
		var oThis = this;
		this.formEl = this.el.getElement('form');
		
		// init elements
		var els = this.formEl.getElements('[name]');
		$each (els, function (el) {
			var matches = el.name.match(/(\w+)\[(\w+)\]/);
			if (matches) {
				var k1 = matches[1].toLowerCase().replace(/_/, '-').camelCase();
				var k2 = matches[2].toLowerCase().replace(/_/, '-').camelCase();
				if (! (k1 in this.elements)) {
					this.elements[k1] = []; 
				}
				this.elements[k1][k2] = el;
			} else {
				this.elements[el.name] = el;
			}
		}, this);
		/*
		this.elements.taf.url = this.formEl.getElement('input[name="TAF[URL]"]');
		this.elements.taf.formtype = this.formEl.getElement('input[name="TAF[formtype]"]');
		this.elements.taf.recipient = this.formEl.getElement('input[name="TAF[RECIPIENT]"]');
		this.elements.taf.senderName = this.formEl.getElement('input[name="TAF[SENDER_NAME]"]');
		this.elements.taf.senderEmail = this.formEl.getElement('input[name="TAF[SENDER_EMAIL]"]');
		this.elements.captcha.hash = this.formEl.getElement('input[name="captcha[hash]"]');
		this.elements.captcha.answer = this.formEl.getElement('input[name="captcha[answer]"]');
		*/
		this.elements.captcha.image = this.formEl.getElement('.captcha img');
		this.elements.captcha.image.addEvent('click', this.updateCaptcha.bind(this));
		
		// add checks
		this.elements.taf.recipient.addEvent('change', this.validateRecipient.bind(this));
		this.elements.taf.senderName.addEvent('change', function(e){ oThis.validateSenderName();});
		this.elements.taf.senderEmail.addEvent('change', function(e){ oThis.validateSenderEmail();});
		this.elements.captcha.answer.addEvent('change', function(e){ oThis.validateCaptcha(); });
		
		// inputs overtext initialization
		this.formEl.getElements('input[title], textarea[title]').each(function (inputEl) {
			new OverText(inputEl, this.overTextOptions);
		}, this);
		
		// enter to send the form
		this.formEl.getElements('input').addEvent('keydown', function (event) {
			if (event.key == 'enter') {
				event.stop();
				this.sendForm();
			}
		}.bind(this));
		
	}.protect(),
	
	_initViewStates: function () {
		// success + button
		this.successEl = this.el.getElement('.success');
		this.successEl.getElement('.btn').addEvent('click', function (){
			this.hide();
		}.bind(this));
		
		// fail + button
		this.failEl = this.el.getElement('.fail');
		this.failEl.getElement('.btn').addEvent('click', function (){
			this.showFormState();
		}.bind(this));
	},
	
	/**
	 * Get/set form type 
	 */
	formType: function (formtype) {
		if (formtype) {
			this.options.formType = formtype;
			this.elements.taf.formtype.value = formtype;
		}
		return this.options.formType;
	},
	
	addHidden: function (name, value) {
		return (new Element('input', {
			type: 'hidden',
			name: name,
			value: value
		})).inject(this.formEl);
	},
	
	setTrigger: function (el) {
		this.elements.trigger = $(el);
		this.elements.trigger.addEvent('click', function (e) {
			e.preventDefault();
			if (this.isShown) {
				this.hide() && this.elements.trigger.removeClass('active');
			} else {
				this.show() && this.elements.trigger.addClass('active');
			}
		}.bindWithEvent(this));
	},
	
	toggle: function (dontAnimate) {
		if (this.isShown) {
			return this.hide(dontAnimate);
		} else {
			return this.show(dontAnimate);
		}
	},
	hide: function (dontAnimate) {
		if (! this.isReady || this.el.get('reveal').timer) { 
			return false;
		}
		
		if (dontAnimate) {
			this.el.hide();
		} else {
			this.el.dissolve();
		}
		this.isShown = false;
		
		// toggler
		if (this.elements.trigger) {
			this.elements.trigger.removeClass('active');
		}
		
		// event
		this.fireEvent('hide');
		
		return true;
	},
	show: function (dontAnimate) {
		if (! this.isReady || this.el.get('reveal').timer) {
			return false;
		}
		
		// revert view state
		this.resetFormSate(this.options.resetOnShow);
		
		if (dontAnimate) {
			this.el.show();
		} else {
			this.el.reveal();
		}
		this.isShown = true;
		
		// toggler
		if (this.elements.trigger) {
			this.elements.trigger.addClass('active');
		}
		
		// event
		this.fireEvent('show');
		
		return true;
	},
	
	updateCaptcha: function () {
		this.elements.captcha.image.src = this.elements.captcha.image.src.replace(/r=\w+/, 'r=' + Math.floor(Math.random()*10000000000000));
		this.isReady = true;
	},
	
	updateTextCaptcha: function () {
		this.isReady = false;
		this.captchaIsVisble = this.captchaEl.isVisible();
		//alert(this.captchaEl.isDisplayed());
		
		// share same request 
		if (! this.updateCaptchaRequest) {
			// fx
			this.captchaFx = new Fx.Tween(this.captchaEl, {link: 'chain', property: 'opacity', duration: 'long'});
			this.captchaFx.set(0); // don't animate initial dummy data 
			
			var receiver = function (response) {
				// cancel prev. & hide
				var fn = function(){
					// set values
					this.captchaEl.getElement('.answer').set('value', '');
					this.captchaEl.getElement('.hash').set('value', response.hash);
					this.captchaEl.getElement('.question').set('html', response.question);
					this.captchaEl.getElement('.suffix').set('html', response.suffix);
					// show
					this.captchaFx.start(1);
					this.isReady = true;
				}.bind(this);
				
				// stop old
				this.captchaFx.cancel();
				// animated hide and show
				if (this.captchaIsVisble) {
					this.captchaFx.start(0).chain(fn);
				} 
				// animated show
				else {
					this.captchaFx.set(1);
					fn();
				}
				this.captchaIsVisble = this.captchaEl.isVisible();
			}
			// instance Reqeust
			this.updateCaptchaRequest = this.ajaxRequest('getCaptcha', null, receiver.bind(this), {link: "ignore"}, true);
		}
		
		// send
		this.updateCaptchaRequest.send();
	},
	
	resetFormSate: function (resetFormValues) {
		//reset view state
		this.formEl.setStyles({'display': 'block', 'opacity': 1});
		this.successEl.setStyle('display', 'none');
		this.failEl.setStyle('display', 'none');

		// reset inputs
		if (resetFormValues) {
			this.resetFormValues();
		}
		
		//OverText.update();
		OverText.update.delay(100); // hidden patch
	},
	
	resetFormValues: function () {
		this.formEl.getElements('input[type!=hidden],textarea').set('value', '');
		this.formEl.getElements('.error').setStyle('opacity', 0);
	},
	
	sendForm: function () {
		if (! this.isReady) return;
		
		// on validate send
		var onValidete = function (hasErrors) {
			// errors
			if (hasErrors) {
				return;
			}
			// on server response 
			this.formEl.set('send', {
				method: 'post',
				url: this.ajaxUrl('TAFmail'),
				onSuccess: function (status) {
					this.isReady = true;
					this.updateCaptcha();
					//this.formEl.unspin();
					status = JSON.decode(status);
					this.fireEvent('response', status);
					if (status) {
						this.showSuccessState();
					} else {
						this.showFailState();
					}
				}.bind(this)
			});
			
			// send form
			this.isReady = false;
			//this.formEl.spin();
			this.formEl.send();
			this.formEl.get('tween').start('opacity', 0.6);
		}.bind(this);

		// validate
		this.validateForm(onValidete);
	},
	

	showSuccessState: function () {
		return this.showState('success');
	},
	showFailState: function () {
		return this.showState('fail');
	},
	showState: function (viewState) {
		if (this.viewState === false) return;
		if (viewState == 'form') return this.showFormState();
		
		var oThis = this;
		var stateEl = this[viewState + 'El'];
		this.viewState = false;
		this.isReady = false;
			
		// fade out form
		this.formEl.get('tween').start('opacity', 0).chain(
			// resize taf
			function () {
				var tafTween = new Fx.Tween(oThis.el);
				var newHeight = stateEl.getDimensions().height;
				tafTween.set('height', '');
				tafTween.start('height', newHeight).chain(
					// show success & restore height
					function () {
						oThis.formEl.setStyle('display', 'none');
						stateEl.setStyles({
							//marginTop: (-1 * oThis.formEl.getDimensions().height),
							opacity: 0,
							display: 'block'
						});
						oThis.el.setStyle('height', 'auto');
						// show el
						stateEl.get('tween').start('opacity', 1);
						oThis.viewState = viewState;
						oThis.isReady = true;
						// event
						oThis.fireEvent('state', viewState);
					}
				)
			}
		);
		return true;
	},
	showFormState: function () {
		// checks
		if (this.viewState === false) return false;
		if (this.viewState === null) return this.show();
		if (this.viewState === 'form') return null;
		
		// from fail/success
		if (!(this.viewState == 'success' || this.viewState == 'fail')) return;
		var oThis = this;
		var stateEl = this[this.viewState + 'El'];
		
		this.viewState = false;
		this.isReady = false;
		
		stateEl.get('tween').start('opacity', 0).chain(function(){
			var tafTween = new Fx.Tween(oThis.el);
			var newHeight = oThis.formEl.getDimensions().height;
			tafTween.set('height', '');
			tafTween.start('height', newHeight).chain(
				function () {
					stateEl.setStyle('display', 'none');
					oThis.formEl.setStyles({
						opacity: 0,
						display: 'block'
					});
					oThis.formEl.get('tween').start('opacity', 1);
					oThis.el.setStyle('height', 'auto');
					oThis.viewState = 'form';
					oThis.isReady = true;
				}
			)
		});
		return true;
	},
	
	validateForm: function (onComplete) {
		var hasErrors = false;
		// inputs validation
		hasErrors = this.validateRecipient() || hasErrors;
		hasErrors = this.validateSenderName() || hasErrors;
		hasErrors = this.validateSenderEmail() || hasErrors;
		
		// captcha validation
		var receiver = function (answerIsValid) {
			hasErrors = !answerIsValid || hasErrors;
			if (onComplete) {
				onComplete(hasErrors);
			}
			this.hasErrors = hasErrors;
		}.bind(this);
		this.validateCaptcha(receiver);
	},
	
	validateCaptcha: function (onComplete) {
		var receiver = function (answerIsValid) {
			if (! answerIsValid) {
				this.showFieldError(this.elements.captcha.answer);
			} else {
				this.hideFieldError(this.elements.captcha.answer);
			}
			if (onComplete) {
				onComplete(answerIsValid);
			}
			this.hasErrors = answerIsValid || this.hasErrors;
		}.bind(this);
		var qs = this.captchaEl.toQueryString();
		var request = this.ajaxRequest('checkCaptcha', qs, receiver);
		//request.send();
	},
	
	validateRecipient: function () {
		// recipient
		var fieldRecipient = this.formEl.getElement('input[name="TAF[RECIPIENT]"]');
		var value = fieldRecipient.get('value').trim();
		var hasErrors = null;
		// required
		if (! value) {
			hasErrors = true;
		} 
		// mail validation
		else {
			var emails = value.split(/\s*[;,]\s*/);
			var emailRe = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,5}$/i;
			for (var i=0; i<emails.length; i++) {
				var email = emails[i].trim();
				if (email == "") {
					continue;
				}
				if (! emailRe.test(email)) {
					hasErrors = true;
					break;
				}
			}
		}
		if (hasErrors) {
			this.showFieldError(fieldRecipient);
		} else {
			this.hideFieldError(fieldRecipient);
		}
		return hasErrors;
	},
	validateSenderName: function () {
		var field = this.formEl.getElement('input[name="TAF[SENDER_NAME]"]');
		var value = field.get('value');
		if (! value.test(/^[\w\d _.'&_-]+$/)) {
			this.showFieldError(field);
			return true;
		} else {
			this.hideFieldError(field);
			return false;
		}
	},
	validateSenderEmail: function () {
		var field = this.formEl.getElement('input[name="TAF[SENDER_EMAIL]"]');
		var value = field.get('value');
		if (! value.test(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,5}$/i)) {
			this.showFieldError(field);
			return true;
		} else {
			this.hideFieldError(field);
			return false;
		}
	},
	
	showFieldError: function (field) {
		var errorLabelEl = field.getParent().getElement('.error');
		errorLabelEl.fade('in');
	},
	hideFieldError: function (field) {
		var errorLabelEl = field.getParent().getElement('.error');
		if (! errorLabelEl) return;
		errorLabelEl.fade('out');
	},
	
	unbind: function ()
	{
		// initially hidden
		this.hide(true);
		
		// reset prev values
		this.resetFormSate(this.options.resetOnShow);
		
		// remove trigger
		this.el.trigger = null;
		
		this.el.dispose();
	}
	
});
// Static
UB.TAF.extend({
	/*
	// Singleton instance
	instance: null,
	GetInstance: function () {
		if (this.instace) {
			return this.instance;
		}
		
		this.instance = new UB.TAF();
		return this.instance;
	}
	*/
});

