/**
 * Mini basket
 * Provides a minibasket on the page which provides a visual representation of the basket on the same page as the user
 * The user can add and remove products from the basket without leaving the page
 *
 * Changelog
 * 1.0.0 - 16/06/2008 - Luke Henderson - Initial release
 * 1.0.0 - 06/07/2009 - Kamba Abudu - Added multilanguages
 *
 *
 * @copyright drivebusiness
 * @package miniBasket
 * @class miniBasketClass
 * @version 1.0.0
 */
var miniBasketClass = Class.create({
	/**
	 * Dom elements
	 */
	attached : false,  //Actual DOM element we are attaching to

	/**
	 * Bool
	 */
	template_loaded : false,

	/**
	 * Integer/floats
	 */
	total_price : 0,
	total_price_str : '0.00',
	total_items : 0,

	/**
	 * Strings
	 */
	attached_id : '', //Id of the basket div

	/**
	 * Objects
	 */
	options : {
		mode : 'standard',
		currency : '&pound;',
		currency_js : '\xA3',
		post_url : 'index.php',
		product_add_error : translateObject.translate('Unfortunately there is no stock of this product\n in this size and colour at this time.', 'miniBasket_product_add_error'),
		product_add_error_pod : translateObject.translate('Unfortunately there is no stock of this product\n in this size and colour at this time or check if you have selected any products.', 'miniBasket_product_add_error_pod'),
		product_delete_error : translateObject.translate('We could not delete the product from the basket.\nPlease try again.','miniBasket_product_delete_error'),
		update_items_id : false,
		update_items_text : translateObject.translate('Your basket contains', 'miniBasket_update_items_text') + ' {items} {items_text}',
		update_total_id : false,
		update_total_text : '{currency}{total}',
		items_text_1 : translateObject.translate('item', 'miniBasket_items_text_1'),
		items_text_2 : translateObject.translate('items', 'miniBasket_items_text_2')
	},
	template_options : {
		basket_empty : translateObject.translate('Your basket is empty', 'miniBasket_basket_empty'),
		basket_total : translateObject.translate('Total', 'miniBasket_basket_total') + ': {currency}{total}',
		image_url : base_url + 'images/js/miniBasket/',
		menu_delay_hide : 5
	},
	events : {},


	/**
	 * Arrays
	 */
	products : new Array(),

	/**
	 * @constructor
	 * @param {String} The id of the element we want to add the basket to
	 * @param {Object} An object containing configuration values for the miniBasketClass
	 * @param {Object} An object containing configuration values for the template loaded by the class
	 * @param {Function} Optional - A special update function for this instance
	 */
	initialize : function()
	{
		this.attached_id = arguments[0] || false;
		this.attached = $(this.attached_id);
		//Make sure the container exists
		if(this.attached == false || this.attached == null)
		{
			return ;
		}

		//See if we have provided any overwriting options
		this.products = arguments[1] || new Array();
		Object.extend(this.options, arguments[2] || {});
		Object.extend(this.template_options, arguments[3] || {});

		if ( arguments[4] ) {
			this.options.currency = arguments[4];
			this.template_options.currency = this.options.currency;
		}

		this.call('initialize');

		miniBasketCached();

		//Calculate the basket total
		//this.recalculateBasket();
		//Sometimes the browser reports two loads so make sure we don't load it twice
		this.template_loaded = true;
		this.template = new miniBasketTemplate(this, this.template_options);

		this.updateBasket();

		this.call('loaded');
	},

	/**
	 * Add a product
	 * @param {String} The id of the form we want to submit. To maintain accessibility, we just submit a form so the add product code can be used without JS
	 */
	addProduct : function(form_id)
	{
		var params = {
			ajax : 'yes' //Setup a ajax variable so that the script only outputs what we need
		};
		if ($('related_to')) {
			params.related_to = $('related_to').value;
		}
		var form = $(form_id).request({
			parameters: params,
			onSuccess: this.addedProduct.bindAsEventListener(this)
		});
	},


	/**
	 * Added a product (response from server)
	 * @param {Object} A XMLHTTP response object
	 */
	addedProduct : function(response)
	{
		//Hack: store the response so we can retrieve it later and pass it back into another function here
		this.response = response;
		var xml = response.responseXML;
		this.total_items = this.getNodeValue(xml, 'num_items');
		this.total_price = this.getNodeValue(xml, 'total');
		this.total_price_str = this.getNodeValue(xml, 'total_str');
		this.options.currency = this.getNodeValue(xml, 'currency_symbol');
		this.options.currency_js = this.getNodeValue(xml, 'currency_symbol_js');
		this.options.currency_iso = this.getNodeValue(xml, 'currency_iso');

		//See if we added a product or updated a product
		var result = this.getNodeValue(xml, 'added_product');
		if(result == 'true')
		{
				//if this is kiosk, swap image back in
				if ($('add_to_bag') && $('add_to_bag').hasClassName('kiosk')) {
					var adding_button = $('add_to_bag').childElements()[0];
					adding_button.writeAttribute('src', '/assets/product/pod/button_add_off.gif');
					$('cart').enable();
				};

					if (typeof(instore_pod) != "undefined") {
						var qty_added = this.total_items;
						update_pod_basket(qty_added);
					}

				//Recalculate the basket now we've updated it
				this.recalculateBasket();
		}//End if result == added || result == updated
		else
		{
			if (typeof(instore_pod) == "undefined") {
				alert(this.options.product_add_error);
			}
			else {
				jQuery.facebox('<div style="width: 300px;">' + this.options.product_add_error_pod + '</div>');
			}
		}

		this.call('addProduct');
	},

	/**
	 * Updates basket
	 */
	updateBasket : function()
	{
		var form = new Ajax.Request(base_url + 'basket/', {
			parameters: {
				ajax : 'yes' //Setup a ajax variable so that the script only outputs what we need
			},
			onSuccess: this.updatedBasket.bindAsEventListener(this)
		});
	},

	/**
	 * Update the basket details
	 * @param {Object} A XMLHTTP response object
	 */
	updatedBasket : function(response)
	{

		var xml = response.responseXML;
		this.total_items = this.getNodeValue(xml, 'num_items');
		this.total_price = this.getNodeValue(xml, 'total');
		this.total_price_str = this.getNodeValue(xml, 'total_str');
		this.options.currency = this.getNodeValue(xml, 'currency_symbol');
		this.options.currency_js = this.getNodeValue(xml, 'currency_symbol_js');
		this.options.currency_iso = this.getNodeValue(xml, 'currency_iso');
		runOverlay();
		var username = this.getNodeValue(xml, 'username');
		var email = this.getNodeValue(xml, 'email');
		var telephone = this.getNodeValue(xml, 'tel');
		var mobile = this.getNodeValue(xml, 'mob');

		as_username = username;
		as_email = email;
		as_telephone = telephone;
		as_mobile = mobile;

		$j("#note_user_email").attr("value", as_email);
		$j("input[name='note_user_email']").attr("value", as_email);

		//Recalculate the basket now we've updated it
		this.recalculateBasket();

		this.call('updateProduct');
	},

	/**
	 * Calculates basket related values
	 */
	recalculateBasket : function()
	{

		//If we have to update the "basket has x items"
		if(this.options.update_items_id !== false)
		{
			$(this.options.update_items_id).update(commodityFontString(this.updateLine(this.options.update_items_text)));
		}
		//If we have to update the basket total div
		if(this.options.update_total_id !== false && $(this.options.update_total_id) !== null)
		{
			$(this.options.update_total_id).update(commodityFontString(this.total_price_str));
		}

		this.call('recalculateBasket');
	},

	/**
	 * Takes a string that's expecting dynamic parameters and replaces them with actual values
	 */
	updateLine : function(str)
	{
		str = str.replace(/\{total\}/, this.total_price);
		str = str.replace(/\{currency\}/, this.options.currency);
		str = str.replace(/\{items\}/, this.total_items);
		str = str.replace(/\{items_text\}/, (this.total_items == 1 ? this.options.items_text_1 : this.options.items_text_2));
		this.call('updateLine');
		return str;
	},

	/**
	 * Observe a particular event in the class
	 *
	 * @param {String} Event type to observe (eg addProduct, deleteProduct
	 * @param {Function} Function to call once event has been triggered
	 */
	observe : function(type, func)
	{
		var events_exist = false;
		try{
			eval('events_exist = this.events.' + type + ' ? true : false;');
		}catch(err) {}
		//See if an array of events has been defined, if not create array
		if(!events_exist) {
			eval('this.events.' + type + ' = new Array();');
		}
		eval('this.events.' + type + '.push(func);');
	},

	/**
	 * Call any functions tied to a particular event
	 *
	 * @param {String} Event type to look for and call functions on
	 */
	call : function(type)
	{

		var events_exist = false;
		try{
			eval('events_exist = this.events.' + type + ' ? true : false;');
		}catch(err) {}
		if(!events_exist)
		{
			return;
		}
		eval('var funcs = this.events.' + type + ';');
		//For each of the functions on the event, call and pass in the miniBasket object
		funcs.each(function(item){ item(this); }.bind(this));
	},

	getNodeValue : function(doc, tag) {
		if(doc.getElementsByTagName(tag).length == 0) {
			return '';
	}
		return doc.getElementsByTagName(tag)[0].childNodes[0].nodeValue;
	}
});

function miniBasketCached() {
	if(typeof miniBasket == 'undefined') {
		setTimeout('miniBasketCached();', 100);
		return;
	}
	//Change the static "your shopping bag" text to dynamic "your bag x items" text
	if($j('#primary-nav-bag_left_your').length > 0) {
		var str = '<div id="primary-nav-bag_whole" style="float: left; height: 18px;">'+
		'<a href="/basket/"><span>shopping_bag</span></a>'+
		'</div>'+
		'<div id="primary-nav-bag_number" style="float: left; height: 18px;">'+
		'<a href="/basket/" id="basket_total" style="float: left;"><span class="letter letter-0"><span>0</span></span></a>'+
		'</div>'+
		'<div id="primary-nav-bag_items" style="float: left; height: 18px;">'+
		'<a href="/basket/"><span>items</span></a>'+
		'</div>'+
		'<div id="primary-nav-bag_price" style="float: left; height: 18px;">'+
		'</div>';
		$j('#primary-nav-bag_left_your').replaceWith(str);
	}

	//display the checkout button if there are items in the basket
	//miniBasket.observe('addProduct', productCheckoutImage);
	//miniBasket.observe('updateProduct', productCheckoutImage);
	//miniBasket.observe('deleteProduct', productCheckoutImage);
}
