
//------------------------------
// concierge script namespace
//------------------------------

C.SL = Class.create( C.BaseAjax , {
	
	initialize: function()
	{
		this.ajaxBase = "/index.php?action=ajax,shoppinglist";
		this.printListUrl = "/index.php?action=bloom,shoppinglist_print";
		this.pager = new C.Pager({targetEl:'c-search-pager', renderOnClick:false, maxContinuousPages:7, callbackFn: this.onPageChange.bind(this)});
		this.currentPage = 1;
		this.listItems = [];
		this.cache = {};
		this.popupWin = false; // the Window object
		this.mockCartId = 0;
		this.activeCartId = 0;
		this.removeIcon = false;
		this.removeIconOver = false;
		this.popupAddToCartProgressSpinner = false;
		this.addInProgress = false;
		this.loadingIndicator = false;
		this.removeIconHideTimeout = false;
	},
	
	
	/**
	 * search ajax callback
	 */
	searchCB : function(transport)
	{
		var result = this.evalJSON(transport);
		if ( result == "no_results" ) 	this.searchResults = false;
		else this.searchResults = result;
		
		this.onSearchComplete();

	},
	
	
	/**
	 * ajax callback called when page count is returned.
	 */
	pageCountCB : function(transport)
	{
		var rs = this.evalJSON(transport);	

/*
		if ( rs.count <= 1 )
		{
			this.pager.hide();
			return;
		}
	*/	
		this.pageCount = rs.count;
		this.pager.start = 1;
		this.pager.end = this.pageCount ;
		this.pager.current = this.currentPage ;
		this.pager.render();			
	},

	
	
	/**
	 * initializes web UI, adding various event handlers and dynamically 
	 * creates UI elements
	 */
	setupUI : function()
	{
	
		Event.observe($('c-search-panel-kw'),'keypress', this.handleSearchInputKeyPress.bind(this) ); 

		this.loader = new Element("div").update("<img src='/images/brand/bloom/ui/loader.gif'> searching...");
//		$(document.body).insert(this.loader);
		
		$('c-search-pager').insert(this.loader);
		this.loader.hide();
		
		var self = this;
		
		this.removeIcon = new Element('div');
		this.removeIcon.addClassName("c-cart-remove-icon");
		this.removeIcon.setStyle( { position:'absolute',zIndex:30 });
		this.removeIcon.observe("click", this.uiCartRemoveIconClick.bind(this) );
		this.removeIcon.observe("mouseover", function(){
			clearTimeout(self.removeIconHideTimeout);
		});		
		
		
		$('c-shoppinglist-items').observe('click', this.onShoppingListClick.bind(this));
		
		this.removeIcon.hide();
		$('c-shoppinglist-items').insert(this.removeIcon);

	},
	
	handleSearchInputKeyPress : function(evt)
	{
		if ( evt.keyCode != 13 ) return;
		var kw = $F('c-search-panel-kw');
		$('c-search-panel-kw').blur();
		this.doSearch(kw,1);
	},
	
	doSearch : function(kw,page)
	{
		if (!page || page == 1)
		{
			page = 1;			
			// invoke ajax WS to find out how many pages there are in this query
			// -----------------------------------------------------------------
			this.doAjax( { onSuccess: this.pageCountCB.bind(this) } , { 'op':'productCount','kw':kw} );			
		}
		//$('c-search-pager').update("").insert(this.loader);
		this.pager.hide();
		this.loader.show();
		this.doAjax( { onSuccess: this.searchCB.bind(this) } , { 'op':'productSearch','kw':kw ,'pg':page} );
	},
	
	
	
	onPageChange : function(p)
	{
		var kw = $F('c-search-panel-kw');
		this.doSearch(kw,p);
	},
	
	onSearchComplete : function()
	{
		var sri = $('c-search-results-items').update("");
		var sriList = $('c-search-list-results').update("");

		this.loader.hide();		
		
		if ( !this.searchResults )
		{
			sri.update("Your search did not return any results.");
			return;
		}
		
		this.pager.show();



		this.searchResults.each( function(e,idx)
		{
			var item = new Element('div');
			var descLine =  (e.brand ? e.brand : "") +" " + (e.name ? e.name : e.description);
			
			descLine = truncateStr( descLine, 60 ) + "...";
			
			var imgSrc;
			if ( !e.image ) imgSrc = '/images/brand/bloom/ui/shopping/no_image_product_web.gif';
			else  imgSrc = C.WS_IMAGES + "/product/"+e.image;
			
			
			item.addClassName('product-item-image');
			item.update(
				"<div class='i-img' onclick=\"_sl.showDetailsPopup( {pid:'"+e.productCode+"' , source:this} );\"><img src='" +imgSrc+"'></div>"+
				"<div class='i-desc'>"+ descLine  + "</div>"+
				"<div class='i-size'>"+ makeBlank(e.size) +" " + makeBlank(e.uom) +
				" [<a href='#' onclick=\"_sl.addToCart('"+e.productCode+"',1);return false\">add</a>] "+
				"</div>"				
				);
			sri.insert(item);

//			new Draggable(item, {revert:true} );			
			
			item = new Element('div');
			item.addClassName('list-result');
			if ( idx % 2 == 0 ) item.addClassName("oddrow");
			item.update(e.description);
			item.writeAttribute( {pid:e.productCode} );
			var wrap = item.wrap( 'div', { 'class':'list-item-wrapper'} );
			sriList.insert(wrap);

			
			
			if ( !this.cache[ item.productCode ] ) this.cache[ e.productCode ] = e;
			

		}.bind(this))	
		
		//$('c-search-footer').setStyle( {display:'block'} );
		
	},
	

	

	
	// --------------------------------	
	// cart functions 
	// --------------------------------
	
	/**
	 * loads the active user's cart and update the sohpping list.
	 * this function is also used as a callback for the Ajax request
	 * @param obj an ID numb
	 */
	loadCart : function( obj )
	{
	
		// reset cart items
		// ----------------
		//this.cartItems = [];
		
		if (!obj)
		{
			this.doAjax( { onSuccess: this.loadCart.bind(this) } , { 'op':'getShoppingList'} );	
		}
		else if ( obj.transport )
		{
			jsonObj = this.evalJSON(obj.transport);
			this.activeCartId = jsonObj.id;
			this.cartItems = jsonObj.items;
			this.cartItems.sort( sortByDateAdded );
			this.redrawCart();
		}
	},
	
	/**
	 * invokes AJAX -> WS which adds an item to the cart. 
	 * @param {Object} pid productID or 'active' to use PID of item in popup
	 * @param {Object} qty
	 */
	addToCart : function(pid,qty)
	{
		if ( this.addInProgress ) return;
		else this.addInProgress = true;
		
		if ( !this.activeCartId )
		{
			alert("No active shopping list.");
			return;
		}
		
		if ( pid == 'active' )
		{
			pid = this.activePID;
			this.popupAddToCartProgressSpinner.show();			
//			var count = this.getQuantityInList(pid);
			//this.setQuantityInList(pid,count+1);
			//
						
		} 
		
		
		var self=this;

		this.doAjax( {onSuccess: function(){ self.loadCart() } } , { 
			'op':'addToCart',
			'pid':pid,
			'lid':this.activeCartId,
			'qty':qty
			});
	},
	
	/**
	 * callback invoked by server-side ajax controller when an item has been
	 * successfully added to the user's cart.
	 * @param {Object} pid
	 * @param {Object} neqQty
	 */
	itemAddedToCart : function( pid , newQty )
	{
		
		//console.log("added",pid,newQty );
		if ( this.popupAddToCartProgressSpinner )	this.popupAddToCartProgressSpinner.hide();
		this.uiUpdatePopupListCount(newQty);
		
		this.addInProgress = false;
	},
	
	
	/**
	 * callback handler for when the user selects the 'organize by' dropdown
	 */
	sortShoppingList : function(e)
	{
		if ( !this.cartItems || this.cartItems.length == 0) return;
		var predicate = false;
		switch(e)
		{
			case "Store section": predicate = sortByCategory; break;
			case "My order": predicate = sortByDateAdded; break;
			case "Alphabetical": predicate = sortByTitle; break;
		}
		this.cartItems.sort( predicate );
		this.redrawCart();
		
	},
	
	
	/**
	 * returns the number of items in the user's current cart for the given pid
	 * @param {Object} pid product code
	 */
	getQuantityInList : function( pid )
	{
		var count = 0;
		if ( this.cartItems )
		this.cartItems.each( function(item){
			if(item.productCode != pid ) return true;
			count = item.quantityDesired - item.quantityPurchased;
		});
		return count;
	},
	
	
	/**
	 * sets the number of items in the cart for the given pid.  this does
	 * not update the server-side model, and should only be to help update
	 * the UI pre-emptively 
	 */
	setQuantityInList : function( pid , count )
	{
		//console.log(this.cartItems);
		var updated = false;
		if ( this.cartItems )
		this.cartItems.each( function(item){
			if(item.productCode != pid ) return true;
			item.quantityDesired = count;
			updated = true;
		});
		 
		// if the item wasn't in the cart, make a stub which contains
		// the count.  this is needed so that the UI can still update if
		// the user spams an action which triggers the adding of items  
		if (!updated) this.cartItems = [ {productCode:pid,quantityDesired:count, quantityPurchased:0}];
	},

		
		
	onShoppingListClick : function(evt)
	{
		var src = Event.element(evt);
		if ( src.hasClassName('c-shoppinglist-item') || src.hasClassName('c-shoppinglist-item-odd') )
		{
			var pid = src.readAttribute('pid');
			this.showDetailsPopup( { pid:pid} );
		}
	},		
	
	redrawCart : function()
	{

		this.removeIcon.remove();
		var cart = $('c-shoppinglist-items');
		cart.update("");
		this.cartItems.each( function(e,idx){
			if (e.quantityDesired > 0) 
			{
				var itemEl = new Element('div');
				itemEl.addClassName('c-shoppinglist-item' + (idx % 2 == 0 ? "" : "-odd"));
				itemEl.update( (e.brand ? e.brand : "") + " " + (e.name ? e.name : e.description) + (e.quantityDesired > 1 ? " <span class='qty'>(x" +e.quantityDesired+")</span>" : "") );
				itemEl.observe('mouseover', this.uiCartItemOver.bindAsEventListener(this, e, itemEl));
				itemEl.observe('mouseout', this.uiCartItemOut.bind(this));
				itemEl.writeAttribute('pid',e.productCode);
				cart.insert(itemEl);
			}
		}.bind(this));
		this.removeIcon.hide();		
		cart.insert(this.removeIcon);
	},
	
	
	//--------------------------
	// UI handlers
	//----------------------------
	uiCartItemOver : function(evt,e,itemDiv)
	{
		this.cartItemOver = true;
		this.cartItemOverId = e.productCode;
		var offset = itemDiv.positionedOffset();
		this.removeIcon.setStyle( {"top": offset[1] +6+ "px" , "left" : offset[0] +2+ "px" } );
		this.removeIcon.show();		
	},	
	
	uiCartItemOut : function(evt, action )
	{
//		if (evt) 
//		{
//			var evtSrc = Event.element(evt);
//			console.log(evtSrc);
//			if ( evtSrc.hasClassName('c-cart-remove-icon') ) return;
//		}		
		
		if ( !action )
		{
			this.cartItemOver = false;						
			this.removeIconHideTimeout = this.uiCartItemOut.bind(this).delay(0.2,false,'hide');		
		}else if(action == 'hide')
		{
			if ( this.cartItemOver ) return;
			this.cartItemOver = false;
			if ( this.removeIconOver ) return;
			this.removeIcon.hide();		
		}
	},
	
	uiCartRemoveIconClick : function(evt)
	{
		var self=this;
		this.doAjax( {onSuccess: function(){ self.loadCart() } } , { 
			'op':'removeFromCart',
			'pid':this.cartItemOverId,
			'lid':this.activeCartId
			});
	},

	/**
	 * finds out how many items are in the cart for the given PID, then 
	 * increments the value by 1 and updates the popup UI to either show
	 * the list count (if the number is 1) or update the existing count.
	 * @param {Object} pid
	 */
	uiUpdatePopupListCount : function(count)
	{

/*		
		if ( count == 0 )
		{
			$$('.c-infowin-listcount-icon')[0].hide();
			$$('.c-infowin-listcount')[0].hide();	
		}
		else
		{*/
			$$('.c-infowin-listcount-icon')[0].show();
			$$('.c-infowin-listcount')[0].show();
			$$('.c-infowin-listcount')[0].update("x"+count);
	//	}
	},

	//---------------------
	// view toggling ( list | details )
	//---------------------
	
	/**
	 * changes the view, resulting in various UI elements being turned on/off.
	 * @param {string} v 'list' or 'details'
	 */
	setView : function(v)
	{
		if( v == this.uiView ) return;
		else this.uiView = v;
		
		switch(v)
		{
			case "list":
				$('b-toggle-details').removeClassName('c-toggle-details-on');
				$('b-toggle-list').addClassName('c-toggle-list-on');				
				$('c-search-results-items').hide();
				$('c-search-listview-panel').show();
				
				break;
			
			case "details":
				$('b-toggle-details').addClassName('c-toggle-details-on');
				$('b-toggle-list').removeClassName('c-toggle-list-on');				
				$('c-search-results-items').show();
				$('c-search-listview-panel').hide();
				break;
		}
	},

	
	//--------------------
	// popup window
	//----------------------	
	
	/**
	 * fetches full product info from server and calls renderPopup when the data 
	 * is availabled/returned.
	 *
	 * this function operates in two modes depending on the cfg param.  If cfg is an id,
	 * an ajax request is sent to the server with instructions to use this method as the callback;
	 * if cfg has a transport property (cfg.transport) then this method assumes it is operating
	 * in 'callback' mode.
	 */
	showDetailsPopup : function( cfg )
	{
		if ( cfg.transport )
		{
			var productDetails = this.evalJSON(cfg.transport);
			var pid = productDetails.productCode;
			Object.extend(this.cache[pid],productDetails);
			this.activePID = pid;
			this.renderPopup(pid);
			if ( this.loadingIndicator ) this.loadingIndicator.hide();
			
		}
		else if ( cfg.pid )
		{
			// try and find the item clicked, and put a loading indicator on it
			// ----------------------------------------------------------------
			var target = cfg.source;
			if ( !target  )target = $$('div[pcd='+cfg.pid+']')[0];
			

			
			if ( target ) this.loadingIndicator.show( {centerOn: target});
			this.doAjax( { onSuccess: this.showDetailsPopup.bind(this) } , { 'op':'productDetails','pid':cfg.pid} );
		}
	},
	
	renderPopup : function( pid )
	{
		var win = this.popupWin;
	
		if (!win)
		{
//			win = new Window({className: "c-window",  zIndex:100, width:"730px",  destroyOnClose: false, recenterAuto:false, showEffectOptions: { delay:0.3 }});
			win = new Window({className: "c-window",  zIndex:100, height:"670px",width:"730px",  destroyOnClose: false, recenterAuto:false, showEffectOptions:{duration:0.3}, showEffect: Element.show , hideEffect: Element.hide});
			win.getContent().update( $('win-tpl').innerHTML  );
			$('win-tpl').remove();
			$('c-infowin-close').observe('click',this.closePopup.bind(this));
			this.popupWin = win;
		}
		
		var winId = win.getId();
		var winContentElId = winId + "_content";
		var winEl = $(winContentElId);
		
		
		// replace template elements with data
		// -----------------------------------
		
		var data = this.cache[pid];
		
		try 
		{
			
			if ( ! this.popupAddToCartProgressSpinner )
			{
				this.popupAddToCartProgressSpinner = winEl.down('.c-infowin-listcount-spinner');				
			} 
			
			this.popupAddToCartProgressSpinner.hide();
			
			winEl.down('.c-infowin-addtofav').hide();
			winEl.down('.c-infowin-recipe-stats').hide();
			winEl.down('.c-infowin-title').update(data.description);
			winEl.down('.c-infowin-details').update(truncateStr(data.details, 400));
			winEl.down('.c-infowin-listcount-spinner').hide();

			winEl.down('.c-infowin-img').replace("<img class='c-infowin-img' src='"+data.imageLarge+"' />");
/*
			winEl.down('.c-infowin-img').writeAttribute({
				'src': data.imageLarge
			});
	*/		
			winEl.down("#b_print_version").hide();
			
			$('rtab-ingredients-content').update(data.ingredients);
			$('rtab-nutrition-content').update(data.nutrition);
			
			// update listcount icon and count
			// --------------------------------
			var listCount = this.getQuantityInList( pid );
			this.uiUpdatePopupListCount(listCount);
			
			// reposition window's Y-pos if client is scrolled to top.
			// -------------------------------------------------------	
			var scrollDim = WindowUtilities.getWindowScroll();
			var topOffset = false;
			if (scrollDim.top < 240) topOffset = 240 - scrollDim.top;
			
			win.showCenter(true, topOffset);
			$(this.popupWin.getId()).setStyle({
				width: "730px"
			})
		}
		catch(e)
		{
			console.log(e);
			console.trace();
		}
	},
	
	
	/**
	 * closes Recipe popup window
	 */
	closePopup : function()
	{
			this.popupWin.close();
	},
	
	
	
	openPrintableList: function()
	{
		var h = 500; var w = 520
		var x = (screen.width / 2) - (w/2);
		var y = (screen.height/ 2) - (h/2) - 100;	
		var win = window.open( this.printListUrl ,'print_version','width='+w+',height='+h+',scrollbars=yes,menubar=yes,screenx=' + x + ',screeny=' + y );
		win.focus();
	}

	
	
	
	
});

// util functions


function sortByCategory(a,b)
{
	if ( a.category == b.category ) return 0;
	else return  a.category > b.category ? 1 : -1;
}

function sortByTitle(a,b)
{
	if ( a.brand == b.brand) return 0;
	else return  a.brand > b.brand ? 1 : -1;
}

function sortByDateAdded(a,b)
{

	return a.orderIdx - b.orderIdx;
}


function truncateStr( str, len )
{
	if ( !str ) return "";
	var trunc = str.substring(0, len);
	trunc = trunc.replace(/\w+$/, '');	
	trunc = trunc.replace(/(\w+)$/,'<span style="white-space:nowrap">$1...</span>');
	return trunc;
}


function makeBlank(s)
{
	return s ? s : "";
}

var _sl = new C.SL();


Event.observe(window,'load',function(){
	_sl.loadCart();	
	_sl.setView('details');	
})


