var OrangeCheckout = {};

OrangeCheckout.basketUpdater = Class.create({
	initialize: function (element, form, options){
		this.element = $(element);
		this.form = form;
		this.options = Object.extend({
			afterUpdate: Prototype.emptyFunction
		}, options || {});
	},
	attachHandlers: function(removeElements) {
		removeElements.invoke('observe', 'click', function(event){
			url = event.element().href;
			new ajaxModal(this.options.confirmationUrl + "?item=" +url.toQueryParams().item +"&itemType=" +url.toQueryParams().itemType);
			Event.stop(event);
			return false;
		}.bindAsEventListener(this))
	},
	attachChangeHandlers: function(changeElements, quantityObserver) {
		changeElements.invoke('observe', 'click', function(event){
			url = event.element().href;
			var needsModal = event.element().hasClassName('needsModal');
			// if there are accessories in the basket, show a confirmation overlay before changing the phone/plan
			if(quantityObserver && (quantityObserver.getTotalSelected() - quantityObserver.getUnMarkedQuantity()) > 0 || needsModal) {
				var queryString = url.split('?');
				if (queryString.length < 2) { new ajaxModal(this.options.changeConfirmationUrl); }
				else { new ajaxModal(this.options.changeConfirmationUrl + "?" + queryString.last()); }
				Event.stop(event);
				return false;
			}
		}.bindAsEventListener(this))
	},
	attachDeliveryHandlers: function(deliveryElements) {
		deliveryElements.invoke('observe', 'click', function(event) {
			this.ajaxUpdateBasket($(this.form).action + "?" + $(this.form).serialize() + "&submit_update_basket=update_basket&ajax=yes");
		}.bindAsEventListener(this));
	},
	attachPromoHandlers: function(promoElements) {
		promoElements.invoke('observe', 'click', function(event) {
			Event.stop(event);
			this.serializeAndSend(event);
		}.bindAsEventListener(this));
	},
	attachPromoHandlerToInput: function(promoInputElement) {
		try{
			promoInputElement.observe('keypress', function(event) {
				if (Event.KEY_RETURN == event.keyCode) {
					Event.stop(event);
					this.ajaxUpdateBasket($(this.form).action + "?" + $(this.form).serialize() + "&submit_update_basket=update_basket&submit_get_discount.x=43");
				}
			}.bindAsEventListener(this));
		}catch(e){
		}
	},
	/** form submitter methods */
	serializeAndSend: function(evt) {
		var parentForm = evt.element().up('form');
		var url = parentForm.action + "?ajax=yes&" + parentForm.serialize();

		var type = evt.element().type;
		if (type == 'image' || type == 'button' || type == 'submit') {
			url += this.getClickPos(evt);
		}
		this.ajaxUpdateBasket(url);
		return;
	},
	getClickPos: function(evt) {
		var elem = Event.element(evt);
		elemPos = elem.cumulativeOffset();
		var pos = "&" + elem.name + ".x=" + (evt.pointerX()-elemPos.left) + "&" + elem.name + ".y=" + (evt.pointerY()-elemPos.top);
		return pos;
	},
	ajaxUpdateBasket: function(url) {
		new Ajax.Request(url, {
			evalScripts: true,
			onLoading: function () {
				this.element.update('<p class="ajax_loader"><span>LOADING</span><p>')
			},
			method: 'get',
			onComplete: function(response) {
				if (response.responseText.isJSON()) {
					// Error message returned or change of confirmationUrl.
					var reply = response.responseText.evalJSON(true);
					if (reply.redirect) {
						new ajaxModal(reply.redirect);
					}
					else if (reply.errormsg) {
						new openModalWithContent(reply.errormsg, { message: true });
					}
				} else {
					this.element.update(response.responseText);
					this.notify('afterUpdate')
				}
			}.bindAsEventListener(this)
		});
	},
	notify: function(event_name){
		try{
			if(this.options[event_name])
				return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
		}catch(e){
			if(e != $break)
				throw e;
			else
				return false;
		}
	}

});

OrangeCheckout.totaliser = Class.create({
	initialize: function (totaliserElement, series, options){
		this.element = $(element);
		this.options = Object.extend({
			// options go here
		}, options || {});
		 if (!this.options.url) this.basketItems = this.newBasketItems();
		// detect the spinner event
		document.observe("spinner:spun", function(event) {
			this.updateItemQuantity(event.target.up('tr').id, event.memo.val);
			if (!this.options.url) {
				$('basket_items_total').update(this.options.unit + this.basketTotal())
				new Effect.Highlight($('basket_items_total'), {duration: 1.2})
			}
		}.bindAsEventListener(this));
	},
	updateTotal: function(){
		var total = 0
		this.basketItems.each( function(b){
			total += (b.quantity * b.price)
		})
		return total
	}
});

OrangeCheckout.modalWarning = Class.create({
	initialize: function(inputId, alertId, mainChecklist, options){
		this.inputId = inputId;
		this.mainChecklist = mainChecklist;
		if ($(inputId)) {
			$(inputId).observe('click', function(event){
				if ($(inputId).checked) {
					new ajaxModal(alertId);
					this.mainChecklist.removeSubmitHandler();
				} else {
					this.mainChecklist.addSubmitHandler();
				}
			}.bind(this));
		}
	},
	addCancelHandler: function(canceller){
		canceller.observe('click', function(evt) {
			$(this.inputId).checked = false;
		}.bind(this));
	}
});

OrangeCheckout.checklist = Class.create({
	initialize: function (form, formButton, alertId, options){
		this.isBeingObserved = false;
		this.form = $(form);
		this.formButton = $(formButton);
		this.checklist = $(alertId);
		if(this.checklist) {
			this.checklist.select('h2').invoke('addClassName', 'replacement');
			this.alertBoxHtml = this.checklist.innerHTML;
			this.ready = false;
			this.checklist.hide();
			this.options = Object.extend({
				// options go here
			}, options || {});
			this.bShow = this.show.bindAsEventListener(this);
			this.addSubmitHandler();
		}
	},
	addSubmitHandler: function(){
		if (this.isBeingObserved == false) {
			this.form.observe('submit', this.bShow);
			this.isBeingObserved = true;
		}
	},
	removeSubmitHandler: function(){
		if (this.isBeingObserved == true) {
			this.form.stopObserving('submit', this.bShow);
			this.isBeingObserved = false;
		}
	},
	show: function(event){
		if(!$('orangeCareTerms') || ($('orangeCareTerms').checked)) {
			new openModalWithContent(this.alertBoxHtml);
		}
		Event.stop(event);
		return false;
	}
});

OrangeCheckout.previousAddresses = Class.create({
	initialize: function (containerElement, URL, pafHandler, pafElements, options){
		this.containerElement = $(containerElement);
		this.URL = URL;
		this.pafHandler = pafHandler;
		this.pafElements = pafElements;

		this.options = { };
		Object.extend(this.options,options || {});
		this.previousAddressCount = 0;

		this.containerElement.up('form').observe('submit', function(event){
			var actions = this.additionalAddressCheck();
			if (actions == 'added_addresses'){
				// Additional address elements have been added.
				alert("Please ensure that you have filled in addresses to cover the last 3 years");
				Event.stop(event);
				return false;
			} else if (!this.validates()) {
				alert("Please check that you have filled in all required fields");
				Event.stop(event);
				return false;
			} else {
				return true;
			}
		}.bindAsEventListener(this));

		this.attachAdditionalAddressHandlers(this.containerElement);

	},
	attachAdditionalAddressHandlers: function(attachElement) {
		if (this.previousAddressCount > 0) {
			$$('h3.hdr_previous_address').invoke('show');
		}
		var dateElements = attachElement.select('select');

		dateElements.each( function(elem, num) {

			elem.observe('change', function(event) {
				this.additionalAddressCheck();
			}.bindAsEventListener(this))

		}.bindAsEventListener(this));
	},
	validates: function() {
		var isValid = true;
		this.containerElement.getElementsBySelector('#required').each(function(input){
			if($F(input) == "") isValid = false;
		});
		return isValid;
	},
	additionalAddressCheck: function() {

		if (this.options.minimum) {
			var minimum = this.options.minimum;
			var total_time = 0;
			var i = 0;
			var previous_time = 0;

			// Do a check of the total length of time shown in addresses.
			do {
				var months = parseInt($F(this.containerElement.up('form').down('.months', i)));
				var years = parseInt($F(this.containerElement.up('form').down('.years', i)));
				previous_time = (years*12) + months;
				total_time += (years*12) + months;

				// If the total is more than minimum before the last address field is reached, we don't need it.
				if (total_time >= minimum && i < this.previousAddressCount) {
					this.removeAdditionalAddress(i);
				}
				i++;
				}
			while(i <= this.previousAddressCount && previous_time != 0);

			// If the total time is less than minimum, and the last field has dates filled in, add another field.
			if (total_time < minimum && previous_time != 0) {
				this.addAdditionalAddress();
			}
			// End of time-based approach
		} else {
			// Address quantity specified approach.
			var quantity = parseInt($F(this.containerElement.up('form').down('.quantity')) - 1);

			if (quantity < this.previousAddressCount) {
				this.removeAdditionalAddress(quantity);
				if (quantity == 0) {
					$$('h3.hdr_previous_address').invoke('addClassName', 'hide');
				}
			}
			else if (quantity > this.previousAddressCount) {
				$$('h3.hdr_previous_address').invoke('removeClassName', 'hide');
				for (var k = (quantity - this.previousAddressCount); k > 0; k--) {
					this.addAdditionalAddress();
				}
			}

		}
	},
	removeAdditionalAddress: function(newAmount) {
		// Remove any unnessary previous address elements.
		for (var j = newAmount; this.previousAddressCount > newAmount; j++) {
			this.containerElement.down('fieldset', this.previousAddressCount).remove();
			this.previousAddressCount--;
		}
		return 'removed_addresses';
	},
	addAdditionalAddress: function() {
		var counter = ++this.previousAddressCount;

		new Ajax.Request((this.URL + '?previousAddresses=' + this.previousAddressCount), {
			method: 'get',
			onSuccess: function(result) {
				// Insert new previous address element.
				Element.insert(this.containerElement, { bottom: result.responseText });
			}.bindAsEventListener(this),
			onComplete: function(r) {
				var elements = $$(this.pafElements);
				// Update the paf handling so that additional addresses also get the paf lookup.
				this.pafHandler.updateElements(elements);
				this.pafHandler.loadPAF();

				// Hide the non-lookup elements of the address section.
				elements[counter].down('dl', 1).hide();

				// fragment added by JMcVey
					// this section is to simulate serverside functionality absent on the client
					/*
						// get all select elements within target
						var p, s=elements[counter].select("select");

						// re-ID the selects and re-for the labels
						w = s[0].up(); //  w=wrapper, ergo label
						w.htmlFor = s[0].id = s[0].id+"_"+counter;

						w = s[1].up();
						w.htmlFor = s[1].id = s[1].id+"_"+counter;

						// re-name the selects also
						s[0].name = s[0].name+"_"+counter;
						s[1].name = s[1].name+"_"+counter;
					// alert("ids:\n===========\n\n" + selects[0].id +"\n"+ labels[0].htmlFor);
					*/

					// add event handlers to HTML included via Ajax
					s.invoke("observe", "change", function(e)
					{
						var o=Event.element(e).up(1).next('span');

						if (o) o.hide();
					});
				// end fragment

				// Add handlers to the additional address elements so that new address elements can be added.
				if (this.options.minimum) {
					this.attachAdditionalAddressHandlers(this.containerElement);
				}
			}.bindAsEventListener(this)
		});
		return 'added_addresses';
	}
});

OrangeCheckout.deliveryUpdater = Class.create({
	initialize: function(deliveryRadios, toUpdate, deliveryChangeUrl, options) {
		this.options = { };
		this.deliveryRadios = deliveryRadios;
		this.toUpdate = toUpdate;
		this.deliveryChangeUrl = deliveryChangeUrl;

		$A(this.deliveryRadios).each( function(e) {
			e.observe('click', this.updateDeliveryCost.bindAsEventListener(this));
		}.bind(this));
	},
	updateDeliveryCost: function(event) {
		var rad = event.element();
		var name = rad.name;
		var value = rad.value;

		var temp = new Array();
		temp = value.split('_');

		var delId = temp[0]
		var delDate = temp[1];

		deliveryUpdate = new Ajax.Updater(this.toUpdate, (this.deliveryChangeUrl +
				'?DeliveryId=' + delId +
				'&DeliveryDate=' + delDate), {
			method: 'get'
		});
	}
});

/**
 * @param options.skipVal Skips attachValidation step (for use with togglingElements that aren't form fields).
 * @param options.reversePolarity Reverses the toggle effect of this function (hides element on select of relevant class rather than show).
 */
OrangeCheckout.toggleSelectOnClass = Class.create({
	initialize: function (optionClassName, togglingClass, options){
		this.togglingElements = $$(togglingClass);
		this.optionElement = $$('option.'+optionClassName)[0];
		this.optionClassName = optionClassName;
		this.options = Object.extend({
			reversePolarity: false,
			afterUpdate: Prototype.emptyFunction()
		}, options || {});
		try {
			this.addHandlerToOption();
			this.checkVal();
		}
		catch (exception) {
			// This function uses a try/catch as the majority of places in which this function will be used is
			// in payment details forms, where the credit card details may only be taken if there is a payment
			// expected immediately (phone not free, or accessories have been purchased)
		}
	},
	checkVal: function(){
		var selectElement = this.optionElement.up('select');
		selected = selectElement.selectedIndex;
		if(selectElement.down('option', selected).hasClassName(this.optionClassName)) {
			(this.options.reversePolarity) ? this.hideVals() : this.showVals();
			this.notify('afterUpdate', true);
		} else {
			(this.options.reversePolarity) ? this.showVals() : this.hideVals();
			this.notify('afterUpdate', false);
		}
	},
	showVals: function() {
		this.togglingElements.invoke('show');
		if(!this.options.skipVal){
			this.togglingElements.each( function(f) {
				attachValidation(f.down('input', 0).id, f.up('form').name);
			});
		}
	},
	hideVals: function() {
		this.togglingElements.invoke('hide');
		if(!this.options.skipVal){
			this.togglingElements.each( function(f) {
				attachValidation(f.down('input', 0).id, f.up('form').name);
			});
		}
	},
	addHandlerToOption: function() {
		var selectElement = this.optionElement.up('select');
		selectElement.observe('change', function(event){
			this.checkVal();
		}.bindAsEventListener(this));
	},
	notify: function(event_name){
		try{
			if(this.options[event_name])
				return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
		}catch(e){
			if(e != $break)
				throw e;
			else
				return false;
		}
	}
});


// this fragment has been added by Beatriz Martin.
// addSpanTag: function: create an span an insert it after the year element.
// showSpanElement: function: create an span an insert it after the year element.
// hideSpanElement: function: create an span an insert it after the year element.

OrangeShop.validateDate = Class.create({
	initialize: function (ddElement, formName, fieldId){
		this.wrapElement = ddElement;
		this.spanElement = null;
		var id = "jsvalidator_"+formName+"_"+fieldId;
		this.addSpanTag(id);
		//alert("formName = " + formName + "\n\nfieldId = " + fieldId);
	},
	addSpanTag: function(id){
		//alert("id = "+id);
		var errorMessageSpan = new Element('span', {'class': 'form-field-validation', 'id': id});
		errorMessageSpan.setStyle({'background-color': 'transparent', 'clear':'both'});
		errorMessageSpan.innerHTML = "Please enter a valid date.";

		this.spanElement = $(errorMessageSpan);
		$(this.wrapElement).insert({ bottom: $(this.spanElement) });
		this.hideSpanElement();

		if ($(this.wrapElement).hasClassName('age18Required')) {
			var errorMessageSpan = new Element('span', {'class': 'form-field-validation validate_age'});
			errorMessageSpan.setStyle({'background-color': 'transparent', 'clear':'both'});
			errorMessageSpan.innerHTML = "You should be at least 18 yrs of age to place your order.";

			this.spanElement = $(errorMessageSpan);
			$(this.wrapElement).insert({ bottom: $(this.spanElement) });
			this.hideSpanElement();
		}
	},
	showSpanElement: function(){
		var errorMssgSpan = this.spanElement;
		$(errorMssgSpan).show();
	},
	hideSpanElement: function(){
		var errorMssgSpan = this.spanElement;
		$(errorMssgSpan).hide();
	}
});

OrangeShop.validateMultipleFields = Class.create({
	initialize: function (fieldClass){
		this.addSpanTag($$(fieldClass));
	},
	addSpanTag: function(jointElements){
		jointElements.each( function(j) {
			var errorMessageSpan = new Element('span', {'class': 'form-field-validation validate-multiple-error'});
			errorMessageSpan.setStyle({'background-color': 'transparent', 'clear':'both'});
			errorMessageSpan.innerHTML = "This field hasn't been filled in correctly - please try again";

			if (j.up('dd').down('span.validate-multiple-error')) { }
			else {
				this.spanElement = $(errorMessageSpan);
				j.up('dd').insert({ bottom: $(this.spanElement) });
				this.hideSpanElement();
			}
		}.bind(this));
	},
	hideSpanElement: function(){
		var errorMssgSpan = this.spanElement;
		$(errorMssgSpan).hide();
	}
});

// It create span elements inside a dd tag which class=dateRequired
// to display the error associated to the fields inside a dd tag which class=dateRequired

OrangeShop.createSpanErrors = Class.create({
	initialize: function (){
		var wrapperTag = "dd";
		var wrapperClass = "dateRequired";
		var formName = "details";
		var tag_class = wrapperTag+"."+wrapperClass;
		var classEqualDateArray = $$(tag_class);

		classEqualDateArray.each(function(ddElem) {
			//dateErrorTag.push(new OrangeShop.validateDate(ddElem));
			if ((ddElem != null) && (ddElem.down('select') != null))
			{
				//alert("formName = " + formName+ "\n\n" + "ddElem.down('select').id = " + ddElem.down('select').id);
				new OrangeShop.validateDate(ddElem, formName, ddElem.down('select').id);
			}
		});
	}
});

OrangeCheckout.errorMessageLink = Class.create({
	initialize: function (){
		var errorLinkArray = $$("a.error");

		errorLinkArray.invoke( 'observe', 'click', function(evt) {
			element = evt.element();
			$(element.rel).focus();
		});
	}
});




// end of the fragment

// this class make visible the address block when the user do not enter
// the address mandatory fields and press submit.

OrangeShop.showsAddressFields = Class.create({
	initialize: function (){
		this.dlElements = null;
		this.setDlElements();

		$$('form').each(function(e)
						{
						e.observe('submit', function()
												{
												this.showDlElements();
												}.bind(this))
						}.bind(this));

	},
	setDlElements: function(){
		this.dlElements = $$('dl.lookupBlock');

	},
	showDlElements: function(){
		$(this.dlElements).each(function(e) {  e.setStyle({'display': 'block'});  });
	},
	hideDlElements: function(){
		$(this.dlElements).each(function(e) {  e.setStyle({'display': 'none'});  });
	}
});


function formatPrice(num) {
//	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num))
		num = "0";
	num = Math.floor(num*100+0.50000000001);
	pence = num%100;
	num = Math.floor(num/100).toString();
	if(pence<10)
		pence = "0" + pence;
	for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
		num = num.substring(0,num.length-(4*i+3))+','+
	num.substring(num.length-(4*i+3));
	return (num + '.' + pence);
}


//  over-writes the TOGGLE method of toggleByRadioButtons class in FUNCTIONS.JS
OrangeShop.toggleDeliveryAndBillingAddress = Class.create(OrangeShop.toggleByRadioButtons,
{
	toggle: function($super)
	{
		$super();

		var state = this.toggleState;

		switch (this.radioName)
		{
			case 'use_as_delivery_address':
			case 'use_as_billing_address':
				this.togglingElement.select('input.maybeRequired').invoke(
					(state==="visible") ? 'addClassName': 'removeClassName', 'required');

				if (state==="visible") loadAction();
			break;
		}
	}
});


Event.observe(window, 'load', function() {
	new linksToModal('.modal-link');
	replaceHeaders();
});


