/**
 * This is the base url of the system
 */
var validationBaseUrl;

/**
 * Add extra validation messages 
 */
Validation.addAllThese([
	['validate-available-email', 'This email address is already in use, please provide another email address.', function(v, elm) {
		if(elm._ajaxValidating && elm._hasAjaxValidateResult) {
			elm._ajaxValidating = false;
			elm._hasAjaxValidateResult = false;
			
			return elm._ajaxValidateResult;
		}
		
		var sendRequest = function() {
			new Ajax.Request(validationBaseUrl + 'bettercheckout/customer/emailCheck',{
				parameters: {'email': elm.value},
				method: 'post',
				onSuccess : function(response) {
					elm._ajaxValidateResult = !response.responseText.evalJSON().exists;
					elm._hasAjaxValidateResult = true;
					Validation.test('validate-available-email',elm);
				}
			});
			elm._ajaxValidating = true;
			return true;
		}
		
		return elm._ajaxValidating || Validation.get('IsEmpty').test(v) || sendRequest();
    }],
    ['validate-existent-email', 'This email address is not in use, please enter a valid email address.', function(v, elm) {
    	if(elm._ajaxValidating && elm._hasAjaxValidateResult) {
			elm._ajaxValidating = false;
			elm._hasAjaxValidateResult = false;
			
			return elm._ajaxValidateResult;
		}
		
		var sendRequest = function() {
			new Ajax.Request(validationBaseUrl + 'bettercheckout/customer/emailCheck',{
				parameters: {'email': elm.value},
				method: 'post',
				onSuccess : function(response) {
					elm._ajaxValidateResult = response.responseText.evalJSON().exists;
					elm._hasAjaxValidateResult = true;
					Validation.test('validate-existent-email',elm);
				}
			});
			elm._ajaxValidating = true;
			return true;
		}
		
		return elm._ajaxValidating || Validation.get('IsEmpty').test(v) || sendRequest();
    }],
    ['validate-phone', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
    	if(Validation.get('IsEmpty').test(v)) return true;
        return /^\+?[0-9]{2,5}?[ 0-9-\(\)]+$/.test(v);
    }],
    ['validate-agreements', 'You must comply with this agreement to place your order.', function(v) {
    	return ((v != "none") && (v != null) && (v.length != 0));
    }]
]);

/**
 * Better Checkout for Magento
 * 
 * This is the javascript source file for the better checkout.
 *
 * @author     Roy Klopper <roy.klopper@concept-creative.com>
 * @copyright  Copyright (c) 2010 Concept Creative (http://www.concept-creative.com)
 */
var BetterCheckout = {};

/**
 * Better Checkout Form class
 * 
 * This is the main object from which the bettercheckout operates. It creates separate objects
 * for the several elements within the checkout. It also offers these sub classes basic functionality
 * for ajax requests and ...
 *
 * @author     Roy Klopper <roy.klopper@concept-creative.com>
 * @copyright  Copyright (c) 2010 Concept Creative (http://www.concept-creative.com)
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 * @version    0.1.0
 */
BetterCheckout.Form = Class.create({

	initialize: function(form, baseUrl)
	{
		this.form = $(form);
		this.baseUrl = baseUrl;		
		validationBaseUrl = baseUrl;

		// Set up the form and its elements
		this.elements = Form.getElements(this.form);
		this.validator = new Validation(this.form,{
		    onSubmit : true,
		    stopOnFirst : true,
		    immediate : true,
		    focusOnError : true
		});

		// Set up elements
		this.customer = new BetterCheckout.Customer(this);
		this.shipping = new BetterCheckout.Shipping(this);
		this.payment = new BetterCheckout.Payment(this);
		this.review = new BetterCheckout.Review(this);
		this.giftmessage = new BetterCheckout.GiftMessage(this);
		this.agreements = new BetterCheckout.Agreements(this);
		this.additional = new BetterCheckout.Additional(this);
	},
	
	parse: function(container, callback)
	{
		callback = callback || function (e, input) {};
		
		Form.getElements(container).each(function(input) {
			
			if(! input.hasClassName('no-save'))
			{
	            if (input.type.toLowerCase() == 'radio' || input.type.toLowerCase() == 'checkbox')
	            {
	                Event.observe(input, 'click', callback.bindAsEventListener(this, input));
	            }
	            else
	            {
	                Event.observe(input, 'blur', callback.bindAsEventListener(this, input));
	            }
			}
        }, this);
	},
	
	sendRequest: function(url, data, callback)
	{
		callback = callback || function() {};

		return new Ajax.Request(url, {
            parameters: data,
            method: 'post',
            onSuccess: callback,
            onError: function()
            {
				window.location.reload(true);
            }
        });
	},
	
	getHeight: function(element)
	{
		var height = element.getDimensions().height;
		return height + parseInt(element.getStyle('paddingTop')) + parseInt(element.getStyle('paddingBottom'));
	}
});

/**
 * This is the customer class, it handles logins, password forgotten function
 * and it automagically saves the users input. All defaults from Magento are
 * implemented for saving, even multiple street lines and the date of birth field.
 * 
 * @author     Roy Klopper <roy.klopper@concept-creative.com>
 * @copyright  Copyright (c) 2010 Concept Creative (http://www.concept-creative.com)
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 * @version    0.1.0
 */
BetterCheckout.Customer = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-credentials');
		this.match = new RegExp(/^[a-z_]+\[[a-z_]+\]\[[0-9]*\]$/);
		this.values = new Hash();
		
		this.main.parse(this.container, this.save.bind(this));
		
		this.container.select('.address-select').each(function(element){
			this.addressSelect(element);
		},this);
		
		Form.getElements(this.container).each(function(element){
			this.values.set(element.id, element.value);
		}, this);

		var login = $('customer-login-btn');
		var password = $('customer-password-btn');
		
		if(login)
		{
			login.observe('click', this.login.bindAsEventListener(this, login));
		}

		if(password)
		{
			password.observe('click', this.password.bindAsEventListener(this, password));
		}
	},
	
	password: function(e, password)
	{
		e.stop();

		var notification = $('customer-customer-notification');
		
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/customer/passwordPost',
			{ email: $('password:username').value },
			function(transport) {
            	var result = transport.responseText.evalJSON();

            	notification.innerHTML = result.message;
            	notification.setStyle({'display': 'block'});
            	
            	if(result.error)
            	{
	            	notification.addClassName('validation-failed');
            	}
            	else
            	{
            		notification.removeClassName('validation-failed');
            	}
        	}
        );
	},
	
	login: function(e, login)
	{
		e.stop();

		var notification = $('customer-customer-notification');

		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/customer/loginPost',
			this.main.form.serialize(true),
			function(transport) {
            	var result = transport.responseText.evalJSON();

            	notification.innerHTML = result.message;
            	notification.setStyle({'display': 'block'});
            	
            	if(! result.error)
            	{
            		notification.removeClassName('validation-failed');
            		
	            	function refresh() {
	            		window.location.reload(true);
	            	}

	            	refresh.delay(0.75);
            	}
            	else
            	{
            		notification.addClassName('validation-failed');
            	}
        	}
        );
	},
	
	addressSelect: function(element)
	{
		if(element.value == '')
		{
			$(element.id + '-form').setStyle({'display': 'block'});
		}
		else
		{
			$(element.id + '-form').setStyle({'display': 'none'});
		}
		
		element.observe('change', function(e){
			if(element.value == '')
			{
				$(element.id + '-form').setStyle({'display': 'block'});
			}
			else
			{
				$(element.id + '-form').setStyle({'display': 'none'});
			}
			
			if(element.id == 'billing-address-select')
			{
				var type = 'billing';
			}
			else
			{
				var type = 'shipping';
			}
			
			this.main.sendRequest(
				this.main.baseUrl + 'bettercheckout/ajax/setAddress',
				this.main.form.serialize(true),
				function()
				{
					this.shipping.update();
					this.payment.update();
					this.review.update();
				}.bind(this.main)
			);
		}.bind(this));
	},
	
	save: function(e, input)
	{
		if(input.hasClassName('no-save') || (input.value == this.values.get(input.id) && input.type.toLowerCase() != 'radio'))
		{
			return;
		}

		this.values.set(input.id, input.value);
		
		if(input.name == 'customer_type')
		{
			this.main.sendRequest(
				this.main.baseUrl + 'bettercheckout/ajax/setCheckoutMethod',
				this.main.form.serialize(true)
	        );
		}
		else
		{
			if(this.request)
			{
				this.request.abort();
			}
			this.request = this.main.sendRequest(
				this.main.baseUrl + 'bettercheckout/ajax/setAddress',
				this.main.form.serialize(true),
				function(transport)
				{
					if(input.hasClassName('update-options'))
					{
						this.shipping.update();
						this.payment.update();
						this.review.update();
					}
					
					this.request = null;
					
				}.bind(this.main)
	        );
		}
	}
	
});

BetterCheckout.Shipping = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-shipping-methods');
		this.methods = this.container.select('.shipping-method');
		this.content = this.container.down('.bettercheckout-content');
		this.request = null;
		
		this.currentMethod = null;

		this.methods.each(this.init.bind(this));
		this.main.parse(this.container, this.save.bind(this));
	},
	
	update: function()
	{
		if(this.request)
		{
			this.request.abort();
		}
		
		this.container.addClassName('loading');
		this.currentMethod = null;
		this.request = new Ajax.Updater(this.content, this.main.baseUrl + 'bettercheckout/ajax/getShippingMethods', {
			evalScripts: true,
			onError: function()
			{
				window.location.reload(true);
			},
			onComplete: function()
			{
				this.methods = this.container.select('.shipping-method');
				this.main.parse(this.container, this.save.bind(this));
				this.methods.each(this.init.bind(this));
				this.container.removeClassName('loading');
				this.request = null;
				
			}.bind(this)
		});
	},
	
	init: function(method)
	{
		if(method.checked)
		{
			method.up('li').addClassName('selected');
			this.currentMethod = method;
		}
	},
	
	save: function(e, input)
	{
		if(this.currentMethod === input || input.hasClassName('no-save'))
		{
			return;
		}
		
		if(this.currentMethod)
		{
			this.currentMethod.up('li').removeClassName('selected');
		}
		
		input.up('li').addClassName('selected');
		this.currentMethod = input;
		
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/ajax/setShippingMethod',
			{ 'method': input.value },
			function()
			{
				this.payment.update();
				this.review.update();
			}.bind(this.main)
        );
	}
	
});

BetterCheckout.Payment = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-payment-methods');
		this.methods = this.container.select('.payment-method');
		this.content = this.container.down('.bettercheckout-content');
		this.request = null;

		this.currentMethod = null;
		
		this.methods.each(this.init.bind(this));
		
		this.main.parse(this.container, this.save.bind(this));
	},
	
	update: function()
	{
		if(this.request)
		{
			this.request.abort();
		}
		
		this.container.addClassName('loading');
		this.currentMethod = null;
		this.request = new Ajax.Updater(this.content, this.main.baseUrl + 'bettercheckout/ajax/getPaymentMethods', {
			evalScripts: true,
			onError: function()
			{
				window.location.reload(true);
			},
			onComplete: function()
			{
				this.request = null;
				this.methods = this.container.select('.payment-method');
				this.main.parse(this.container, this.save.bind(this));
				this.methods.each(this.init.bind(this));
				this.container.removeClassName('loading');
			}.bind(this)
		});
	},
	
	init: function(method)
	{
		var box = $('payment_form_' + method.value);
		
		if(method.checked)
		{
			if(box)
			{
				box.setStyle({'display': 'block'});
			}
			
			this.currentMethod = method;
			method.up('li').addClassName('selected');
		}
		else if(box)
		{
			Form.getElements(box).invoke('disable');
		}
	},
	
	save: function(e, input)
	{
		if(this.currentMethod === input || input.hasClassName('no-save'))
		{
			return;
		}
		
		if(input.hasClassName('payment-method'))
		{
			if(this.currentMethod)
			{
				var oldBox = $('payment_form_' + this.currentMethod.value);
				
				if(oldBox)
				{
					oldBox.setStyle({'display': 'none'});
					
					Form.getElements(oldBox).invoke('disable');
				}
			
				this.currentMethod.up('li').removeClassName('selected');
			}
			
			var box = $('payment_form_' + input.value);
			
			if(box)
			{
				box.setStyle({'display': 'block'});
			
				Form.getElements(box).invoke('enable');
			}
			
			input.up('li').addClassName('selected');
			this.currentMethod = input;
		}
		
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/ajax/setPaymentData',
			this.main.form.serialize(true),
			function()
			{
				this.review.update();
			}.bind(this.main)
        );
	}
	
});

BetterCheckout.Review = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-review');
		this.content = this.container.down('.bettercheckout-content');
		this.inputs = this.container.select('input.qty');
		this.updater = this.container.down('button.btn-update');
		
		this.request = null;

		this.inputs.each(this.init.bind(this));
		this.updater.observe('click', this.updateQty.bindAsEventListener(this));
		
		this.container.select('a[rel=external]').each(function(a){
			a.target = '_blank';
		});
	},
	
	init: function(input)
	{
		var currentValue = input.value;
		
		input.observe('blur', function(e){
		
			if(input.value > 0)
			{
				currentValue = input.value; 
			}
			else
			{
				input.value = currentValue;
			}
		}.bind(this));
	},
	
	updateQty: function(e)
	{
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/ajax/setCartQty',
			this.main.form.serialize(true),
			function(transport)
			{
				var result = transport.responseText.evalJSON();

				if(result.result)
				{
					this.shipping.update();
					this.payment.update();
					this.review.update();
				}
				else
				{
					window.location.reload(true);
				}
			}.bind(this.main)
		);
	},
	
	update: function()
	{
		if(this.request)
		{
			this.request.abort();
		}
		
		this.container.addClassName('loading');
		
		this.request = new Ajax.Updater(this.content, this.main.baseUrl + 'bettercheckout/ajax/getReview', {
			evalScripts: true,
			onError: function()
			{
				window.location.reload(true);
			},
			onComplete: function()
			{
				this.container.removeClassName('loading');
				this.inputs = this.container.select('input.qty');
				this.updater = this.container.down('button.btn-update');
				this.inputs.each(this.init.bind(this));
				this.request = null;
				
				this.updater.observe('click', this.updateQty.bindAsEventListener(this));
				this.container.select('a[rel=external]').each(function(a){
					a.target = '_blank';
				});
			}.bind(this)
		});
	}
	
});

BetterCheckout.GiftMessage = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-giftmessage');

		if(! this.container)
		{
			return;
		}
		
		this.content = this.container.down('.bettercheckout-content');
		this.main.parse(this.container, this.save.bind(this));
	},
	
	
	save: function(e, input)
	{
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/ajax/setGiftMessage',
			this.main.form.serialize(true)
        );
	}
	
});

BetterCheckout.Agreements = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.setup();
	},
	
	setup: function()
	{
		var elements = this.main.form.select('.bettercheckout-agreement');
		
		if(! elements.length)
		{
			return;
		}

		var modal = new Cc.Modal(); 

		elements.each(function(element){
			var toggler = element.down('label a');
			var agreement = element.down('.bettercheckout-agreement-content');
			
			toggler.observe('click', function(e){
				e.stop();
				modal.show(agreement);
			});
		}, this);
	}

});

BetterCheckout.Additional = Class.create({
	
	initialize: function(main)
	{
		this.main = main;
		this.container = this.main.form.down('#bettercheckout-actions');
		
		this.main.parse(this.container, this.save.bind(this));
	},
	
	save: function(e, input)
	{
		this.main.sendRequest(
			this.main.baseUrl + 'bettercheckout/ajax/setAdditional',
			this.main.form.serialize(true)
        );
	}

});