var upcoming =
{
	// the number of milliseconds between each change
	"delay"		: 7000,

	// the set of upcoming events
	"events"	: [ ],

	// will be set using window.setInterval (to an int representing its interval ID)
	"interval"	: null,

	// number of events to show at once
	"perPage"	: 4,
	
	// this needs to be the negative of "perPage" as it's added to make 0 on initialization
	"offset"	: -4,

	// already preloaded images
	"preloaded"	: { },

	
	// functions
	
	"assignNavHandlers" : function( callback )
	{
		$( function( )
		{
			$( '#bottom_more img[src*="back"]' ).click( upcoming.prevEvents );
			$( '#bottom_more img[src*="more"]' ).click( upcoming.nextEvents );
		} );
		
		if( "function" === typeof callback ){ callback( ); }
	},
	
	"assignRollOvers" : function( jObj )
	{
		// check truthiness (will invalidate an empty set or undefined)
		jObj = jObj || $( document );
		
		jObj.find( 'img[src*="btn_moreinfo"], img[src*="btn_buytickets"]' ).hover(
				
			function( )
			{
				var src	= $( this ).attr( 'src' );
				$( this ).attr( 'src', src.slice( 0, -4 ) + '_ro' + src.slice( -4 ) );
			},
			
			function( )
			{
				var src	= $( this ).attr( 'src' );
				$( this ).attr( 'src', src.slice( 0, -7 ) + src.slice( -4 ) );
			}
		);
	},
	
	"assignStopHandler" : function( callback )
	{
		$( function( )
		{
			$( '#bottom_feature' ).hover( 
				upcoming.stopRotation,
				function( ){ upcoming.startRotation( false ); }
			);
		} );
		
		if( "function" === typeof callback ){ callback( ); }
	},

	"cfcCheck":function( url )
	{
		var cfc = 'http://www.ticketmaster.com/cgi/outsider.plx?CAMEFROM=AEGNLAX_WMAINLAX010107001&GOTO=';
		var pattern = /GOTO=/g;	
		var len = url.length;
		var pos = url.search( 'GOTO=' );
		var newUrl = url;

		if( pos > 0 ){ newUrl = url.slice( pos + 5, len ); }
		if( url.search( 'brand' ) < 0 ){ newUrl += '?brand=nokiala'; }

		return cfc + newUrl;
	}, // end cfcCheck.


	"loadEvents" : function( callback )
	{
		// homogenize callback to function
		if( "function" !== typeof callback ){ callback = function( ){ }; }

		// get the JSON with an XHR
		$.getJSON( 'ajax/event.service.php', { 'type' : 'upcomingList' }, function( data ){ upcoming.events = data; callback( data ); } );
	},
	
	"nextEvents" : function( )
	{
		if( ( upcoming.offset + upcoming.perPage ) >= ( upcoming.events.length - 1 ) )
		{
			// this gets set to 0 in the next line
			upcoming.offset = -upcoming.perPage;
		}
		
		upcoming.offset += upcoming.perPage;

		// show the active page's set of events
		upcoming.showEvents( upcoming.events.slice( upcoming.offset, upcoming.offset + upcoming.perPage ) );
	},

	"preload" : function( )
	{
		for( var i = 0, newIms = [ ], len = arguments.length; i < len; ++i )
		{
			if( ! arguments[ i ] in upcoming.preloaded )
			{
				newIms[ newIms.length ] = new Image;
				newIms[ newIms.length - 1 ].src = arguments[ i ];
				upcoming.preloaded[ arguments[ i ] ] = true;
			}
		}
		delete newIms;
	},
	
	"prevEvents" : function( )
	{
		// special case
		if( 0 === upcoming.offset )
		{
			// this is actually LARGER than the number of events,
			// because of the next line (which we even it out to the last page)
			upcoming.offset = upcoming.events.length + upcoming.events.length % upcoming.perPage;
		}
		
		upcoming.offset -= upcoming.perPage;

		// show the active page's set of events
		upcoming.showEvents( upcoming.events.slice( upcoming.offset, upcoming.offset + upcoming.perPage ) );
	},

	"showEvents" : function( page )
	{
		var	images = [ ],
		
			$featured = $( '#bottom_fader' ),
			
			showNew = function( )
			{
				var	header		= '<span class="upcoming-event">',
					trailer		= '</span>',
					headerLast	= '<span class="upcoming-event last-event">'
			
				for( var spans = [ ], i = 0; i < page.length; ++i )
				{
					spans[ i ] =
						'<a href="' + page[ i ].links.info + '"><img src="' + page[ i ].media + '" /></a>';
						
					if( true === page[ i ].onsale )
					{
						spans[ i ] +=
							'<a class="buy-tickets" href="' + upcoming.cfcCheck( page[ i ].links.ticket ) + '"><img src="images/btn_buytickets.gif" /></a>' +
							'<a href="' + page[ i ].links.info + '"><img src="images/btn_moreinfo.gif" style="clear:left;" /></a>';
					}

					else
					{
						spans[ i ] +=
							'<a href="' + page[ i ].links.info + '"><img src="images/btn_onsalesoon.png" style="clear:left;" /></a>';
					}
					
						
						spans[ i ] += 
							'<h3>' + page[ i ].date + '</h3>' +
							'<a class="event-title" href="' + page[ i ].links.info + '">' + page[ i ].title + '</a>';
					
				}
				
				// OK, so what this does is it takes all but the last item, joins them
				// together with headers and trailer HTML (at this time, <span>),
				// then adds the last item with a special header (at this time,
				// <span class="lastEvent") so we can not put a border on the last item
				$featured.html( header + spans.slice( 0, -1 ).join( trailer + header ) + trailer + headerLast + spans.slice( -1 ) + trailer );
				
				// activate our snazzy rollovers
				upcoming.assignRollOvers( $featured );
				
				// show the #bottom_fader div again now that it's ready
				$featured.animate( { 'opacity' : 1 }, 'slow' );
			};

		// grab the next set of images
		for( var i = 0; i < page.length; ++i ){ images[ images.length ] = page[ i ].media; }

		// preload the images about a second before they need to be there
		upcoming.preload.apply( this, images );

		// if there are spans there, hide them first
		if( $featured.find( 'span' ).length > 0 )
		{
			$featured.animate( { 'opacity' : 0 }, 'slow', showNew );
		}
		
		// just go ahead and show
		else { showNew( ); }
	},
	
	"startRotation" : function( immediate )
	{
		$( function( )
		{
			if( null === upcoming.interval && upcoming.events.length > upcoming.perPage )
			{
				upcoming.interval = window.setInterval( upcoming.nextEvents, upcoming.delay );
			}

			// this homogenizes the argument:immediate to a Boolean
			if( !!immediate ){ upcoming.nextEvents( ); }
		} );
	},

	"stopRotation" : function( )
	{
		window.clearInterval( upcoming.interval );
		upcoming.interval = null;
	}
};
