var httpsUrl = "";
loadjscssfile(httpsUrl + '/modules/Adeo.SpringBoard.Ecommerce/view/ecommerce.css', 'css');

function AdeoOrder()
{
	/* Load cart contents from cookie if possible */
	var CART_CONTENTS = "CART_CONTENTS_COOKIE";
	this.CART_CONTENTS = CART_CONTENTS;
	var data = {
		currency: "CAD", 
		customer: null, 
		email: null,
		phone: null,
		mailingList: null,
		createAccount: null,
		password: null,
		billingAddress: {
			customerName: null, 
			address1: null, 
			address2: null, 
			city: null,
			country: null, 
			state: null, 
			postalCode: null }, 
		shippingAddress: {
			useBilling: null,
			customerName: null, 
			address1: null, 
			address2: null,
			city: null, 
			country: null, 
			state: null, 
			postalCode: null }, 
		items: [],
		shipping: 0,
		tax: [],
		discount: 0,
		token: null,
		coupons: [],
		payment: {}
	};
	this.data = data;
	var PromoHandlers = [];
	this.PromoHandlers = PromoHandlers;

	this.LoadCouponHandlers = function()
	{
		this.PromoHandlers.length = 0;
		for (var i = 0; i < this.data.coupons.length; i++)
		{
			this.PromoHandlers[i] = PromoFactory.CreatePromoHandler(this.data.coupons[i].type, this.data.coupons[i]);
		}
	}

	var cartCookie = getCookie(CART_CONTENTS);
	if (cartCookie)
	{
		this.data = $.evalJSON(cartCookie);
		this.LoadCouponHandlers();
	}

	var Loaded = false;
	this.Loaded = Loaded;



	/* Loads the checkout inputs into JSON data and saves to persistent cookie */
	this.InputValue = function(json, key, controlName, save)
	{
		var control = document.getElementById(controlName);
		if (control)
		{
			if (save)
			{
				json[key] = control.value;
			}
			else if (json[key])
			{
				control.value = json[key];
			}
		}
	}

	this.RecurseInput = function(data, json, inputs, save)
	{
		for (var key in json) 
		{
			if (typeof(json[key]) == 'string')
			{
				this.InputValue(data, key, inputs[key], save);
			}
			else
			{
				this.RecurseInput(data[key], json[key], inputs[key], save);
			}
		}
	}

	this.SaveFormContents = function()
	{
		this.RecurseInput(Order.data, EcomUI.Settings.inputNames, EcomUI.Settings.inputNames, true);
		this.SaveCartContents(true);
	}

	this.LoadFormContents = function()
	{
		this.Loaded = true;
		this.RecurseInput(Order.data, EcomUI.Settings.inputNames, EcomUI.Settings.inputNames, false);
	}

	/* Places cart content in persistent cookie */
	this.SaveCartContents = function(noRefresh)
	{
		setCookie(CART_CONTENTS, $.toJSON(this.data));
		if (!noRefresh)
		{
			EcomUI.CartUpdateHandler();
			EcomUI.ShowCart(); //ASSumes something changed and we want to refresh
		}
	}

	/* adds item to basket */
	this.AddItem = function(productKey, qty)
	{
		var pl = new SOAPClientParameters();
		pl.add("productKey", productKey);
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetProduct", pl, true, function(data) {
			/* Basic product data */
			var product = eval("(" + data + ")"); //Workaround for known bug "Invalid label" - http://willcode4beer.com/tips.jsp?set=jsonInvalidLabel
			var actualSku = product.sku;
			var desc = product.description;
			var pric = product.price;
			if (!qty) qty = 1;
			/* Options are trickier */
			var validated = true;
			var additionalDescription = "";
			for (var i = 0; i < product.options.length; i++)
			{
				var option = product.options[i];
				/* retrieve value */
				var control = document.getElementById("productOption" + i);
				var value = control.value
				if (control.options) //<select> control
				{
					value = control.options[control.selectedIndex].text;
				}
				/* fail validation if required */
				if (!value && option.required)
				{
					validated = false;
					control.className += " validationFailed";
					alert(option.name + " is required");
				}
				else if (value)
				{
					if (additionalDescription != "")
					{
						additionalDescription += ", ";
					}
					additionalDescription += option.name + ": " + value;
					/* sku and price */
					var optionIndex = control.selectedIndex - 1; //1st one is always blank
					if (option.sku)
					{
						actualSku = option.sku;
					}
					else if (option.values && option.values[optionIndex].sku)
					{
						actualSku = option.values[optionIndex].sku;
					}
					if (option.price)
					{
						pric = option.price;
					}
					else if (option.values && option.values[optionIndex].price)
					{
						pric = option.values[optionIndex].price;
					}
				}
			}
			if (additionalDescription)
			{
				desc += " (" + additionalDescription + ")";
			}
			/* Save and refresh */
			if (validated)
			{
				Order.data.items[Order.data.items.length] = {productKey: productKey, sku: actualSku, description: desc, quantity: qty, price: pric};
				Order.SaveCartContents(true);
				if (EcomUI.Settings.onAddToCart)
				{
					EcomUI.Settings.onAddToCart();
				}
				else
				{
					EcomUI.GoToCart();
				}
			}
		});		
	}

	this.Place = function()
	{
		if (EcomUI.ValidateCustomer() && EcomUI.ValidateAddress())
		{
			if (EcomUI.Settings.Payment.save)
				EcomUI.Settings.Payment.save();
			this.SaveFormContents();
			EcomUI.LoadPrePayment(Order.data.PaymentCode, function() {
				var validated = true;
				if (EcomUI.Settings.Payment.validate)
					validated = EcomUI.Settings.Payment.validate();
				if (validated)
				{					
					Order.ProcessPayment();
				}
			});
		}
	}

	/* Do not call directly unless validated */
	this.ProcessPayment = function()
	{
		var pl = new SOAPClientParameters();
		Order.data.currency = "CAD";
		pl.add("Code", Order.data.PaymentCode);
		pl.add("Order", $.toJSON(Order.data));
		pl.add("CultureCode", board_culture);		
		document.getElementById(EcomUI.Settings.controlNames.btnPlaceOrder).disabled = true;
		
		SOAPClient.invoke(URL_SOAP_CART, "ProcessPayment", pl, true, function(data) {
			
			document.getElementById(EcomUI.Settings.controlNames.btnPlaceOrder).disabled = false;
			try
			{				
				data = data.replace(/\n\\/g, "\\");
				
				var payment = eval("(" + data + ")");
				Order.data.token = payment.token;
				Order.SaveCartContents(true);
				if (payment.message)
				{
					alert(payment.message);
				}
				if (payment.success)
				{
					var redirected = false;
					if (EcomUI.Settings.Payment.type == 'submit')
					{
						var paymentForms = $("#" + EcomUI.Settings.containerNames.paymentPrePanel + " form");
						if (paymentForms.length > 0)
						{
							redirected = true;
							paymentForms[0].submit();
						}
						else
						{
							alert("There is no form to submit in the payments panel. Attempting to continue."); //Not even sure if this is a good idea.
						}
					}
					if (!redirected) // "fill" or just plain failed
					{						
						document.location = EcomUI.Settings.ConfirmationUrl;
					}
				}
			}
			catch (ex)
			{
				var msg = data.fileName;
				if (!msg)
					msg = ex.message;
				alert("Unexpected error: " + msg);
			}
		});
	}

	/* Removes and refreshes */
	this.RemoveItem = function(index)
	{
		if (confirm(SBPhrases["CART_REMOVE_ITEM"])) 
		{
			this.data.items.splice(index, 1);
			this.SaveCartContents();
		}
	}

	/* Updates quantity and refreshes */
	this.UpdateItem = function(index, qty)
	{
		if (window.beforeUpdateItem)
			window.beforeUpdateItem(index, qty);
		this.data.items[index].quantity = qty;
		this.SaveCartContents();
	}
}

function AdeoUI(userSettings)
{
	/* Can be used for customizations */
	var Settings = {
		defaultProductPage: '/',
		optionsTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/options.template.html',
		cartTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/cart.template.html',
		checkoutTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/checkout.template.html',
		accountTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/account.template.html',
		confirmationTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/confirmation.template.html',
		loginTemplate: '/modules/Adeo.SpringBoard.Ecommerce/view/login.template.html',
		inputNames: {
			currency: 'drpCurrency',
			email: 'txtEmail',
			phone: 'txtPhone',
			mailingList: 'txtMailList',
			createAccount: 'chkNewLogin',
			password: 'txtPassword',
			billingAddress: {
				customerName: 'txtName', 
				address1: 'txtAddress1', 
				address2: 'txtAddress2', 
				city: 'txtCity',
				country: 'drpCountry', 
				state: 'drpState', 
				postalCode: 'txtPostal' 
				}, 
			shippingAddress: {
				useBilling: 'chkUseBilling',
				customerName: 'txtName1', 
				address1: 'txtAddress11', 
				address2: 'txtAddress21',
				city: 'txtCity1', 
				country: 'drpCountry1', 
				state: 'drpState1', 
				postalCode: 'txtPostal1' 
				}
		}, 
		containerNames: {
			paymentPanel: 'divPayment',
			paymentPrePanel: 'divPrePayment',
			shippingPanel: 'divShipping',
			subTotalLabel: 'spanSubTotalAmount',
			discountLabel: 'spanDiscountAmount',
			shippingLabel: 'spanShippingAmount',
			taxLabel: 'spanTaxAmounts',
			totalLabel: 'spanTotalAmount',
			cartCountLabel: 'spanCartCount'
		},
		controlNames: {
			btnPlaceOrder: 'btnPlaceOrder'
		},
		shipping: 0,
		tax: []
	};
	this.Settings = Settings;

	/* override default settings */
	if (userSettings)
	{
		for (var key in userSettings) 
		{
			Settings[key] = userSettings[key];
		}
	}

	/* Load cart contents from cookie if possible */
	var UI_SESSION = "UI_SESSION";
	var Session = {lasttProductPage: Settings.defaultProductPage};
	var sessionCookie = getCookie(UI_SESSION);
	if (sessionCookie)
	{
		Session = $.evalJSON(sessionCookie);
	}
	this.Session = Session;


	/* Places cart content in persistent cookie */
	this.SaveSession = function()
	{
		setCookie(UI_SESSION, $.toJSON(this.Session));
	}

	/* Private */
	var templates = new Array();
	this.templates = templates;

	var countries = {};
	this.countries = countries;

	/* Loads a remote template file */
	this.LoadTemplate = function(template, controlName, data)
	{
		var doComplete = function(html) {
			var html = parseTemplate(templates[template], data);
			$("#" + controlName).html(html);
			if (template == EcomUI.Settings.checkoutTemplate)
			{
				EcomUI.RebindCountryList();
			}
			else if (template == EcomUI.Settings.loginTemplate)
			{
				$("#" + controlName).dialog({minWidth: 325, minHeight: 175});
			}
		}
		if (this.templates[template])
		{
			doComplete();
		}
		else
		{
			$.ajax({
				url: template,
				success: function(html) {
					templates[template] = html;
					doComplete();
				},
				error: function(req, status) {
					alert("Could not load template [" + template + "].Cause:\n" + req.status + " " + status);
				}
			});
		}
	}

	this.RevokeCoupon = function(Index, Template)
	{
		if (Order.data.coupons[Index])
		{
			if (confirm("Revoke coupon [" + Order.data.coupons[Index].code + "]?"))
			{
				Order.PromoHandlers[Index].OnRevoke();
				Order.data.coupons.splice(Index, 1);
				Order.LoadCouponHandlers();
				Order.SaveCartContents(true);
				EcomUI.LoadTemplate(Template, 'divEcommerce', Order.data);
			}
		}
	}

	this.ApplyCoupon = function(CouponCode, Template)
	{
		var couponApplied = false;
		if (CouponCode)
		{
			for (var i = 0; i < Order.data.coupons.length; i++)
				couponApplied = couponApplied || (Order.data.coupons[i].code.toLowerCase() == CouponCode.toLowerCase());
			if (!couponApplied)
			{
				/* Load from server */
				var pl = new SOAPClientParameters();
				pl.add("CouponCode", CouponCode);
				pl.add("CultureCode", board_culture);
				SOAPClient.invoke(URL_SOAP_CART, "GetCoupon", pl, true, function(data) {
					var coupon = eval("(" + data + ")");
					if (!coupon.invalid)
					{
						Order.data.coupons[Order.data.coupons.length] = coupon;
						Order.LoadCouponHandlers();
						Order.SaveCartContents();
						//EcomUI.LoadTemplate(Template, 'divEcommerce', Order.data);
					}
					else
					{
						alert("Coupon code is invalid or expired");
					}
				});
			}
			else
			{
				alert("Coupon already applied");
			}
		}
		else
		{
			alert("Coupon code is required");
		}
	}

	this.ShowPromoInfo = function()
	{
		$("#divPromoInfo").dialog({width: 750, height: 250});
	}

	this.LoadOptions = function(productKey, controlName)
	{
		/* This is a products page. Remember it */
		this.Session.lastProductPage = document.location.toString();
		this.SaveSession();

		/* Load from server */
		var pl = new SOAPClientParameters();
		pl.add("ProductKey", productKey);
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetOptions", pl, true, function(data) {
			var options = {options: eval(data) }; //Don't like this.... but whatever for now.
			EcomUI.LoadTemplate(EcomUI.Settings.optionsTemplate, controlName, options);
		});
		this.AttachEvents(productKey);
	}

	this.LoadCurrencies = function()
	{		
		var pl = new SOAPClientParameters();
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetCurrencies", pl, true, function(data) {
			var currencies = eval("(" + data + ")").currencies;
			EcomUI.currencies = currencies;
			var list = document.getElementById(EcomUI.Settings.inputNames.currency);
			if (list)
			{
				$(list).change(function() {
					Order.data.currency = list.options[list.selectedIndex].value;
					Order.SaveCartContents(true);
					if (window.changeCurrency)
						window.changeCurrency();
				});
				list.options.length = 0;
				for (var i = 0; i < currencies.length; i++)
				{
					if (!Order.data.currency)
					{
						if (window.currencyCode)
							Order.data.currency = window.currencyCode;
						else
							Order.data.currency = currencies[i].code;
						Order.SaveCartContents(true);
					}
					var option = new Option(currencies[i].code, currencies[i].code);
					list.options[list.options.length] = option;
					if (currencies[i].code == Order.data.currency)
						list.selectedIndex = i;
				}
			}
			else
			{
				throw new Error("Control named [" + listId + "] does not exist");
			}
		});
	}

	this.CartUpdateHandler = function()
	{
		/* Promos */
		for (var p = 0; p < Order.PromoHandlers.length; p++)
			Order.PromoHandlers[p].OnCartUpdate();

		/* Item count indicator */
		var spanCartCount = document.getElementById(EcomUI.Settings.containerNames.cartCountLabel);
		var spanCartSubTotal = document.getElementById(EcomUI.Settings.containerNames.subTotalLabel);
		var text = " 0 " + SBPhrases["CART_ITEMS"];
		var totalAmount = 0;
		if (Order.data.items.length > 0)
		{
			text = " " + Order.data.items.length + " " + SBPhrases["CART_ITEMS"];
			
			for (var i = 0; i < Order.data.items.length; i++)
				totalAmount += Order.data.items[i].price * Order.data.items[i].quantity;		
		}
		
		spanCartSubTotal.innerHTML = totalAmount.toFixed(2);
		spanCartCount.innerHTML = text;
	}

	this.AttachEvents = function(productKey)
	{
		/* Add to cart */
		$('.btnAddCart').click(function() {
			qty = 1;
			var txtQuantity = document.getElementById("txtQuantity");
			if (txtQuantity)
			{
				qty = parseInt(txtQuantity.value);
			}
			//var options = EcomServer.GetOptions(productKey);
			Order.AddItem(productKey, qty);
		});
	}

	this.UpdatePrice = function(newPrice)
	{
		if (newPrice)
		{
			var prices = $(".price").html("$" + newPrice);
		}
	}

	this.GoToCart = function() 
	{
		/* Redirect to cart page */
		var pl = new SOAPClientParameters();
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetCartUrl", pl, true, function(data) {
			document.location = httpsUrl + data;
		});
	}

	this.GoToCheckout = function() 
	{
		/* Redirect to cart page */
		var pl = new SOAPClientParameters();
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetCheckoutUrl", pl, true, function(data) {
			document.location = data;
		});
	}

	this.GoBackLastProduct = function()
	{
		if (this.Session.lastProductPage)
			document.location = this.Session.lastProductPage;
		else
			history.go(-1);
	}

	/* Loads the cart from a remote template file */
	this.ShowCart = function()
	{
		if (EcomUI.Settings.onBeforeShowCart)
		{
			EcomUI.Settings.onBeforeShowCart();
		}
		EcomUI.LoadTemplate(EcomUI.Settings.cartTemplate, 'divEcommerce', Order.data);
	}


	this.SimulateUpdateCart = function()
	{
		var divEcommerce = document.getElementById("divEcommerce");
		divEcommerce.innerHTML = "<img src='/modules/Adeo.SpringBoard.Ecommerce/view/imgs/ajax-loader.gif' />";		
		setTimeout("EcomUI.ShowCart()", 1000);
	}

	this.HasData = function(JsonObj)
	{
		var hasData = false;
		for (var key in JsonObj)
		{
			if (JsonObj[key])
				hasData = true;
		}
		return hasData;
	}

	/* Loads the checkout page from a remote template file */
	this.ShowCheckout = function()
	{
		/* Get client info if logged in. */
		var pl = new SOAPClientParameters();
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetCustomerData", pl, true, function(Data) {
			var data = eval("(" + Data + ")");
			if (data.customerInfo)
			{
				//if (!EcomUI.HasData(Order.data.billingAddress))
					Order.data.billingAddress = data.customerInfo.billingAddress;
				//if (!EcomUI.HasData(Order.data.shippingAddress))
					Order.data.shippingAddress = data.customerInfo.shippingAddress;
			}
			EcomUI.countries = data.countries;
			data.order = Order.data;
			Order.SaveCartContents(true);
			Order.Loaded = false;
			EcomUI.LoadTemplate(EcomUI.Settings.checkoutTemplate, 'divEcommerce', data);
		});
	}

	this.RegexCheck = function(controlName, description, regex)
	{
		var control = document.getElementById(controlName);
		var result = true;
		if (control)
		{
			if (!regex.test(control.value))
			{
				result = false;
				alert('Invalid ' + description);
				control.className += " validationFailed";
			}
		}
		return result;
	}

	this.NullCheck = function(controlName, description)
	{
		var INVALID_CLASS = " validationFailed";
		var control = document.getElementById(controlName);
		var result = true;
		if (control)
		{
			var val = control.value;
			if (control.options && (control.selectedIndex >= 0))
				val = control.options[control.selectedIndex].value;

			if (!val)
			{
				result = false;
				alert(description + " required");
				control.className += INVALID_CLASS;
			}
			else
			{
				control.className = control.className.replace(INVALID_CLASS, "");
			}
		}
		return result;
	}

	this.ValidateCustomer = function()
	{
		return this.NullCheck(Settings.inputNames.phone, 'Phone') && this.RegexCheck(Settings.inputNames.email, "email address", /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i);
	}

	this.ValidateAddress = function()
	{
		var valid = 
				this.NullCheck(Settings.inputNames.billingAddress.customerName, 'Name') &&
				this.NullCheck(Settings.inputNames.billingAddress.address1, 'Address') &&
				this.NullCheck(Settings.inputNames.billingAddress.city, 'City') &&
				this.NullCheck(Settings.inputNames.billingAddress.country, 'Country') &&
				this.NullCheck(Settings.inputNames.billingAddress.state, 'State') &&
				this.NullCheck(Settings.inputNames.billingAddress.postalCode, 'Postal code');
		
		var useBilling = true;
		var chkBilling = document.getElementById(Settings.inputNames.shippingAddress.useBilling);
		if (valid && chkBilling && !chkBilling.checked)
		{
			valid = 
				this.NullCheck(Settings.inputNames.shippingAddress.customerName, 'Ship to name') &&
				this.NullCheck(Settings.inputNames.shippingAddress.address1, 'Ship to address') &&
				this.NullCheck(Settings.inputNames.shippingAddress.city, 'Ship to city') &&
				this.NullCheck(Settings.inputNames.shippingAddress.country, 'Ship to country') &&
				this.NullCheck(Settings.inputNames.shippingAddress.state, 'Ship to state') &&
				this.NullCheck(Settings.inputNames.shippingAddress.postalCode, 'Ship to postal code');			
		}

		return	valid;
	}

	this.EnableBilling = function(disable)
	{
		var index = 0;
		for (var key in this.Settings.inputNames.shippingAddress)
		{
			var control = document.getElementById(this.Settings.inputNames.shippingAddress[key]);
			if (index && control) {
				control.disabled = disable;
				/*
				Not worth the trouble... Needs to be called on load & there is the issue of dropdowns not matching etc.
				var controlBilling = document.getElementById(controls[i]);
				if (disable && controlBilling)
				{
					control.value = controlBilling.value;
				}
				*/
			}
			index++;
		}
	}

	this.RebindCountryList = function()
	{
		var list = document.getElementById(this.Settings.inputNames.billingAddress.country);
		var list1 = document.getElementById(this.Settings.inputNames.shippingAddress.country);
		if (list && list1)
		{
			list.options.length = 0;
			list1.options.length = 0;
			list.options[0] = new Option("", "");
			list1.options[0] = new Option("", "");
			for (var i = 0; i < this.countries.length; i++)
			{
				var newOption = new Option(this.countries[i].name, this.countries[i].code);
				list.options[list.options.length] = newOption;
				if (this.countries[i].code == Order.data.billingAddress.country)
					list.selectedIndex = i + 1;
				list1.options[list1.options.length] = new Option(this.countries[i].name, this.countries[i].code);
				if (this.countries[i].code == Order.data.shippingAddress.country)
					list1.selectedIndex = i + 1;
			}
			this.RebindStateList(list);
			this.RebindStateList(list1);
		}
		else
		{
			throw new Error("Controls named [" + this.Settings.inputNames.billingAddress.country + "] & [" + this.Settings.inputNames.shippingAddress.country + "] do not exist");
		}
	}

	this.RebindStateList = function(countryControl)
	{
		/* Get the country code */
		var countryCode = countryControl.options[countryControl.selectedIndex].value;
		var countryIndex = 0;
		var country;
		do
		{
			country = this.countries[countryIndex];
			countryIndex++;
		}
		while ((country.code != countryCode) && (countryIndex < this.countries.length));

		/* Reload options */
		var listId = this.Settings.inputNames.billingAddress.state;
		if (countryControl.id == this.Settings.inputNames.shippingAddress.country)
			listId = this.Settings.inputNames.shippingAddress.state;
		var stateControl = document.getElementById(listId);
		if (stateControl)
		{
			stateControl.options.length = 0;
			stateControl.options[0] = new Option("", "");
			for (var i = 0; i < country.states.length; i++)
				stateControl.options[stateControl.options.length] = new Option(country.states[i].name, country.states[i].code, country.states[i].code == Order.data.billingAddress.state);
		}
		else
		{
			throw new Error("Control named [" + listId + "] does not exist");
		}

		
		/* Payment, shipping and tax might also be affected */
		if (countryControl == document.getElementById(this.Settings.inputNames.billingAddress.country)) //Don't call twice
		{
			this.GetPaymentMethods();
		}
		else
		{			
			this.GetShippingMethods();
		}
		
		
	}

	this.GetPaymentMethods = function()
	{
		var stateControl = document.getElementById(this.Settings.inputNames.billingAddress.state);
		var countryControl = document.getElementById(this.Settings.inputNames.billingAddress.country);
		var postalCodeControl = document.getElementById(this.Settings.inputNames.billingAddress.postalCode);

		if (postalCodeControl && countryControl && stateControl)
		{
			var pl = new SOAPClientParameters();
			//pl.add("Country", Order.data.currency);
			pl.add("Country", "USD");
			pl.add("CultureCode", board_culture);
			
			SOAPClient.invoke(URL_SOAP_CART, "GetPaymentMethods", pl, true, function(data) {
			
				var paymentOptions = eval("(" + data + ")").payment;
				EcomUI.paymentOptions = paymentOptions;
				var paymentPanel = document.getElementById(EcomUI.Settings.containerNames.paymentPanel);
				if (paymentPanel)
				{
					paymentPanel.innerHTML = "";
					for (var i = 0; i < paymentOptions.length; i++)
					{
						if (!Order.data.PaymentCode)
							Order.data.PaymentCode = paymentOptions[i].code;
						EcomUI.AppendRadioOption(paymentPanel, "payment", paymentOptions[i].name, paymentOptions[i].code, i, Order.data.PaymentCode);
					}
					if (paymentOptions.length > 0)
					{
						EcomUI.LoadPrePayment(Order.data.PaymentCode);
						$("#" + EcomUI.Settings.containerNames.paymentPanel + " input[value=" + Order.data.PaymentCode + "]").attr("checked", true); //more MSIE crazyness
					}
					$("#" + EcomUI.Settings.containerNames.paymentPanel + " input").click(function() {
						/*  start MSIE 7 nonsense */
						$("#" + EcomUI.Settings.containerNames.paymentPanel + " input").attr("checked", null);
						this.checked = true;
						/* stop... the madness*/

						if (EcomUI.Settings.Payment.save)
							EcomUI.Settings.Payment.save();
						Order.data.PaymentCode = this.value;
						Order.SaveCartContents(true);
						EcomUI.LoadPrePayment(this.value);
					});
				}
			});
		}
		else
		{
			throw new Error("Could not find one of the following controls: country, state, or postal code. Check your .Settings");
		}
	}

	this.LoadPrePayment = function(code, callback)
	{
		var pl = new SOAPClientParameters();
		pl.add("Code", code);
		pl.add("Order", $.toJSON(Order.data));
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "PreProcessPayment", pl, true, function(data) {
try
{
			var payment = eval("(" + data + ")");
			EcomUI.Settings.Payment = payment;
//alert(EcomUI.Settings.Payment.toSource());
}
catch (ex)
{
	alert(ex.toSource() + "\nData:" + data.toSource());
}
			var paymentPanel = document.getElementById(EcomUI.Settings.containerNames.paymentPrePanel);
			if (paymentPanel)
			{
//alert(payment.html);
				paymentPanel.innerHTML = payment.html;
				if (EcomUI.Settings.Payment.load)
					EcomUI.Settings.Payment.load();
				if (callback)
					callback();
			}
		});
	}

	/* Can be overriden if necessary */
	this.AppendRadioOption = function(panel, group, caption, value, index, checkedValue)
	{
		var element = document.createElement("input");
		element.type = "radio";
		element.id= group + index;
		element.checked = (value == checkedValue) || (checkedValue == null && index == 0);
		element.name = group;
		element.value = value;
		panel.appendChild(element);
		element = document.createElement("span");
		element.innerHTML = caption;
		panel.appendChild(element);
		element = document.createElement("br");
		panel.appendChild(element);
	}

	this.AppendRadioGroup = function(panel, title)
	{
		element = document.createElement("span");
		element.innerHTML = title;
		element.className = "groupTitle";
		panel.appendChild(element);
		element = document.createElement("br");
		panel.appendChild(element);
	}

	this.GetShippingMethods = function()
	{
		var stateControl = document.getElementById(this.Settings.inputNames.billingAddress.state);
		var countryControl = document.getElementById(this.Settings.inputNames.billingAddress.country);
		var postalCodeControl = document.getElementById(this.Settings.inputNames.billingAddress.postalCode);
	
		if (postalCodeControl && countryControl && stateControl)
		{
			var pl = new SOAPClientParameters();
			pl.add("Country", countryControl.options[countryControl.selectedIndex].value);
			pl.add("State", stateControl.options[stateControl.selectedIndex].value);
			pl.add("PostalCode", postalCodeControl.value);
			pl.add("Items", $.toJSON(Order.data.items));
			pl.add("CultureCode", board_culture);
			
			SOAPClient.invoke(URL_SOAP_CART, "GetShippingRates", pl, true, function(data) {
				
				var shippingMethods = eval("(" + data + ")").shipping;
				EcomUI.shippingMethods = shippingMethods;
				var shippingPanel = document.getElementById(EcomUI.Settings.containerNames.shippingPanel);
				if (shippingPanel)
				{
					shippingPanel.innerHTML = "";
					for (var i = 0; i < shippingMethods.length; i++)
					{
						EcomUI.AppendRadioGroup(shippingPanel, shippingMethods[i].name);
						var rates = shippingMethods[i].options;
						for (var j = 0; j < rates.length; j++)
						{
							if (!Order.data.ShippingCode)
								Order.data.ShippingCode = rates[j].code;
							var option = EcomUI.AppendRadioOption(shippingPanel, "shipping", rates[j].name, rates[j].code, i, Order.data.ShippingCode);
						}
					}
					$("#" + EcomUI.Settings.containerNames.shippingPanel + " input").click(function() {
						/*  start MSIE 7 nonsense */
						$("#" + EcomUI.Settings.containerNames.shippingPanel + " input").attr("checked", null);
						this.checked = true;
						/* stop... the madness*/

						var discountAffected = false;
						for (var p = 0; p < Order.PromoHandlers.length; p++)
							discountAffected = discountAffected || Order.PromoHandlers[p].OnShipping(this.value);
						Order.data.ShippingCode = this.value;
						EcomUI.GetShippingAmount();
						Order.SaveCartContents(true);
						if (discountAffected)
							EcomUI.ShowCheckout();
						else
							EcomUI.ApplyTax();
					});
					$("#" + EcomUI.Settings.containerNames.shippingPanel + " input[value=" + Order.data.ShippingCode + "]").trigger('click');
					if (Order.Loaded)
					{
						Order.SaveFormContents();
					}
					else
					{
						Order.LoadFormContents();
					}
					EcomUI.ApplyTax();
				}
			});
		}
		else
		{
			throw new Error("Could not find one of the following controls: country, state, or postal code. Check your .Settings");
		}
	}

	this.GetShippingAmount = function()
	{
		var returnValue = -1;
		var shippingOptions = $("#" + EcomUI.Settings.containerNames.shippingPanel + " input");
		for (var i = 0; i < shippingOptions.length; i++)
		{
			if (shippingOptions[i].checked)
			{
				for (var g = 0; g < EcomUI.shippingMethods.length; g++)
				{
					var group = EcomUI.shippingMethods[g].options;
					for (var r = 0; r < group.length; r++)
					{						
						if (shippingOptions[i].value == group[r].code)
						{
							returnValue = group[r].amount;
							if (window.ecomUserSettings && window.ecomUserSettings.onProcessShipping)
								returnValue = window.ecomUserSettings.onProcessShipping(Order, group[r].amount);
							Order.data.shipping = returnValue;							
						}
					}
				}
			}
		}
		return returnValue;
	}

	this.ApplyTax = function()
	{
		var subTotalLabel = document.getElementById(EcomUI.Settings.containerNames.subTotalLabel);
		var shippingLabel = document.getElementById(EcomUI.Settings.containerNames.shippingLabel);
		var discountLabel = document.getElementById(EcomUI.Settings.containerNames.discountLabel);
		var taxLabel = document.getElementById(EcomUI.Settings.containerNames.taxLabel);
		var totalLabel = document.getElementById(EcomUI.Settings.containerNames.totalLabel);
		var stateControl = document.getElementById(EcomUI.Settings.inputNames.billingAddress.state);
		var countryControl = document.getElementById(EcomUI.Settings.inputNames.billingAddress.country);
		var postalCodeControl = document.getElementById(EcomUI.Settings.inputNames.billingAddress.postalCode);

		if (subTotalLabel && shippingLabel && taxLabel && totalLabel && stateControl && countryControl && postalCodeControl)
		{
			var pl = new SOAPClientParameters();
			pl.add("Country", countryControl.options[countryControl.selectedIndex].value);
			pl.add("State", stateControl.options[stateControl.selectedIndex].value);
			pl.add("PostalCode", postalCodeControl.value);
			pl.add("CultureCode", board_culture);
			SOAPClient.invoke(URL_SOAP_CART, "GetTaxRates", pl, true, function(data) {
				var taxes = eval("(" + data + ")").tax;
				/* Sub total */
				var subtotal = parseFloat(subTotalLabel.innerHTML);
				Order.data.totalAmount = subtotal;
				
				/* Shipping */					
				shippingLabel.innerHTML = Order.data.shipping.toFixed(2);								
				subtotal += Order.data.shipping;
				
				/* Discount */
				var discount = 0;
				if (discountLabel)
				{
					discount = parseFloat(discountLabel.innerHTML.replace("$", ""));
				}
				Order.data.discount = discount;
				subtotal = subtotal - discount;
				/* Taxes */
				var labelValue = "";
				Order.data.tax.length = 0;
				
				for (var i = 0; i < taxes.length; i++)
				{
					var taxAmount = (subtotal * (taxes[i].percentage / 100) + 0.0049);
					taxAmount = (Math.round(taxAmount * 100) / 100);
					subtotal += taxAmount;
					labelValue += "(" + taxes[i].code + ") $" + taxAmount.toFixed(2) + "\n<br />";
					Order.data.tax[Order.data.tax.length] = {code: taxes[i].code, percentage: taxes[i].percentage, amount: taxAmount};
				}
				if (!labelValue)
				{
					labelValue = "$0.00";
				}
				taxLabel.innerHTML = labelValue;
				totalLabel.innerHTML = (Math.round((subtotal) * 100) / 100).toFixed(2);
			});
		}
		else
		{
			throw new Error("Could not find one of the following controls: sub total, shipping, tax or grand total. Check your .Settings");
		}
	}

	/* Loads the checkout screen from a remote template */
	this.ShowAccount = function()
	{
		/* Get client info if logged in. */
		var pl = new SOAPClientParameters();
		pl.add("CultureCode", board_culture);
		SOAPClient.invoke(URL_SOAP_CART, "GetOrderHistory", pl, true, function(data) {
			var history = eval("(" + data + ")");
			EcomUI.LoadTemplate(EcomUI.Settings.accountTemplate, 'divEcommerce', history);
		});
	}

	/* Loads the checkout screen from a remote template */
	this.ShowConfirmation = function()
	{
		 EcomUI.LoadTemplate(EcomUI.Settings.confirmationTemplate, 'divEcommerce', Order.data);
	}

	/* I only want the 2 decimals i gave you, thx.
	http://www.mredkj.com/javascript/nfbasic2.html
	*/
	this.FixFloat = function(Amount)
	{
		Amount *= 100;
		Amount = Math.round(Amount);
		return (Amount / 100).toFixed(2);
	}

	/* Prints the links container in a "clean" window */
	this.PrintReceipt = function(sender)
	{
		var html = "<html><head><link rel='stylesheet' type='text/css' href='/modules/Adeo.SpringBoard.Ecommerce/view/ecommerce.css' /></head><body>" + sender.parentNode.innerHTML + "</body></html>";
		var win = window.open();
		win.document.write(html);
		win.document.close(); 
		win.print();
	}

	this.OpenLogin = function()
	{
		this.divLoginFormName = "divLoginForm";
		if (!document.getElementById(divLoginForm))
		{
			var divLoginForm = document.createElement("div");
			divLoginForm.id = this.divLoginFormName;
			divLoginForm.title = SBPhrases["CART_LOGIN"];
			document.body.appendChild(divLoginForm);
		}
		EcomUI.LoadTemplate(EcomUI.Settings.loginTemplate, this.divLoginFormName, {});
	}

	this.AfterLogin = function(response)
	{
		if (response.toString() == true.toString())
		{
			$("#" + EcomUI.divLoginFormName).dialog("close");
			EcomUI.ShowCheckout();
		}
		else
		{
			document.getElementById("divEcomLoginFailed").style.display = "block";
		}
	}

	this.Logout = function()
	{
		Security.UserLogout(function() {
			EcomUI.ShowCheckout();
		});
	}
}

AdeoEcom = {};

///////// PROMO FACTORY  ///////////

AdeoEcom.PromoMaker = function() {};

AdeoEcom.PromoMaker.prototype.CreatePromoHandler = function(Code, Promo)
{
	switch (Code) //sucks!
	{
		case "9": 
			return new AdeoEcom.PercentOffPromo(Promo);
			break;
		case "11": 
			return new AdeoEcom.FreeShippingPromo(Promo);
			break;
		case "10": 
			return new AdeoEcom.DollarsOffPromo(Promo);
			break;
		case "12": 
			return new AdeoEcom.FreeWithPurchasePromo(Promo);
			break;
		default:
			return new AdeoEcom.Promo(Promo);
			break;
	}
}

///////// PROMO HANDLERS  ///////////

AdeoEcom.Promo = function(Promo) { 
	this.Promo = Promo;
};

AdeoEcom.Promo.prototype.IsEligible = function() {
	var isEligible = true;
	switch (this.Promo.condition)
	{
		case "totalAmount":
			var totalAmount = 0;
			for (var i = 0; i < Order.data.items.length; i++)
				totalAmount += Order.data.items[i].price * Order.data.items[i].quantity;
			isEligible = totalAmount >= parseFloat(this.Promo.value);
			break;
		case "sku":
			var parts = this.Promo.value.split("*");
			var sku;
			var itemCount = 1;
			if (parts.length > 1)
			{
				itemCount = parseInt(parts[0]);
				sku = parts[1];
			}
			else
			{
				sku = this.Promo.value;
			}
			var hasItem = false;
			for (var i = 0; i < Order.data.items.length; i++)
				hasItem = hasItem || ((Order.data.items[i].sku == sku) && (Order.data.items[i].quantity >= itemCount));
			isEligible = hasItem;
			break;
	}
	return isEligible;
};

AdeoEcom.Promo.prototype.IndexOfSku = function(Sku) {
	var itemIndex = -1;
	for (var i = 0; i < Order.data.items.length; i++)
	{
		if (Order.data.items[i].sku == Sku)
			itemIndex = i;
	}
	return itemIndex;
}

AdeoEcom.Promo.prototype.CheckDiscount = function(Discount) {
	if (this.IsEligible())
		return parseFloat(Discount);
	else
		return 0;
}

AdeoEcom.Promo.prototype.OnCartUpdate = function() {};

//Returns true if discount affected
AdeoEcom.Promo.prototype.OnShipping = function(NewCode) {
	return false;
};

AdeoEcom.Promo.prototype.GetDiscountAmount = function(OrderTotal) {
	return 0;
};

AdeoEcom.Promo.prototype.OnRevoke = function() {};




//     /////// PERCENT OFF  ///////////
AdeoEcom.PercentOffPromo = function(Promo) {
	this.constructor(Promo);
};

AdeoEcom.PercentOffPromo.prototype = new AdeoEcom.Promo();

AdeoEcom.PercentOffPromo.prototype.GetDiscountAmount = function(OrderTotal) {
	var totalAmount = OrderTotal;
	if (this.Promo.condition == "sku")
	{
		var skuIndex = IndexOfSku(this.Promo.value);
		if (skuIndex >= 0) //Ok to default to total, becuase won't be eligible anyway and will return 0
			totalAmount = Order.data.items[skuIndex].quantity * Order.data.items[skuIndex].price;
	}
	return this.CheckDiscount(totalAmount * (parseFloat(this.Promo.amount) / 100));
};


//     /////// DOLLARS OFF  ///////////
AdeoEcom.DollarsOffPromo = function(Promo) {
	this.constructor(Promo);
};

AdeoEcom.DollarsOffPromo.prototype = new AdeoEcom.Promo();

AdeoEcom.DollarsOffPromo.prototype.GetDiscountAmount = function(OrderTotal) {
	return this.CheckDiscount((this.Promo.amount));
};


//     /////// FREE SHIPPING  ///////////
AdeoEcom.FreeShippingPromo = function(Promo) {
	this.constructor(Promo);
};

AdeoEcom.FreeShippingPromo.prototype = new AdeoEcom.Promo();

AdeoEcom.FreeShippingPromo.prototype.OnShipping = function(NewCode) {
	return Order.data.ShippingCode != NewCode;
};

AdeoEcom.FreeShippingPromo.prototype.GetDiscountAmount = function(OrderTotal) {
	return this.CheckDiscount(Order.data.shipping);
};


//     /////// FREE SHIPPING  ///////////
AdeoEcom.FreeWithPurchasePromo = function(Promo) {
	this.constructor(Promo);
};

AdeoEcom.FreeWithPurchasePromo.prototype = new AdeoEcom.Promo();

AdeoEcom.FreeWithPurchasePromo.prototype.OnCartUpdate = function() {
	var freebieIndex = this.IndexOfSku(this.Promo.code);
	var needsSaving = false;
	if (this.IsEligible() && (freebieIndex < 0)) //add freebie
	{
		Order.data.items[Order.data.items.length] = {"productKey":-1,"sku":this.Promo.code,"description":this.Promo.description,"quantity":"1","price":"0.00"};
		needsSaving = true;
	}
	else if (!this.IsEligible() && (freebieIndex >= 0)) //remove freebit
	{
		Order.data.items.splice(freebieIndex, 1);
		needsSaving = true;
	}
	else if ((freebieIndex >= 0) && (Order.data.items[freebieIndex].quantity != 1)) //nice try, but don't get greedy.
	{
		Order.data.items[freebieIndex].quantity = 1;
	}
	if (needsSaving)
		Order.SaveCartContents(true);
};

AdeoEcom.FreeWithPurchasePromo.prototype.GetDiscountAmount = function(OrderTotal) {
	return this.CheckDiscount(0);
};

AdeoEcom.FreeWithPurchasePromo.prototype.OnRevoke = function() {
	var freebieIndex = this.IndexOfSku(this.Promo.code);
	if (freebieIndex >= 0) //zoink!
		Order.data.items.splice(freebieIndex, 1);
};



//var EcomServer = new AdeoServer();
var URL_SOAP_CART = "/modules/Adeo.SpringBoard.Ecommerce/model/Ecommerce.asmx";
var PromoFactory = new AdeoEcom.PromoMaker();
var EcomUI = new AdeoUI(window.ecomUserSettings);
var Order = new AdeoOrder();

$(document).ready(function() {
	EcomUI.CartUpdateHandler();
});

