var nlm = new nlmScripter;
var SITE_ROOT = '/cart/';
var CART_URL = SITE_ROOT + '/cart.http.php';

var ERRORS = new Array();
var CURRENT_ADDRESS_TYPE = '';

var ADDRESS_SHIPPING = 'shipping';
var ADDRESS_BILLING = 'billing';


var SHIPPING_FOUND = false;

/**
 * ***
 * Front end functions for adding a new product to the cart.
*/

/**
 * Add a product to cart. The quantity and atttributes will automatically be added
 * by grabbing the values from the DOM.
*/
function addToCart(product_id) {
	// First, get any attributes
	var attr = $('attributes_' + product_id);

	var quantity = $('quantity_' + product_id).value();
	quantity = parseInt(quantity);
	
	if ( isNaN(quantity) || quantity < 1) {
		alert('The quantity must be a number greater than 0.');
		return false;
	}
	
	params = new Object();
	params.action = 'addproduct';
	params.product_id = product_id;
	params.quantity = quantity;
	
	_sendRequest(params, function(json) { _httpAddToCart(json, product_id); } );
}

/**
 * Handle the response after a product has been added to a cart.
*/
function _httpAddToCart(json, pid) {
	//var response = nlm.json(json);

	//var pid = response.product_id;

	//var message_class = ( 1 == response.error ? 'error' : 'success' );
	// class - FireFox/good browsers
	//$('request_message_' + pid).attr('class', message_class);
	
	// className - IE
	//$('request_message_' + pid).attr('className', message_class);
	
	//$('request_message_' + pid).replace( T('span', { content: response.text } ) );

	$('request_message_' + pid).addHtml(json);
	setTimeout( function() { $('request_message_' + pid).addHtml('') }, 5000);
}


/**
 * ***
 * Shopping Cart Front End Functions
 * ***
*/


/**
 * Determines which step of the cart to show depending on the validation
 * of previous form inputs.
*/
function showStep(step_num) {
	ERRORS = new Array();
	
	switch ( step_num ) {
		// Just a placeholder
		case STEP_BEGIN: {
			break;
		}
		
		// They are going to the shipping section, so the name and email
		// address need to be validated.
		case STEP_SHIPPING: {
			var validate_begin = _validateBegin();
			if ( true == validate_begin ) {
				showQuantityText('update_quantities_shipping', 'update_quantities_finalize');
				_saveCustomer();
			} else {
				_message(ERRORS, 1);
			}
			
			break;
		}
	
		// The customer is going to the billing section, so the shipping address
		// and shipping method must be selected.
		case STEP_BILLING: {
			var validate_address = _validateForm('shipping_address', true);
			var validate_sm = _validateShippingMethod();

			if ( true == validate_address && true == validate_sm ) {
				$('update_quantities_shipping').style('display', 'none');
				$('update_quantities_finalize').style('display', 'none');
				
				_saveAddress('shipping_address', ADDRESS_SHIPPING, _httpSaveAddress);
				_setDisableQuantity(true);
			} else {
				_message(ERRORS, 1);
			}

			break;
		}
		
		// They are going to the confirmation section. The Billing Address and
		// Billing Information need to be validated before that can happen.
		case STEP_CONFIRM: {
			var validate_address = _validateForm('billing_address', false);
			var validate_billing = _validateForm('billing_information', false);
			
			if ( false == validate_billing || false == validate_address ) {
				_message(ERRORS, 1);
			} else {
				if ( true == validate_billing ) {
					_saveBilling('billing_information');
				}
				
				if ( true == validate_address ) {
					_saveAddress('billing_address', ADDRESS_BILLING, _httpSaveAddress);
				}
				
				showQuantityText('update_quantities_finalize', 'update_quantities_shipping');
				
				calculateTotal();
				_setDisableQuantity(true);
			}
			
			break;
		}
		
		case STEP_FINAL: {
			hideAll();
			showQuantityText('update_quantities_finalize', 'update_quantities_shipping');
			$('shopping_cart_final').style('display', 'block');
			$('shopping_cart_product_list').style('display', 'none');
			
			break;
		}
	}
}



function showQuantityText(show_field, hide_field) {
	$(hide_field).style('display', 'none');
	$(show_field).style('display', 'inline');
}

/**
 * Shows the shipping section.
*/
function showShipping() {
	hideAll();
	_setDisableQuantity(false);
	
	showQuantityText('update_quantities_shipping', 'update_quantities_finalize');
	$('shopping_cart_shipping').style('display', 'block');
}

/**
 * Shows the billing section.
*/
function showBilling() {
	hideAll();

	$('update_quantities_shipping').style('display', 'none');
	$('update_quantities_finalize').style('display', 'none');
	$('shopping_cart_billing').style('display', 'block');
}

/**
 * Shows the billing section.
*/
function showOverview() {
	hideAll();
	$('shopping_cart_overview').style('display', 'block');
}

/**
 * Hides all sections.
*/
function hideAll() {
	$('shopping_cart_start').style('display', 'none');
	$('shopping_cart_shipping').style('display', 'none');
	$('shopping_cart_billing').style('display', 'none');
	$('shopping_cart_overview').style('display', 'none');
}

function _setDisableQuantity(set) {
	var inputs = $('shopping_cart_product_list').childrenRaw('select');
	
	var i=0;
	for ( i=0; i<inputs.length; i++ ) {
		//if ( inputs[i].type == 'text' ) {
			inputs[i].disabled = set;
		//}
	}
}


/**
 * ***
 * Validation Functions
 * ***
*/

/**
 * Function to validate the Name and Email Address entered before the customer
 * can continue the checkout.
*/
function _validateBegin() {
	var inputs = $('customer_data').children('input');
	
	if ( inputs.name.length < 1 ) {
		ERRORS.push('Please enter a name.');
	}
	
	if ( inputs.email_address.length < 1 || false == _validateEmail(inputs.email_address) ) {
		ERRORS.push('The email address entered is invalid.');
	}
	
	if ( inputs.company.length < 1 ) {
		ERRORS.push('Please enter a company name.');
	}
	if ( inputs.phone_number.length < 6 ) {
		ERRORS.push('Please type your phone number, it must be 6 digits or longer.');
	}
	
	return ( ( ERRORS.length > 0 ) ? false : true );
}

function _validateForm(form_name, reset) {
	// If reset is true, the ERRORS array should be reset. If there
	// are multiple forms on the same page, reset should be set to false
	// so that the customer sees the errors of all forms.
	if ( true == reset ) { ERRORS = new Array(); }

	var form = $(form_name).childrenRaw('input');
	
	var i=0;
	for ( i=0; i<form.length; i++ ) {
		// Elements must be required to pass.
		// TODO: Make required a regex that they must pass.
		if ( 1 == form[i].getAttribute('required') ) {
			if ( form[i].value.length < 1 ) {
				var input_name = form[i].name.split('_').join(' ');
				ERRORS.push('Please enter a value into the "' + input_name + '" field.');
			}
		}
	}
	
	return ( ( ERRORS.length > 0 ) ? false : true );
}

/**
 * Validates whether or not a shipping method was selected.
*/
function _validateShippingMethod() {
	var form = $('shipping_method_list').childrenRaw('input');

	var i=0;
	var passed = false;
	for ( i=0; i<form.length; i++ ) {
		if ( true == form[i].checked ) { passed = true; }
	}

	if ( false == passed ) {
		ERRORS.push('Please select a Shipping Method before you continue.');
	} else {
		saveShippingMethod();
	}

	return passed;
}


function validateZipCode(zip_code) {
	//zip_code = zip_code;
	
	if ( zip_code.length == 5 ) {
		getShipping();
	}
}

/**
 * ***
 * Customer Information Management Functions
 * ***
*/


/**
 * Saves the Customer's Name and Email address to the session
*/
function _saveCustomer() {
	var inputs = $('customer_data').children('input');
	
	params = new Object();
	params.action = 'savecustomer';
	params.name = inputs.name;
	params.email_address = inputs.email_address;
	params.company = inputs.company;
	params.phone_number = inputs.phone_number;
	
	_sendRequest(params, _httpSaveCustomer);
}

/**
 * Callback from _saveCustomer()
*/
function _httpSaveCustomer(json) {
	var response = nlm.json(json);
	
	_message(response.text, response.error);
	if ( 0 == response.error ) {
		showShipping();
	}
}

/**
 * Saves an address to the session. The type is either shipping or billing.
 * save_function is a callback for what should happen after the address is saved.
*/
function _saveAddress(form_name, type, save_function) {
	var inputs = $(form_name).children('input');
	var state = $(form_name).children('select').state;
	var country = inputs.country; //$(form_name).children('select').country;


	var params = new Object();
	params.action = 'saveaddress';
	params.address_type = type;
	
	params.name = inputs.name;
	params.street_one = inputs.street_address_one;
	params.street_two = inputs.street_address_two;
	params.city = inputs.city;
	params.state = state;
	params.zip_code = inputs.zip_code;
	params.country = country;

	_setAddressType(type);
	_sendRequest(params, save_function);
	_writeAddress(type, params);
}

/**
 * Callback for after an address has been saved.
*/
function _httpSaveAddress(json) {
	var response = nlm.json(json);
	
	_message(response.text, response.error);
	if ( 0 == response.error ) {
		switch ( CURRENT_ADDRESS_TYPE ) {
			case ADDRESS_SHIPPING: {
				showBilling();
				break;
			}
			
			case ADDRESS_BILLING: {
				showOverview();
				break;
			}
		}
	}
}

function saveShippingMethod() {
	var form = $('shipping_method_list').childrenRaw('input');

	var i=0;
	var method;
	var module;
	var price = 0.0;
	for ( i=0; i<form.length; i++ ) {
		if ( true == form[i].checked ) {
			method = form[i].value;
		}
	}

	price = $('shipping_price_' + method).value();
	module = $('shipping_module_' + method).value();

	params = new Object();
	params.action = 'saveshipping';
	params.module = module;
	params.method = method;
	params.price = price;

	_sendRequest(params, function(json) { });
}

/**
 * Saves the billing information to the session.
*/
function _saveBilling(form_name) {
	var cc = $(form_name).children('input');
	
	var select = $(form_name).children('select');
	
	var params = new Object();
	params.action = 'savebilling';
	params.credit_card_name = cc.credit_card_name;
	params.credit_card_number = cc.credit_card_number;
	params.credit_card_expiration_month = select.credit_card_expiration_month;
	params.credit_card_expiration_year = select.credit_card_expiration_year;
	params.credit_card_cvv2 = cc.credit_card_cvv2;

	_sendRequest(params, function() {
			var cc_num = params.credit_card_number;
			var len = cc_num.length;
			var half = Math.ceil(len/2);
			var dist = Math.ceil(((len - half) / 2));
			
			var i=0;
			for ( i=dist; i<(dist+half); i++ ) {
				cc_num[i] = 'X';
			}

			$('shopping_cart_credit_card_overview').addHtml(
				params.credit_card_name + '<br />' +
				cc_num + '<br />' +
				params.credit_card_expiration_month + '/' + params.credit_card_expiration_year + '<br />' +
				params.credit_card_cvv2 + '<br /><br />'
			);
		}
	);
}

/**
 * Sets the global address type so it can be used in _httpSaveAddress()
*/
function _setAddressType(addr_type) {
	CURRENT_ADDRESS_TYPE = addr_type;
}

/**
 * Writes the address to the confirmation screen.
 * addr_type is either shipping or billing.
*/
function _writeAddress(addr_type, addr) {
	var addr_two = '';
	if ( '' != addr.street_two ) {
		addr_two = addr.street_two + '<br />';
	}
	
	$('shopping_cart_' + addr_type + '_overview').addHtml(
		addr.name + '<br />' +
		addr.street_one + '<br />' +
		addr_two +
		addr.city + ', ' + addr.state + ' ' + addr.zip_code + '<br />' +
		addr.country
	);
}

/**
 * Copies the address data from the 'from' form to the 'to' form.
*/
function copyAddress(from, to) {
	var from_addr = $(from).childrenRaw('input');
	var to_addr = $(to).childrenRaw('input');
	
	var from_state = $(from).children('select').state;
	var to_states = $(to).childrenRaw('option');


	var from_country = $(from).children('select').country;
	
	// Copy all of the input values.
	var i=0;
	for ( i=0; i<from_addr.length; i++ ) {
		to_addr[i].value = from_addr[i].value;
	}
	
	// Because the state is a dropdown, it needs to be handled differently.
	for ( i=0; i<to_states.length; i++ ) {
		if ( to_states[i].value == from_state ) {
			to_states[i].selected = true;
		}
		
		if ( to_states[i].value == from_country ) {
			to_states[i].selected = true;
		}
	}
}

/**
 * ***
 * Message Functions
 * ***
*/

/**
 * Writes a message to the shopping cart.
*/
function _message(msg, error) {
	var message_class = ( 1 == error ? 'message_error' : 'message_success' );
	
	if ( 'object' == typeof msg ) {
		msg = msg.join('<br />');
	}
	
	$('sc_message').addHtml(msg);
	$('sc_message').attr('class', message_class);
	$('sc_message').attr('className', message_class);
	$('sc_message').style('display', 'block');
}

/**
 * Hides the current message and resets the contents.
*/
function hideMessage() {
	$('sc_message').addHtml('');
	$('sc_message').style('display', 'none');
}

/**
 * ***
 * Shipping Functions
 * ***
*/

/**
 * Front end function for loading the shipping quotes.
 * _saveAddress() is called here to save the address first so that the
 * NLM_Mini_Cart class can just use the newly saved address rather than
 * having to pass the new data.
*/
function getShipping() {
	var validate_address = _validateForm('shipping_address', true);
	if ( true == validate_address ) {
		_saveAddress('shipping_address', ADDRESS_SHIPPING, _loadShippingQuotes);
	} else {
		_message(ERRORS, 1);
	}
}

/**
 * Callback for after the address has been saved.
*/
function _loadShippingQuotes(json) {
	_message('Loading your shipping quotes. One moment please.', 0);
	
	//$('shipping_method_list').addHtml('<img src="' + SITE_ROOT + '/Themes/Images/ajax_spinner_long.gif" />');
	$('shipping_method_list').replace( T('p', { content: 'Loading Shipping Quotes', 'class': 'success', next: T('img', { src: SITE_ROOT + '/Themes/Images/ajax_spinner_long.gif', style: 'margin: auto; display: block' } ) } ) );
	
	var params = new Object();
	params.action = 'getshipping';
	
	_sendRequest(params, _showShippingQuotes);
}

/**
 * Callback from _loadShippingQuotes that displays them on the screen.
*/
// TODO: handle errors gracefully
function _showShippingQuotes(json) {
	var sml = 'shipping_method_list';
	var sq = 'shipping_quotes';
	
	// Right now, pure HTML is being returned because IE doesn't like 
	// cooperating with dynamic tables.
	$(sml).addHtml(json);
	
	/*
	$(sml).replace( T('table', { 'id': sq } ) );
	for ( var quote in methods ) {
		var q = methods[quote];
		
		$('shipping_quotes').append( T('tr',
			{ next: T('td',
				{ 'class': 'method', 'colspan': "3", 'content': q.title }
				)
			}
			)
		);

		for ( var m in q.quotes ) {
			var x = q.quotes[m];
			var quote_id = 'quote_' + x.method;
			$(sq).append( T('tr', { id: quote_id} ) );

			// mn = Method Name
			var mn = T('td',
				{ 'class': 'method_name', content: x.method_name }
			);
			
			// mp = Method Price
			var mp = T('td',
				{ 'class': 'method_price', content: '$' + x.price }
			);
			
			// ms = Method Select
			var ms = T('td',
				{ 'class': 'method_select', next: T('input',
					{ type: 'radio', onclick: "saveShippingMethod()", name: 'shipping_method', value: x.method }
					)
				}
			);

			var mph = T('input', {type: 'hidden', id: 'shipping_price_' + x.method, value: x.price } );
			$(quote_id).append(mn);
			$(quote_id).append(mp);
			$(quote_id).append(ms);
			$(quote_id).append(mph);
		}
	}
	*/
	_message('Shipping Method quotes successfully loaded!', 0);
	
	// Global variable to determine if shipping has been calculated
	SHIPPING_FOUND = true;
}

/**
 * Shopping Cart and Line Item Management Functions
*/
/**
 * Updates the quantity of a line item by the product ID. 
*/
function updateQuantity(product_id) {
	var quantity = parseInt($('quantity_' + product_id).value());
	var original_quantity = parseInt($('product_quantity_original_' + product_id).value());
	if ( true == isNaN(quantity) ) {
		quantity = 0;
	}
	
	var delete_item = true;
	if ( 0 == quantity ) {
		delete_item = confirm('Are you sure you want to remove this product from your Shopping Cart?');
	}
	
	if ( true == delete_item ) {
		params = new Object();
		params.action = 'updateproduct';
		params.product_id = product_id;
		params.quantity = quantity;
		
		$('product_quantity_original_' + product_id).setValue(quantity);
		_sendRequest(params, function(json) {
				// Recalculate the total for this line item
				calculateLineItemTotal(product_id, quantity);
				
				// Recalculate the totals for the order
				calculateTotal();
				
				// Recalculate the shipping if all of the information
				// has already been filled out.
				if ( true == SHIPPING_FOUND ) {
					getShipping();
				}
			}
		);
	} else {
		$('quantity_' + product_id).setValue(original_quantity);
	}
}
/**
 * Calculates the total of the order.
*/
function calculateTotal() {
	params = new Object();
	params.action = 'calculatetotal';

	_sendRequest(params, _updateTotals);
}

/**
 * Calculates the line item total (total_price) for a line item.
*/
function calculateLineItemTotal(product_id, quantity) {
	var price = parseFloat( $('product_price_' + product_id).value() );
	var quantity = parseInt(quantity);
	
	$('total_price_' + product_id).addHtml( (price * quantity).toFixed(2) );
	
	if ( 0 == quantity ) {
		$('product_listing_item_' + product_id).style('display', 'none');
	}
}


/**
 * Finalizes the order and ensures the card is successfully charged.
*/
function finalizeOrder(button) {
	hideMessage();
	
	params = new Object();
	params.action = 'saveorder';

	button.disabled = 'disabled';
	button.className = 'large_button_disabled';
	
	_sendRequest(params, function(json) { _saveOrder(json, button); } );
}

function _saveOrder(json, button) {
	var order = nlm.json(json);

	if ( 0 == order.error ) {
		$('shopping_cart_title').style('display', 'none');
		$('shopping_cart_product_list').style('display', 'none');
		$('button_edit_shipping').style('display', 'none');
		$('button_edit_billing').style('display', 'none');
		$('button_finalize').style('display', 'none');
		
		_message('Thank you for your order! Your Order ID is ' + order.order_id, 0);
	} else {
		button.disabled = null;
		button.className = 'large_button';
	
		_message(order.text, 1);
	}
}


/**
 * Callback to write the totals where necessary.
*/
function _updateTotals(json) {
	var total = nlm.json(json);

	$('total_sub').addHtml(total.sub);
	$('total_tax').addHtml(total.tax);
	$('total_shipping').addHtml(total.shipping);
	$('total_total').addHtml(total.total);
	$('total_tax_rate').addHtml(total.tax_rate);
	$('cart_product_listing_subtotal').addHtml(total.sub);
}

/**
 * Sends an HTTP Request.
*/
function _sendRequest(params, callback_func) {
	nlm.httpRequest( {
		url: CART_URL,
		params: params,
		method: 'POST',
		headers: { 'Content-type': 'application/x-www-form-urlencoded' },
		isasync: true,
		isxml: false,
		callback: callback_func
		}
	);
}

/**
 * Validates an email address, loosely based on RFC2882 (I think).
*/
function _validateEmail(email) {
	var email_regex = /([a-z0-9-_.!#$%^&*~`]+)(@[a-z0-9-]+\.[a-z]+)/i;
	var regex = new RegExp(email_regex);

	return regex.test(email);
}
