//Author:       Steve Eidemiller
//Date:         06/27/2010
//Description:  Coupon scroller handler

//NOTE: Many of these functions rely on JavaScript's "function closure" to retain calling parameters for use in
//event handlers and callback functions. Each instance of the function preserves the contents of a different
//instance of the calling parameters, which are needed later when the event/callback triggers.

/*********************************************************************************************************************
Revision History:
00/00/2010 - Who - What
*********************************************************************************************************************/

//TODO: pass in the ID's of the left/right arrow buttons and google map too



//Class definition
function xCouponScrollerClass(containerID, scrollerID, coupons)
{
	//Class properties
	this.containerID     = containerID; //This DOM element should already exist so the new scrollerID element can be inserted into it
	this.scrollerID      = scrollerID;  //This DOM element will be created by this class and should NOT already exist
	this.allCoupons      = coupons;
	this.coupons         = coupons; //This list could be filtered from this.allCoupons (i.e. filtered by metro region)
	this.blockCount      = 7;
	this.blockWidth      = 119;
	this.scrollIncrement = this.blockWidth + 4; //4 = accounts for gaps between coupon blocks
	this.scrollPosition  = -coupons.length * this.scrollIncrement;
	this.currentCoupon   = 0; //Index into this.coupons[]
	this.mouseHover      = false;
	this.animationDelay  = 300; //Milliseconds to "scroll" one coupon
	this.scrollDelay     = 2500; //Milliseconds between auto-scroll events
	this.scrollTimer     = null;
	this.scrollDirection = -1; //Scroll right
	this.mapHandler      = null;

	//Determine the currently "active" coupon index based on the scroll position
	this.getCurrentCouponIndex = function()
	{
		return (-this.scrollPosition / this.scrollIncrement + Math.floor(this.blockCount / 2)) % this.coupons.length;
	};

	//Click() event handler for the left/right arrow buttons
	this.onArrowClick = function()
	{
		var handlerInstance = $(this).data('scrollerClass'); //Class instance
		if (handlerInstance)
		{
			//Scroll the coupon strip
			handlerInstance.scrollDirection = (this.id.toLowerCase().indexOf('left') > -1 ? 1 : -1); //+1 for "left", -1 for "right"
			handlerInstance.scrollNow.call(handlerInstance, handlerInstance.scrollDirection);
		}
	};

	//Mouse is hovering over the map or the scroller strip
	this.onMouseHover = function()
	{
		var handlerInstance = $(this).data('scrollerClass'); //Class instance
		if (handlerInstance)
		{
			handlerInstance.mouseHover = true;
			handlerInstance.autoScrollStop();
		}
	};

	//Mouse is NOT hovering over the map or the scroller strip
	this.onMouseLeave = function()
	{
		var handlerInstance = $(this).data('scrollerClass'); //Class instance
		if (handlerInstance)
		{
			handlerInstance.mouseHover = false;
			handlerInstance.autoScrollStart();
		}
	};

	//Start scrolling automatically
	this.autoScrollStart = function()
	{
		//Stop any automatic scrolling that may be in progress
		this.autoScrollStop();

		//Setup a new scroll timer for the automated scrolling
		var classInstance = this; //For "function closure" on the event handler below, to pass it a reference to the current instance of the class
		this.scrollTimer = window.setInterval( function()
		{
			classInstance.scrollNow.call(classInstance, classInstance.scrollDirection);
		}, this.scrollDelay);
	};

	//Stop any automatic scrolling that may be in progress
	this.autoScrollStop = function()
	{
		if (this.scrollTimer)
		{
			window.clearInterval(this.scrollTimer)
			this.scrollTimer = null;
		}
	};

	//Arrow button handler for the scroller
	this.scrollNow = function(scrollDirection)
	{
		//Finish the current animation immediately
		$('#' + this.scrollerID).stop(true, true);

		//If (we have more than one coupon)...
		if (this.coupons.length > 1)
		{
			//Remove all "active" highlights from all coupons
			$('div.xCouponWrapper.xActive').removeClass('xActive');

			//Determine the new scroller position (left margin CSS offset)
			var minLeft = -this.coupons.length * this.scrollIncrement;
			var left = this.scrollPosition + this.scrollIncrement * scrollDirection;
			if (left < minLeft) //Scroll left, right arrow
			{
				$('#' + this.scrollerID).css('margin-left', '0px');
				left = -this.scrollIncrement;
			}
			else if (left > 0) //Scroll right, left arrow
			{
				$('#' + this.scrollerID).css('margin-left', minLeft + 'px');
				left = minLeft + this.scrollIncrement;
			}

			//Animate from the current position to the new position
			this.scrollPosition = left;
			$('#' + this.scrollerID).animate(
				{
					'margin-left' : this.scrollPosition + 'px'
				},
				{
					'duration' : this.animationDelay,
					'easing'   : 'jswing',
					'complete' : function()
					{
						//Animation is complete
						var handlerInstance = $(this).data('scrollerClass');
						if (handlerInstance) handlerInstance.onScrollComplete(handlerInstance);
					}
				}
			);
		}

		//Determine the resulting current coupon index
		this.currentCoupon = this.getCurrentCouponIndex();
	};

	//Complete() event handler for the left/right scrolling $.animate() method
	this.onScrollComplete = function(handlerInstance)
	{
		//Highlight the current "active" coupon
		$('.xCouponIndex_' + handlerInstance.currentCoupon).addClass('xActive');

		//Sync the map, if there is one
		if (this.mapHandler)
		{
			this.mapHandler.panMap.call(this.mapHandler, handlerInstance.currentCoupon);
		}
	};

	//Setup the scroller with the list of coupons and wire up all the events
	this.initialize = function()
	{
		var html = [];

		//No coupons
		if (this.coupons.length == 0) return;

		//Build the HTML for all the coupon blocks in the scroller
		for (var i = 0; i < this.coupons.length; i++)
		{
			var coupon = this.coupons[i];

			var zipCode = coupon.zip_code;
			if (zipCode != '') zipCode = '<br/>' + zipCode;

			var htmlCoupon = [];
			htmlCoupon.push('<div class="xCouponWrapper xCouponIndex_' + i + '" language="JavaScript" onclick="xShowCouponPopup(' + coupon.id + '); return false;">');
			htmlCoupon.push(    '<div class="xCouponLayout center">');
			htmlCoupon.push(        '<div>' + coupon.banner_image + '</div>');
			htmlCoupon.push(        '<div>' + coupon.image + '</div>');
			htmlCoupon.push(        '<div class="xCouponTitle">' + coupon.title + '</div>');
			htmlCoupon.push(        '<div class="xCouponKeyword">Text "' + coupon.keyword + '" to ' + coupon.short_code + zipCode + '</div>');
			htmlCoupon.push(        '<div class="xCouponBody">' + coupon.body_html + '</div>');
			htmlCoupon.push(    '</div>');
			htmlCoupon.push('</div>');
			html.push(htmlCoupon.join(''));
		}

		//If (we have more than one coupon)...
		if (html.length != 1)
		{
			//Duplicate the coupon HTML array as needed to fill the entire width of the scoller
			while (html.length < this.blockCount)
			{
				html = html.concat(html);
			}

			//Double the size of the coupon strip so that we always have coupon blocks on each side of the scroller "window"
			html = html.concat(html);

			//Wrap the coupon strip with a <div> to contain and position everything
			html.unshift('<div id="' + this.scrollerID + '" style="width: ' + (html.length * 2 * this.scrollIncrement * 2) + 'px; height: 181px; margin-left: ' + this.scrollPosition + 'px;">');
			html.push('</div>');
		}
		else
		{
			//Wrap the coupon strip with a <div> to contain and position everything
			html.unshift('<div id="' + this.scrollerID + '" style="width: ' + (html.length * this.scrollIncrement) + 'px; height: 181px; margin-left: ' + (Math.floor(this.blockCount / 2) * this.scrollIncrement) + 'px;">');
			html.push('</div>');
		}


		//Put the coupon HTML into the scroller element
		$('#' + this.containerID).html(html.join(''));
		$('#' + this.scrollerID).data('scrollerClass', this); //Store an object reference to this class instance

		//Determine the current coupon index and make that coupon "active"
		this.currentCoupon = this.getCurrentCouponIndex();
		$('.xCouponIndex_' + this.currentCoupon).addClass('xActive');

		//Wire up "hover" detection to stop automatic scrolling when the mouse is over the scroller or map
		var jqSelector = '#' + this.scrollerID + ', #' + this.containerID + ', #xGoogleMap';
		$(jqSelector).data('scrollerClass', this); //Store an object reference to this class instance
		$(jqSelector).hover(this.onMouseHover, this.onMouseLeave);

		//Left/Right arrow button handlers for the scroller
		var jqSelector = '#xCouponStripArrowLeft, #xCouponStripArrowRight';
		$(jqSelector).data('scrollerClass', this); //Store an object reference to this class instance
		$(jqSelector).click(this.onArrowClick);
		$(jqSelector).hover(this.onMouseHover, this.onMouseLeave);

		//Scroll automatically at periodic intervals
		this.autoScrollStart();
	};

	//Rebuild the scroller so it's filtered by a specific metro region
	this.filterByMetroRegion = function(regionIndex)
	{
		//Stop any scrolling that might be in progress
		this.autoScrollStop();

		//Remove the event handlers
		var jqSelector = '#' + this.scrollerID + ', #' + this.containerID + ', #xGoogleMap, #xCouponStripArrowLeft, #xCouponStripArrowRight';
		$(jqSelector).unbind();

		//Destroy the existing coupon strip
		$('#' + this.containerID).html('');

		//Build the list of filtered coupons
		var couponsFiltered = [];
		if (regionIndex == -1)
		{
			//Show all coupons
			couponsFiltered = this.allCoupons;
		}
		else
		{
			//Filter the list of coupons by the selected metro region
			var r = xMapRegions[regionIndex];
			for (var i = 0; i < this.allCoupons.length; i++) //For (each coupon)...
			{
				var coupon = this.allCoupons[i];
				if (coupon.is_nationwide)
				{
					//Allow nationwide coupons in every region
					couponsFiltered.push(coupon);
				}
				else
				{
					//For (each region in the specified metro area)...
					for (var j = 0; j < r.regions.length; j++)
					{
						var region = r.regions[j];
						if (coupon.latitude >= region.lat1 && coupon.latitude <= region.lat2 && coupon.longitude >= region.lng1 && coupon.longitude <= region.lng2)
						{
							couponsFiltered.push(coupon);
							break; //Stop looping so we don't add the same coupon multiple times if it's in multiple overlapping regions
						}
					}
				}
			}
		}

		//
		this.coupons = couponsFiltered;
		this.scrollPosition  = -this.coupons.length * this.scrollIncrement;
		this.initialize();
	};

	//Initialize the class instance
	this.initialize();
}

