nfl.namespace('events');
nfl.events.VideoListEvent = {
	FILTER_CHANGE: 'videolist:filterchange',
	VIDEOS:        'videolist:videos',
	PAGE_CHANGE:   'videolist:pagechange'
};
nfl.events.VideoPlayerEvent = {
	INITIALIZED:       'videoplayer:initialized',
	AVAILABLE:         'videoplayer:available',
	READY_TO_PLAY:     'videoplayer:readytoplay',
	UNAVAILABLE:       'videoplayer:unavailable',
	AD_START:          'videoplayer:adStart',
	AD_COMPLETE:       'videoplayer:adComplete',
	AD_LOADED:         'videoplayer:adLoaded',
	PRE_ROLL_START:    'videoplayer:preRollStart',
	PRE_ROLL_COMPLETE: 'videoplayer:preRollComplete',
	PLAY:              'videoplayer:play',
	PAUSE:             'videoplayer:pause',
	POST_ROLL_START:   'videoplayer:postRollStart',
	PLAYBACK_COMPLETE: 'videoplayer:playbackComplete',
	RESTART:           'videoplayer:restart',
	ADD_TO_FAVORITES:  'videoplayer:addToFavorites'
};
nfl.namespace('videos');
(function () {
	var ESCAPED_DELIMITER = /#%7B([^%]+)%7D/g,
	    VideoListEvent    = nfl.events.VideoListEvent,
	    VideoPlayerEvent  = nfl.events.VideoPlayerEvent,
	    CLASS_NAME = {
			CURRENT: 'current',
			PREVIOUS: 'previous',
			NEXT: 'next',
			PAGE: 'page',
			INIT: 'initialized'
		},
	    FILTER_RE           = /^filter\-([^\-]*)/,
	    DEFAULT_THUMB_IMAGE = {
			small:     nfl.global.imagepath + '/img/video/poster-frames/poster-frame-80x60.jpg',
			"x-small": nfl.global.imagepath + '/img/video/poster-frames/poster-frame-60x45.jpg'
		},
	    IS_TIFF             = /\.tiff?$/;
	
	function isBadImage ( _url ) {
		return _url.blank() || IS_TIFF.test( _url );
	}
	
	function onVideoListEvent ( _e ) {
		console.log( _e.eventName, $H(_e.memo).inspect() );
	}
	
	function getFilterParamName( _id ) {
		var m = _id.match( FILTER_RE );
		if ( ! m ) { throw new Error("Could not create paramName from '" + _id + "'"); }
		return m[1]; 
	}
	
	function templatize(ref) {
		var el, t;
		el = $(ref);
		if ( ! el ) {
			throw new Error( 'Could not templatize "' + ref + '"');
		}
		t = new Template(el.innerHTML.replace(ESCAPED_DELIMITER, "#{$1}"));
		el.update('');
		el.hide();
		return t; 
	}
	
	// Helper functions for converting query strings to hash strings
	/*
	function hashToHashparamsArray( pair ) {
		return encodeURIComponent( pair.key ) + ':' + encodeURIComponent( pair.value );
	}
	function removePreQueryHref ( _s ) {
		return _s.substring( _s.indexOf('?'), _s.length );
	}
	
	function objectToHashparams ( _o ) {
		return '#' + $H( _o ).map(hashToHashparamsArray).join('/');
	}
	*/

	// Log video list events
	$H(VideoListEvent).each(function( _pair ) { document.observe( _pair.value, onVideoListEvent ); });
	
	nfl.videos = {
		// Is this really necessary?
		InitializeHeaderIE6: (function () {
			function onResize ( _evt ) {
				if (!window.XMLHttpRequest && document.all) { // this is only needed for IE6
					var viewportWidth = document.viewport.getWidth();
					$('hd').style.width = viewportWidth + " px";
				}
			}
			return function() {
				Event.observe(document.onresize ? document : window, "resize", onResize);
				onResize();
			};
		}()),
		InitializeVideoSearch: (function () {
			var ID, label, input, notBlank;
	
			ID = {
				INPUT: 'hd-video-search-input',
				LABEL: 'hd-video-search-label'
			};
			notBlank = /\S/;
	
			function onInputFocus ( _evt ) {
				label.hide();
			}
			function onInputBlur ( _evt ) {
				if ( notBlank.test( input.value ) ) { return; }
				input.value = '';
				label.show();
			}
			return function() {
				input = $(ID.INPUT);
				label = $(ID.LABEL);
				if ( ! ( input && label )  ) { return; }

				input.observe('focus', onInputFocus ); 
				input.observe('blur', onInputBlur );
				if ( input.value ) {
					onInputFocus();
				}
				else {
					onInputBlur();
				}
			};
		}()),
		VideoNavigation: (function () {
			var ID, ATTR, CSS, sexy = false;
	
			ID = {
				CONTAINER: 'video-nv-main'
			};
			ATTR = {
				ORIGINAL_HEIGHT: 'data-oheight'
			};
			CSS = {
				CONTENT: 'div.channel-content',
				GROUP: 'li.video-nv-group',
				SHADOW: 'shadow',
				PREPARED: 'prepared'
			};
	
			function prepareChannel ( _el ) {
				var group, iframe, newStyle, oHeight, div;
		
				newStyle  = { display: 'none' };
				
				group    = _el.up( 'li' );
				group.channels = _el;

				oHeight = _el.offsetHeight - parseFloat( _el.getStyle('paddingBottom') ) - parseFloat( _el.getStyle('paddingTop') );
				_el.setAttribute( ATTR.ORIGINAL_HEIGHT, oHeight + 'px' );
				_el.addClassName( CSS.PREPARED );
				
				// Fixes select see-through in IE6
				if ( Prototype.Browser.IE ) {
					iframe    = document.createElement( 'iframe' );
					iframe.id = "DivShim";
					iframe.setAttribute("scrolling","no");
					iframe.setAttribute("frameborder","0");
					_el.insertBefore( iframe, _el.firstChild );
				}
				
				div = document.createElement('div');
				div.className = CSS.SHADOW;
				_el.appendChild( div );

				if ( sexy ) {
					newStyle.backgroundPosition = '0 ' + oHeight + 'px';
					newStyle.height = '0px';
				}
				_el.setStyle( newStyle );
			}
			function onMouseOver ( _e ) {
				var group, from, channels;
				_e.stop();
		
				group    = _e.findElement( CSS.GROUP );
				if ( ! group ) { return; }
				channels = group.channels;
				from     = $( _e.relatedTarget || _e.fromElement );

				if ( (! channels) || (! from) || ( from && from.descendantOf && from.descendantOf( group ) ) ) { return; }
		
				if ( sexy ) {
					if ( channels.transitionEffect ) {
						channels.transitionEffect.cancel();
					}
					channels.transitionEffect = new Effect.Morph( channels, {
						style: { height: channels.getAttribute( ATTR.ORIGINAL_HEIGHT ) },
						duration: 0.5,
						beforeStart: function() { channels.show(); channels.setStyle({ zIndex: 1000 }); },
						afterFinish: function() { channels.transitionEffect = null; channels.setStyle({ zIndex: 1000 }); }
					});
				}
				else {
					channels.show();
				}
			}
			function onMouseOut ( _e ) {
				var group, to, channels;

				_e.stop();
		
				group    = _e.findElement( CSS.GROUP );
				if ( ! group ) { return; }
				channels = group.channels;
				to       = $( _e.relatedTarget || _e.toElement );
		
				if ( (! channels) || ( to  && ( to === group || ( to.descendantOf && to.descendantOf( group ) ) ) ) ) { return; }
		
				if ( sexy ) {
					if ( channels.transitionEffect ) {
						channels.transitionEffect.cancel();
					}
					channels.transitionEffect = new Effect.Morph( channels, {
						style: { height: '0px' },
						duration: 0.5,
						afterFinish: function() { channels.hide(); channels.transitionEffect = null; }
					});
				}
				else {
					channels.hide();
				}
			}
			
			return {
				initialize: function() {
					var el = $(ID.CONTAINER);
					if ( ! el ) { return; }
	
					// If we have scriptaculous, go the extra mile
					if ( Effect ) { sexy = true; }
			
					el.observe('mouseover', onMouseOver );
					el.observe('mouseout', onMouseOut );
					el.select( CSS.CONTENT ).each( prepareChannel );
				},
				setAnimation: function( _value ) {
					if ( sexy === _value ) { return; }
					sexy = _value;
					$$('#' + ID.CONTAINER + ' ' + CSS.CONTENT).each(
						_value ? function( _el ) {
							_el.setStyle({ backgroundPosition: '0 ' + _el.getAttribute( ATTR.ORIGINAL_HEIGHT ) + 'px', height: '0px', paddingBottom: null });
							_el.addClassName( CSS.PREPARED );
						} : function( _el ) {
							_el.setStyle({ backgroundPosition: 'left top', height: 'auto', paddingBottom: '0px' });
							_el.removeClassName( CSS.PREPARED );
						});
				}
			};
		}()),
		FilterByLinks: (function() {
			var COMPONENT       = "nfl.videos.FilterByLinks";

			function onClick ( _e ) {
				var target, value;
				_e.stop();
				target = _e.findElement('a');
				if ( (! target ) || target === document || Element.hasClassName( target, CLASS_NAME.CURRENT ) ) { return; }
				value  = target.href.match( this.valueRE )[1];
				this.setFilterValue( value );
				document.fire( VideoListEvent.FILTER_CHANGE, { component: this.name, filters: nfl.videos.FilterSets.getValue() });
				
			}
			
			function updateHref( _param, _hash ) {
				return function( _obj ) {
					_hash.set( _param, _obj.key );
					$( _obj.id ).href = '?' + _hash.toQueryString(); 
				};
			}
			
			function updateLinks ( _e ) {
				if ( _e.memo.component === this.name ) { return; }
				this.values.each( updateHref( this.paramName, _e.memo.filters.clone() ) );
			}
			
			return Class.create({
				initialize: function( _options ) {
					var el, re;

					el                = $(_options.el);
					if ( ! el ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + el );
					}
					this.id           = el.identify();
					this.defaultValue = _options.defaultValue;
					this.name         = COMPONENT + '#' + this.id;
					this.paramName    = getFilterParamName( this.id );
					this.valueRE = re = new RegExp( "\\?(?:.+&)?" + this.paramName + "=([^&]*)" );
					this.values       = el.select('a').collect( function( _a ) {
						var id, match = _a.href.match( re );
						if ( match ) {
							id = _a.identify();
							return { id: id, key: match[1], value: _a.innerHTML.strip() };
						}
					} );
					el.observe( 'click', onClick.bindAsEventListener(this) );
					document.observe( VideoListEvent.FILTER_CHANGE, updateLinks.bindAsEventListener(this) );
				},
				getFilterValue: function() {
					return $$( '#' + this.id + ' .' + CLASS_NAME.CURRENT ).first().href.match( this.valueRE )[1];
				},
				__findFilterValue: function( _value ) {
					return this.values.find( this.__valueFinder( _value ) );
				},
				__hasFilterValue: function( _value ) {
					return this.values.any( this.__valueFinder( _value ) );
				},
				isLegalValue: function( _value ) {
					return this.__hasFilterValue( _value );
				},
				setFilterValue: function( _value, _ignoreFilterChange ) {
					var current;

					this.value  = _value;
					current     = $( this.__findFilterValue( _value ).id );
					current.addClassName( CLASS_NAME.CURRENT );
					current.siblings().invoke('removeClassName', CLASS_NAME.CURRENT );
				},
				__valueFinder: function( _value ) {
					return function( _obj ) {
						return _obj.key === _value;
					};
				}
			});
		}()),
		FilterBySelect: (function() {
			var COMPONENT = "nfl.videos.FilterBySelect";
			
			function onSubmit (_e) {
				var value;
				
				_e.stop();
				value = $F( this.select );
				document.fire( VideoListEvent.FILTER_CHANGE, { component: this.name, filters: nfl.videos.FilterSets.getValue() });
			}
			return Class.create({
				initialize: function( _options ) {
					var form;
					
					form              = $(_options.el);
					if ( ! _options.el ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + _options.el );
					}
					this.id           = form.identify();
					this.select       = form.select('select').first().identify();
					this.name         = COMPONENT + '#' + this.id;
					this.defaultValue = _options.defaultValue;
					this.paramName    = getFilterParamName( this.id );

					this.setFilterValue( this.defaultValue );
					form.observe( 'submit', onSubmit.bindAsEventListener(this) );
				},
				isLegalValue: function( _value ) {
					return $$('#' + this.select + ' option[value=' + _value + ']').length > 0;
				},
				getFilterValue: function() {
					return $(this.select).value;
				},
				setFilterValue: function( _value, _ignoreFilterChange ) {
					var s;
					s               = $(this.select);
					this.value      = _value;
					s.selectedIndex = s.select('option[value=' + _value + ']').first().index;
				}
			});
		}()),
		FilterBySortType: (function () {
			var COMPONENT     = 'nfl.videos.FilterByWeek',
			    FILTER_RE     = /#/,
			    CURRENT_CLASS = 'current',
			    CURRENT_CSS   = 'li.' + CURRENT_CLASS;
			
			function onMouseOver( _e ) {
				var li, div, relTarg;

				_e.stop();
				li = _e.findElement('li');
				relTarg = $(_e.relatedTarget || _e.fromElement);

				// We have an LI,
				// and out LI is a direct parent of our div,
				// and we have options
				// and we're coming from somewhere else
				if ( li && li.up().id === this.id &&
					( div = li.select('div.options').first() ) &&
					(
						(relTarg && ! relTarg.descendantOf( li )) ||
						(! relTarg)
					)
				) {
					div.setStyle({ height: null });
				}
			}
			
			function onMouseOut( _e ) {
				var li, div, relTarg;

				_e.stop();
				li = _e.findElement('li');
				relTarg = $( _e.relatedTarget || _e.toElement );

				// if we're deep in a list, look higher
				if ( li && li.up().id !== this.id ) {
					li = li.up('li');
				} 
				// We have an LI,
				// and out LI is a direct parent of our div,
				// and we have options
				// and we're going to somewhere else
				if ( li &&
					( div = li.select('div.options').first() ) &&
					(
						(relTarg && ! relTarg.descendantOf( li )) ||
						(! relTarg)
				    ) 
				) {
					div.setStyle({ height: 0 });
				}
			}
			
			function onClick( _e ) {
				var a, m;

				_e.stop();

				a  = _e.element();
				
				// If we didn't click on an "a" get out of there!
				if ( ! ( a.nodeName.toLowerCase() === 'a' && (m = a.href.match( this.valueRE ))) ) {
					return;
				}
				// Wrap in try/catch because setFilterValue throws if a value is already set
				try {
					this.setFilterValue(m[1]);
					document.fire( VideoListEvent.FILTER_CHANGE, { component: this.name, filters: nfl.videos.FilterSets.getValue() });
				}
				catch(e) {}
			}
			
			function getLegalFilterValues( _a ) {
			  var m = _a.href.match(this.valueRE);
			  if (m) { return m[1]; }
			}
			
			function getLinkWithFilterValue ( _value, _instance ) {
				return function( _a ) {
					var m = _a.href.match(_instance.valueRE);
					return m[1] === _value;
				};
			}
			
			return Class.create({
				initialize: function( _options ) {
					var el            = $( _options.el );
					this.id           = el.identify();
					this.defaultValue = _options.defaultValue;
					this.paramName    = getFilterParamName( this.id );
					this.valueRE      = new RegExp( "\\?(?:.+&)?" + this.paramName + "=([^&]*)" );
					this.legalValues  = el.select('a').map(getLegalFilterValues.bind(this));
					this.name         = COMPONENT + '#' + this.id;
					el.
						observe('mouseover', onMouseOver.bind(this) ).
						observe('mouseout', onMouseOut.bind(this) ).
						observe('click', onClick.bind(this) ).
						select('div.options').
						invoke('setStyle', { height: 0 });
				},
				isLegalValue: function( _value ) {
					return this.legalValues.indexOf( _value ) !== -1;
				},
				getFilterValue: function() {
					var a, m;
					a = $(this.id).select( CURRENT_CSS + '>a' ).last();
					if ( ! ( a && (m = a.href.match( this.valueRE ))) ) { return this.defaulValue; }
					return m[1];
				},
				setFilterValue: function( _value ) {
					var el, re, a, parent;
					el = $(this.id);
					re = this.valueRE;
					if ( _value === this.getFilterValue() || ! this.isLegalValue( _value ) ) {
						throw new Error('Cannot set Filter Value.');
					}
					el.select( CURRENT_CSS ).invoke('removeClassName', CURRENT_CLASS);
					a  = el.select( 'a' ).filter( getLinkWithFilterValue( _value, this ) ).first();
					parent = a.up();
					// add class="current" to all LIs up the chain from the target
					while ( parent !== el ) {
						if ( parent.nodeName.toLowerCase() === 'li' ) {
							parent.addClassName( CURRENT_CLASS );
						}
						parent = parent.up();
					}
				}
			});
		}()),
		FilterByWeek: (function () {
			var COMPONENT     = 'nfl.videos.FilterByWeek',
			    FILTER_VALUES = [ -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19 ];
			
			function getWeekFromFilterValue ( _value ) {
				return FILTER_VALUES.indexOf( _value );
			}
			function getWeekNameFromFilterValue ( _value ) {
				return ( _value === FILTER_VALUES.first() ) ? "Preseason" :
				       ( _value === FILTER_VALUES.last() )  ? "Postseason" :
				       "Week " + getWeekFromFilterValue( _value );
			}
			function getFilterValueFromWeek ( _week ) {
				var nWeek = parseInt(_week, 10);
				if ( nWeek === parseFloat(_week) && nWeek > 0 && nWeek < FILTER_VALUES.length ) {
					return FILTER_VALUES[ nWeek ];
				}
				return FILTER_VALUES.first();
			}
			function getInteger ( _v ) {
				return parseInt( _v, 10 );
			}
			function getFilterPair ( _value ) {
				return Object.isArray( _value ) ? _value : _value.split(',').collect( getInteger );
			}
			
			return Class.create( Control.Slider, {
				initialize: function( $super, options) {
					var el, start, end, range, track, id, startWeek, endWeek, startV, endV,
					    width, results, template, value, name, curStart, curEnd, mutex;
			
					el        = $(options.el);
					if ( ! el ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + el );
					}
					id         = el.identify();
					start      = el.select('.start').first();
					end        = el.select('.end').first();
					track      = el.select('.track').first();
					range      = el.select('.range').first();
					results    = el.select('.results').first();
					template   = templatize( results );
					width      = start.offsetWidth / 2;
					startV     = FILTER_VALUES.first();
					endV       = FILTER_VALUES.last();
					if ( options.defaultValue ) {
						value  = getFilterPair( options.defaultValue );
						startV = getFilterValueFromWeek( value[0] );
						endV   = getFilterValueFromWeek( value[1] );
					}
					startWeek  = getWeekFromFilterValue( startV );
					endWeek    = getWeekFromFilterValue( endV );
					name       = COMPONENT + '#' + id;
					
					curStart   = startV;
					curEnd     = endV;

					this.paramName    = getFilterParamName( id );
					this.defaultValue = startWeek + ',' + endWeek;
					
					results.update( template.evaluate({ start: getWeekNameFromFilterValue( startV ), end: getWeekNameFromFilterValue( endV ) }) );
					results.show();
					
					// simple mutex for when setting two values at once
					mutex = true;
					this.shouldFire = function( _value ) { mutex = _value; };
					
					$super( [ start, end ], track, {
						range: $R( -1, 19 ),
						values: FILTER_VALUES,
						sliderValue: [ startV, endV ],
						restricted: true,
						spans: [ range ],
						onChange: function( value ) {
							var newStart, newEnd;
							newStart = value[0];
							newEnd   = value[1];
							if ( newStart === curStart && newEnd === curEnd ) {
								return console.log('FilterByWeek change with no value change.');
							}
							curStart = newStart;
							curEnd   = newEnd;
							results.update( template.evaluate({ start: getWeekNameFromFilterValue( newStart ), end: getWeekNameFromFilterValue( newEnd ) }) );
							if ( mutex ) {
								document.fire( VideoListEvent.FILTER_CHANGE, { component: name, filters: nfl.videos.FilterSets.getValue() });
							}
						}
					});
					
					Event.observe( window, 'beforeunload', function( e ) {
						results = start = end = track = range = null;
					});
					// for width miscalcs in IE
					el.select('div.slider').first().addClassName( CLASS_NAME.INIT );
				},
				isLegalValue: function( _value ) {
					var v;
					if ( ! _value ) { return false; }
					v = getFilterPair( _value );
					return FILTER_VALUES.include( getFilterValueFromWeek(v[0]) ) && FILTER_VALUES.include( getFilterValueFromWeek(v[1]) );
				},
				getFilterValue: function() {
					var range = this.getRange();
					return getWeekFromFilterValue( range.start ) + ',' + getWeekFromFilterValue( range.end );
				},
				setFilterValue: function( _value, _ignoreFilterChange ) {
					var newV, oldV1, oldV2, range;
					newV = getFilterPair( _value );
					// kludgy, but prevents multiple FILTER_CHANGE events
					// could be refactored
					range = this.getRange();
					oldV1 = range.start !== newV[0];
					oldV2 = range.end !== newV[1];
					if ( _ignoreFilterChange || oldV1 && oldV2 ) { this.shouldFire( false ); }
					if ( oldV1 ) { this.setValue( getFilterValueFromWeek( newV[0] ), 0 ); }
					if ( ! _ignoreFilterChange ) { this.shouldFire( true ); }
					if ( oldV2 ) { this.setValue( getFilterValueFromWeek( newV[1] ), 1 ); }
					this.shouldFire( true );
				}
			});
		}()),
		/**
		 * FilterSets
		 * 
		 * A static class for maintianing filters.
		 */
		FilterSets: (function() {
			var COMPONENT = 'nfl.videos.FilterSets',
			    __filters = [];
			
			function getEachFilterValue ( _acc, _filter ) {
				var filterValue = _filter.getFilterValue();
				if ( filterValue !== _filter.defaultValue ) {
					_acc[_filter.paramName] = filterValue;
				}
				return _acc;
			}
			
			
			// does this grab original page setting?!?
			// Maybe change page setting into a filter.
			function setFilterFromHash( _hash ) {
				return function( _acc, _filter ) {
					var value = _hash.get( _filter.paramName );
					if ( Object.isUndefined( value ) ) {
						value = _filter.defaultValue;
					}
					if ( ( ! _filter.isLegalValue( value ) ) || value === _filter.getFilterValue() ) {
						return _acc;
					}
					_filter.setFilterValue( value, true );
					return true;
				};
			}

			function setLocationHash ( _hash ) {
				var newHash, newHashBlank;
				newHash      = window.location.hashparams.getStringFromHash( _hash );
				newHashBlank = newHash.blank();
				if ( newHashBlank && window.location.hash.blank() ) { return; }
				window.location.hash = '#' + ( newHashBlank ? 'all' : newHash );
				// prevent weird scrolling if newHash is blank.
			}
			
			function setPaginationHash ( _e ) {
				var pagination, filtersHash, filtersSize, newHash;
				pagination  = _e.memo;
				filtersHash = nfl.videos.FilterSets.getValue();
				filtersSize = filtersHash.size();
				
				if ( pagination.page !== pagination.defaultPage ) {
					filtersHash.set('page', pagination.page);
				}
				if ( pagination.perPage !== pagination.defaultPerPage ) {
					filtersHash.set('perPage', pagination.perPage);
				}
				
				setLocationHash( filtersHash );
			}

			function adjustFiltersToHash ( _e ) {
				// If any of the filters have been updated by the hash, fire a filter change
				var anyFiltersChanged, hashParams, pagination, memo, page, perPage;
				hashParams        = window.location.hashparams.get() || new Hash();
				pagination        = nfl.videos.VideoPageSetting.getPagination();
				anyFiltersChanged = __filters.inject( false, setFilterFromHash( $H(hashParams) ) );
				page              = parseInt(hashParams.get('page') || pagination.defaultPage, 10);
				perPage           = parseInt(hashParams.get('perPage') || pagination.defaultPerPage, 10);
				if ( anyFiltersChanged ) {
					memo = { component: COMPONENT, filters: nfl.videos.FilterSets.getValue() };
					if ( page !== pagination.defaultPage ) {
						memo.page = page;
					}
					if ( perPage !== pagination.defaultPerPage ) {
						memo.perPage = perPage;
					}
					document.fire( VideoListEvent.FILTER_CHANGE, memo );
				}
				else if ( page !== pagination.page || perPage !== pagination.perPage ) {
					 nfl.videos.VideoPageSetting.setPagination({ page: page, perPage: perPage }, COMPONENT );
				}
				if ( _e.eventName === 'dom:loaded' ) {
					document.observe( 'window:hashchange', adjustFiltersToHash );
					document.observe( VideoListEvent.PAGE_CHANGE, setPaginationHash );
				}
			}
			
			function onFilterChange ( _e ) {
				var perPage, page, hash;
				hash    = _e.memo.filters.clone();
				page    = _e.memo.page;
				perPage = _e.memo.perPage;
				if ( page ) {
					hash.set('page', page);
				}
				if ( perPage ) {
					hash.set('perPage', perPage)
				}
				setLocationHash(hash);
			}

			document.observe( 'dom:loaded', adjustFiltersToHash );
			document.observe( VideoListEvent.FILTER_CHANGE, onFilterChange );
			
			return {
				add: function( _filter ) {
					console.log('FilterSets#add()', _filter);
					__filters.push( _filter );
				},
				getFilters: function() {
					return __filters;
				},
				getValue: function() {
					return $H(__filters.inject({}, getEachFilterValue));
/*				},
				setFilter: function( _filter, _value ) {
					var f = __filters.find( hasParamName( _filter ) );
					
					if ( f.isLegalValue( _value ) ) {
						f.setFilterValue( _value );
					}
					else {
						throw new Error( _value + ' is not a legal value for ' + f.name );
					}
*/				}
			};
		}()),
		VideoCollection: (function() {
			var VIDEOS_PER_BATCH   = 50,
			    AJAX_VIDEO_URL     = '/ajax/videos/v2',
			    CHANNEL_PARAM      = 'channelId',
			    TAG_PARAM          = 'tag',
			    SEARCH_PARAM       = 'search',
			    RUN_TIME_FIND      = /^(?:00:)?((\d\d:)+\d\d):\d\d$/,
			    RUN_TIME_REPLACE   = "$1",
			    DEFAULT_THUMB_SIZE = 'x-small',
			    COMPONENT          = 'nfl.videos.VideoCollection',
			    FADE_DURATION      = 0.5;
			
			function getBatch ( _oPagination ) {
				return Math.ceil( _oPagination.perPage * _oPagination.page / VIDEOS_PER_BATCH ) - 1;
			}

			function onPageChange ( _e ) {
				var m, batch;
				
				m = _e.memo;
				
				if ( ( ! m )  || m.component === this.name ) { return; }

				batch = getBatch( m );

				if ( this.hasBatch( batch ) ) {
					return this.render( m );
				}
				this.addVideos( batch );
			}
			
			function onFilterChange ( _e ) {
				var m, o, batch = 0;
				
				m = _e.memo;

				if ( ! m ) { return; }

				this.filters   = _e.memo.filters.clone();
				this.__batches = [];
				this.videos    = [];
				o              = nfl.videos.VideoPageSetting.getPagination();
				if ( m.page || o.page !== o.defaultPage ) {
					nfl.videos.VideoPageSetting.setPagination({ page: m.page || o.defaultPage }, this.name );
					batch = getBatch(nfl.videos.VideoPageSetting.getPagination());
				}
				return this.addVideos(batch);
			}

			function onBeforeUnload ( _e ) {
				this.list = null;
			}
			
			function onAjaxSuccess ( _transport ) {
				console.log( 'onAjaxSuccess()' );
				var json = _transport.responseJSON;
				if ( ! json && _transport.responseText.isJSON() ) {
					json = _transport.responseText.evalJSON();
				}
				
				if ( ! json) {
					return console.error('No JSON Available.');
				}
				
				this.addBatch( json.batch, json.videos );
				this.total = json.total;
				this.render();
				document.fire( VideoListEvent.VIDEOS, { total: this.total } );
			}
			
			function onAjaxFailure ( _transport ) {
				console.error('Ajax Failure!', _transport);
				this.list.update( 'Videos are unavailable at this time.' );
				document.fire( VideoListEvent.VIDEOS, { total: 0 } );
			}
			
			function onAjaxComplete ( _transport ) {
				this.ajax = null;
			}
			
			function stopCurrentEffect ( _el ) {
				if ( ! _el.effect ) { return; }
				_el.effect.cancel();
			}
			
			function nullCurrentEffect ( _el ) {
				_el.effect = null;
			}
			
			function onDomLoaded( _e ) {
				document.fire( VideoListEvent.VIDEOS, { total: this.total } );
			}
			
			function ignoreCurrentAjax ( _collection ) {
				return function( _el ) {
					var o;
					// If we're already making an Ajax request
					// don't worry about the result
					if ( _collection.ajax ) {
						o = _collection.ajax.options;
						o.onSuccess = o.onFailure = o.onComplete = Prototype.emptyFunction;
					}
				};
			}
			
			function startAjaxRequest ( _collection, _options ) {
				return function( _el ) {
					// Store this ajax request 
					_collection.ajax = new Ajax.Request( AJAX_VIDEO_URL, _options );
					nullCurrentEffect( _el );
				};
			}
			
			function setPlayButton( _el, _visibility) {
				try { _el.select('span').first().setStyle({ visibility: _visibility }); }
				catch(e) {}
			}

			return Class.create({
				initialize: function( _config ) {
					this.filters   = new Hash();
					this.template  = templatize( _config.template );
					this.list      = $( _config.list );
					if ( ! this.list ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + _config.list );
					}
					this.videos    = [];
					this.total     = _config.total;
					this.thumbSize = _config.thumbSize || DEFAULT_THUMB_SIZE;
					this.name      = COMPONENT + '#' + this.list.identify();
					this.empty     = templatize( _config.empty );
					
					if ( _config.channel ) { 
						this.channel = _config.channel;
					}
					if ( _config.tag ) { 
						this.tag     = _config.tag;
					}
					if ( _config.search ) { 
						this.search  = _config.search;
					}
					
					this.addBatch( _config.batch, _config.videos );

					// Fix for IE hiding and showing thumbnails
					if ( Prototype.Browser.IE ) {
						this.list.observe('mouseover', function( _e ) {
							var el = _e.findElement('div.thumbnail');
							_e.stop();
							if ( ! el ) { return; }
							setPlayButton( el, 'visible' );
						});
						this.list.observe('mouseout', function( _e ) {
							var el = _e.findElement('div.thumbnail');
							_e.stop();
							if ( ! el ) { return; }
							setPlayButton( el, 'hidden' );
						});
					}

					document.observe( VideoListEvent.FILTER_CHANGE, onFilterChange.bindAsEventListener(this) );
					document.observe( VideoListEvent.PAGE_CHANGE, onPageChange.bindAsEventListener(this) );
					document.observe('dom:loaded', onDomLoaded.bindAsEventListener(this) );
					Event.observe( window, 'beforeunload', onBeforeUnload.bindAsEventListener(this) );
				},
				addVideos: function( _batch ) {
					
					var params, options, season;
					
					params = this.filters.clone();
					params.set('batchNum', _batch || 0);
					
					// One-off logic because season is a baaaad value;
					season = params.get('season');
					if ( season && isNaN(parseInt(season, 10)) ) {
						params.set('season', null);
					}
					if ( this.channel ) {
						params.set( CHANNEL_PARAM, this.channel );
					}
					if ( this.search ) {
						params.set( SEARCH_PARAM, this.search );
					}
					if ( this.tag ) {
						params.set( TAG_PARAM, this.tag );
					}
					
					options = {
						method: 'get',
						parameters: params,
						onSuccess: onAjaxSuccess.bind( this ),
						onFailure: onAjaxFailure.bind( this ),
						onComplete: onAjaxComplete.bind( this )
					};
					
					this.effect = new Effect.Opacity( this.list, {
						to: 0,
						duration: FADE_DURATION,
						beforeStart: ignoreCurrentAjax( this ),
						afterFinish: startAjaxRequest( this, options )
					});
				},
				__batches: [],
				addBatch: function( _batch, _videos ) {
					var i, l, offset = _batch * VIDEOS_PER_BATCH;
					this.__batches[ _batch ] = true;
					
					for ( i = 0, l = _videos.length; i < l; i+=1 ) {
						this.videos[ offset + i ] = this.videoCleaner( _videos[ i ] );
					}
				},
				hasBatch: function( _b ) {
					try {
						return this.__batches[ _b ] === true;
					}
					catch(e) {
						console.log('I died.');
						return false;
					}
				},
				render: function( _o ) {
					var o, i, start, end, videos, template, result, e;
					
					if ( this.videos.length === 0 ) {
						result     = this.empty.evaluate( this );
					}
					else {
						o          = _o ? _o : nfl.videos.VideoPageSetting.getPagination();
						start      = ( o.page - 1 ) * o.perPage;
						end        = start + o.perPage - 1;
						if ( end >= this.total ) {
							end    = this.total - 1;
						}
						videos     = this.videos;
						template   = this.template;
						result     = '';
					
						for ( i = start; i <= end; i+=1 ) {
							videos[i].index = i;
							result += template.evaluate( videos[i] );
						}
					}
					this.list.update( result );
					e = new Effect.Opacity( this.list, {
						to: 1,
						duration: FADE_DURATION,
						beforeStart: stopCurrentEffect,
						afterFinish: nullCurrentEffect
					});
				},
				videoCleaner: function( _video ) {
					var thumb = ( this.thumbSize === DEFAULT_THUMB_SIZE ? _video.xSmallImage : _video.smallImage );
					
					if ( isBadImage( thumb ) ) {
						thumb = DEFAULT_THUMB_IMAGE[ this.thumbSize ];
					}
					_video.thumbnailImage = '<img src="' + thumb + '" alt="Watch: ' + _video.briefHeadline + '" />';
					if ( ( ! _video.date ) && _video.published ) {
						_video.date = new Date( _video.published ).toAPStyle( true );
					}
					_video.runTime = _video.runTime.replace( RUN_TIME_FIND, RUN_TIME_REPLACE );
					return _video;
				}
			});
		}()),
		VideoPageSetting: (function () {
			var page, perPage, defaultPage, defaultPerPage;
			
			function update ( _component ) {
				var o = nfl.videos.VideoPageSetting.getPagination();
				if ( _component ) { o.component = _component; }
				document.fire( VideoListEvent.PAGE_CHANGE, o );
			}
			
			return {
				setPagination: function( _value, _component ) {
					var newPage, newPerPage, inNaNPerPage, isNaNPage;
					
					newPage      = parseInt( _value.page, 10 );
					newPerPage   = parseInt( _value.perPage, 10 );
					isNaNPage    = isNaN(newPage);
					inNaNPerPage = isNaN(newPerPage);
					if (
						(isNaNPage || page === newPage) &&
						(inNaNPerPage || perPage === newPerPage )
					) { return; }
					page    = isNaNPage ? 1 : newPage;
					if ( ! inNaNPerPage ) {
						perPage = newPerPage;
					}
					update( _component );
				},
				getPagination: function() {
					return { page: page, perPage: perPage, defaultPage: defaultPage, defaultPerPage: defaultPerPage };
				},
				setDefaults: function( _o ) {
					page = defaultPage = parseInt(_o.page, 10);
					perPage = defaultPerPage = parseInt(_o.perPage, 10);
				},
				getDefaultPerPage: function() {
					return defaultPerPage;
				},
				getDefaultPage: function() {
					return defaultPage;
				}
			};
		}()),
		VideosPerPageFilter: (function () {
			var COMPONENT = 'nfl.videos.VideosPerPageFilter';
		
			function onFormSubmit ( _e ) {
				var value = $F( this.el );
				_e.stop();

				if ( value === this.value ) { return; }

				this.value = value;
				nfl.videos.VideoPageSetting.setPagination({ perPage: value, page: 1 }, this.name );
			}
		
			function onPageChange ( _e ) {
				if ( _e.memo.component === this.name || _e.memo.perPage === this.value ) { return; }

				this.value = this.el.value = _e.memo.perPage;
			}
			
			function onBeforeUnload ( _e ) {
				this.id = this.el = null;
			}
		
			return Class.create({
				initialize: function( ref ) {
					var form = $( ref );

					if ( ! form ) {
						console.log('Could not initialize ' + COMPONENT + '. Could not find ' + ref);
						return;
					}
					
					this.id    = form.identify();
					this.el    = form.select('select').first();
					this.value = $F( this.el );
					this.name  = COMPONENT + '#' + this.id;
					
					// sometimes browsers will keep a value in the <select>
					// regardless of <option selected="selected">
					if ( this.value !== nfl.videos.VideoPageSetting.getDefaultPerPage() ) {
						nfl.videos.VideoPageSetting.setPagination({ perPage: this.value }, this.name);
					}
					
					form.observe( 'submit', onFormSubmit.bind( this ) );
					document.observe( VideoListEvent.PAGE_CHANGE, onPageChange.bindAsEventListener(this) );
					Event.observe( window, 'beforeunload', onBeforeUnload.bindAsEventListener(this) );
				}
			});
		}()),
		VideosDisplaying: (function() {
			var COMPONENT = 'nfl.videos.VideosDisplaying';
			
			function onVideos ( _e ) {
				this.total = _e.memo.total;
				this.render();
			}
			
			function onPageChange ( _e ) {
				this.render( _e.memo );
			}
			
			function onBeforeUnload ( _e ) {
				this.el = null;
			}
			
			return Class.create({
				initialize: function( _ref ) {
					var templateNodes, min, max, total;
					this.el = $( _ref );
					
					if ( ! this.el ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + _ref );
					}
					templateNodes   = this.el.cloneNode(true);
					min             = templateNodes.select('.min').first();
					max             = templateNodes.select('.max').first();
					total           = templateNodes.select('.total').first();
					this.min        = parseInt( min.innerHTML, 10 );
					this.max        = parseInt( max.innerHTML, 10 );
					this.total      = parseInt( total.innerHTML, 10 );
					min.innerHTML   = "#{min}";
					max.innerHTML   = "#{max}";
					total.innerHTML = "#{total}";
					this.template   = templatize( templateNodes );
					this.name       = COMPONENT + '#' + this.el.identify();
					
					document.observe( VideoListEvent.VIDEOS, onVideos.bind(this) );
					document.observe( VideoListEvent.PAGE_CHANGE, onPageChange.bind(this) );
					Event.observe( window, 'beforeunload', onBeforeUnload.bind(this) );
				},
				render: function( _o ) {
					var o, page, perPage;
					
					o        = _o ? _o : nfl.videos.VideoPageSetting.getPagination();
					perPage  = o.perPage;
					page     = o.page;

					this.min = ( page - 1 ) * perPage + 1;
					this.max = this.min + perPage - 1;
					if ( this.max > this.total ) {
						this.max = this.total;
					}
					this.el.update( this.template.evaluate( this ));
					if ( this.total ) {
						this.el.show();
					}
					else {
						this.el.hide();
					}
				}
			});
		}()),
		VideoPagination: (function() {

			var MAX_PAGES_DISPLAYED = 5,
			    SPREAD              = 2,
			    COMPONENT           = 'nfl.videos.VideoPagination',
			    PAGE_NUMBER_RE      = /(\d+)$/;

			/**
			 * Creates a range of pages
			 * Copied from nfl.news.Paginator
			 *
			 * @param Number page  The current page
			 * @param Number pages The total number of pages
			 * @returns Range The range of pages to show
			 */
			function getRange(page, pages) {
				var start, end;

				start = page - SPREAD;
				if (pages - page < SPREAD && page - SPREAD > 0) {
					start -= SPREAD - (pages - page);
				}
				if (start < 1) { start = 1; }

				end = page + SPREAD;
				if (end > pages || pages < MAX_PAGES_DISPLAYED) { end = pages; }
				else if (end < MAX_PAGES_DISPLAYED && pages >= MAX_PAGES_DISPLAYED) {
					end = MAX_PAGES_DISPLAYED;
				}

				return $R(start, end);
			}
			
			function onVideos ( _e ) {
				this.total = _e.memo.total;
				this.render();
			}
			
			function onPageClick ( _e ) {
				var a, m;
				a = _e.findElement('a');

				if ( (! a ) || a === document ) { return; }
				_e.stop();
				m = a.href.match( PAGE_NUMBER_RE );
				if ( ! m ) { return; }
				nfl.videos.VideoPageSetting.setPagination({ page: m[1] });
			}
			
			function onPageChange ( _e ) {
				if ( this.total ) { this.render( _e.memo ); }
			}
			
			function onBeforeUnload ( _e ) {
				this.el = this.destination = null;
			}
			
			return Class.create({
				initialize: function( _o ) {
					this.el          = $( _o.content );
					if ( ! this.el ) {
						throw new Error( 'Could not initialize ' + COMPONENT + ', could not find ' + _o.content );
					}
					this.template    = templatize( _o.template );
					this.destination = $( _o.destination );
					this.name        = COMPONENT + '#' + this.el.identify();
					
					nfl.videos.VideoPageSetting.setDefaults({ page: _o.page, perPage: _o.perPage });
					
					this.el.observe( 'click', onPageClick.bindAsEventListener(this) );
					document.observe( VideoListEvent.PAGE_CHANGE, onPageChange.bindAsEventListener(this) );
					document.observe( VideoListEvent.VIDEOS, onVideos.bindAsEventListener(this) );
					Event.observe( window, 'beforeunload', onBeforeUnload.bindAsEventListener(this) );
				},
				render: function( _o ) {
					var o, pages, pagination, template, page_html, page;
					
					page_html  = '';
					o          = _o ? _o : nfl.videos.VideoPageSetting.getPagination();
					page       = o.page;
					pages      = Math.ceil( this.total / o.perPage );
					pagination = this.el;
					template   = this.template;

					if (pages > 1) {
						if (page > 1) {
							page_html += template.evaluate({ className: CLASS_NAME.PREVIOUS, page: page - 1, page_name: 'Previous'});
						}
						getRange(page, pages).each(function (current) {
							var className = CLASS_NAME.PAGE;
							if (current === page) { className += (' ' + CLASS_NAME.CURRENT);}
							page_html += template.evaluate({ className: className, page: current, page_name: current});
						});
						if (page < pages) {
							page_html += template.evaluate({ className: CLASS_NAME.NEXT, page: parseInt(page, 10) + 1, page_name: 'Next'});
						}
						pagination.update(page_html);
						pagination.show();
						if ( this.destination && _o ) {
							Effect.ScrollTo( this.destination );
						}
					}
					else {
						pagination.hide();
					}
					
				}
			});
		}()),
		VideoCompanionAd: (function() {
			var AD_CONTAINER_CLASS = 'adcontainer';

			function onAbandonedPreRoll( _e ) {
				var propValue = "Preroll_abandon";
				// eek! we're being abandoned! Track it
				console.log('logging abandoned pre-roll.');
				s_analytics.linkTrackVars="prop35";
				s_analytics.prop35 = propValue;
				s_analytics.tl(true,'o',propValue);
			}
			function onCompletedPreRoll( _e ) {
				Event.stopObserving( window, 'unload', onAbandonedPreRoll );
				document.stopObserving( VideoPlayerEvent.PLAY, onCompletedPreRoll );
			}
			function showCompanionAd( _e ) {
				console.log('VideoCompanionAd#showCompanionAd(): ' + _e.memo.companionURL );
				var adURL = _e.memo.companionURL;
				if ( adURL ) {
					this.ad.url = adURL;
				}
				Event.observe( window, 'unload', onAbandonedPreRoll );
				document.observe( VideoPlayerEvent.PLAY, onCompletedPreRoll );
				this.writeAd();
			}
			function writeAd( _e ) {
				// remove the old listeners; we don't need them
				document.stopObserving( VideoPlayerEvent.PRE_ROLL_START, this.showCompanionAd );
				document.stopObserving( VideoPlayerEvent.PLAY, this.writeAd );
				document.stopObserving( VideoPlayerEvent.UNAVAILABLE, this.writeAd );
				$( this.adID ).update( this.ad.getIframeHTML() );
			}
			
			return Class.create({
				initialize: function( _config ) {
					console.log("initializing ad");
					var container, adContainer;
					
					// set up properties
					container             = $( _config.el );
					this.el               = container.identify();
					this.defaultURL       = _config.adURL;
					this.showCompanionAd  = showCompanionAd.bindAsEventListener( this );
					this.writeAd          = writeAd.bindAsEventListener( this );
					
					// create the div for the ad
					adContainer           = document.createElement('div');
					adContainer.className = AD_CONTAINER_CLASS;
					this.adID             = Element.identify( adContainer );
					container.appendChild( adContainer );
	
					// create new ad object
					this.ad               = new nfl.ads.Ad(this.adID,'',{width:_config.width, height:_config.height, url:this.defaultURL, write:false});
					//this.ad               = { getIframeHTML: function() { return 'BROKEN ON PURPOSE: ' + this.url; }, url: _config.adURL };
					
					// wait for video player events
					document.observe( VideoPlayerEvent.AD_LOADED, this.showCompanionAd );
					document.observe( VideoPlayerEvent.PLAY, this.writeAd ); 
					document.observe( VideoPlayerEvent.UNAVAILABLE, this.writeAd ); 
				}
			});
		}()),
		/**
		 * These classes are lazily initialized to save processor resources
		 * on pages on which they are not used, and downloaded time when
		 * they are. Doing so removes a dependency on comments.js
		 *
		 * @author ryan.cannon
		 */
		VideoPageSiteLifeController: {
			define: function() {
				// once the dom is ready, continue the initialization, maintaining
				// some scope this is called by initialize()
				function onDomReady ( _self, _config ) {
					return function( _e ) {
						var showCommentsObject;
						// If we have an array of comment totals, loop through them
						if ( Object.isArray(_config.comment_totals) ) {
							_config.comment_totals.each(function(_ref) {
								_self.showMetaData( _ref );
							});
						}
						// otherwise, if we have one, register the one
						else if ( _config.comment_totals ) {
							_self.showMetaData( _config.comment_totals );
						}
						// if the video is commentable
						if ( _config.commentable ) {
							showCommentsObject = {
								container: _config.container,
								list: _config.list,
								report_form: _config.report_form,
								batchRequests: true
							};
							// if this is the comment page, add pagination
							if ( _config.is_comment_page ) {
								showCommentsObject.pagination  = _config.pagination;
							}
							// otherwise, only show a couple comments
							else {
								showCommentsObject.page    = 1;
								showCommentsObject.perPage = 3;
							}
							_self.showComments( showCommentsObject );
						}
						// now go get the data from Pluck!
						_self.getData();
					};
				}
				if ( ! ( nfl.news && nfl.news.Comments && nfl.news.Comments.ArticleController ) ) {
					throw new Error("Missing dependency: nfl.news.Comments.ArticleController");
				}
				nfl.videos.VideoPageSiteLifeController = Class.create( nfl.news.Comments.ArticleController, {
					initialize: function( $super, _config ) {
						var initObject, commentable, recommendable;
						
						commentable   = _config.commentable;
						recommendable = _config.recommendable;
						initObject = {
							ecm_id: _config.ecm_id,
							headline: _config.headline,
							url: _config.url,
							section: _config.section,
							categories: _config.categories
						};
						// if the video is commentable, initialize, enable comments and track
						// registrations
						if ( commentable ) {
							initObject.signed_in_messaging  = _config.signed_in_messaging;
							initObject.signed_out_messaging = _config.signed_out_messaging;
							$super( initObject );
							this.enableComments({
								comment_form: _config.comment_form,
								is_comment_page: _config.is_comment_page,
								trackingName: 'VS_Comments_Submit'
							});
							nfl.news.Comments.TrackRegistrations();
						}
						// if it's not, we just need to update Pluck metadata on this vieo
						else {
							$super( initObject );
						}
						// if it's recommendable, enable recommendations
						if ( recommendable ) {
							this.enableRecommendations();
						}
						// once the dom is loaded, finish initialization
						document.observe('dom:loaded', onDomReady( this, _config ) );
					}
				});
			}
		},
		ObserveVideoPlayerEvents: function() {
			var i, VideoPlayerEvent = nfl.events.VideoPlayerEvent;

			function logVPE( _e ) { console.log( _e.eventName, $H( _e.memo ).inspect() ); }
			// log all video events
			for ( i in VideoPlayerEvent ) {
				if ( VideoPlayerEvent.hasOwnProperty( i ) ) {
					document.observe( VideoPlayerEvent[i], logVPE );
				}
			}
			
			// kill animated menus for performance reasons in IE6 during video playback
			function killAnimation( _e ) {
				nfl.global.Navigation.setAnimation( false );
			}
			function enableAnimation( _e ) {
				nfl.global.Navigation.setAnimation( true );
			}

			if ( Prototype.Browser.IE && navigator.appVersion.indexOf('MSIE 6.0') ) {
				document.observe( VideoPlayerEvent.PRE_ROLL_START, killAnimation );
				document.observe( VideoPlayerEvent.PLAY, killAnimation );
				document.observe( VideoPlayerEvent.PAUSE, enableAnimation );
				document.observe( VideoPlayerEvent.PLAYBACK_COMPLETE, enableAnimation );
				document.observe( VideoPlayerEvent.UNAVAILABLE, enableAnimation );
			}
		},
		/*
		 * @author arianna.winters
		 * @class nfl.videos.carousel
		 * @param {String} | {Object} parent container element of ul element
		 */
		Carousel: Class.create({
			initialize: function(container,options){
				this.container	= $(container);
				console.log('initializing '+container);
				this.list		= this.container.select('.list-items').first();
				this.options	= options || {};
				this.rows		= (typeof this.options.rows !== 'undefined')? this.options.rows:1;
				this.evtprefix	= 'videos';
				this.totalPages	= -1;
				this.portwidth	= 0;
				this.totalWidth = 0;

				/* set list width to children total width */
				var tChildren	= this.list.select('li');
				tChildren.each(function(ele){
					this.totalWidth	= this.totalWidth + ele.getWidth();
				}.bind(this));
				console.info('this.rows = '+this.rows);
				this.list.setStyle({width:(this.totalWidth)+'px'});
				console.log('set list style to '+this.list.getStyle('width'));
				this.scrollMultiplyer = 1;
				this.originalLeftMargin	= (parseInt(this.list.getStyle('margin-left').replace('px',''), 10));
				console.log('initializing '+container+' ending.');
				document.observe(this.evtprefix+':carousel:scroll',this.onScroll.bind(this));
				document.observe(this.evtprefix+':carousel:pagechange',this.onPageChange.bind(this));
				document.fire(this.evtprefix+':carousel:pagechange',{id:this.container.identify()});
			},
			onPageChange: function(event){
				var currentPageEle, totalPagesEle;
				if(this.container.identify() === event.memo.id){
					console.info('nfl.photos.carousel.onPageChange');
					currentPageEle	= this.container.select('.carousel-controls-page').first();
					totalPagesEle	= this.container.select('.carousel-controls-totalpages').first();
					this.portwidth 	= this.container.getWidth()+ Math.abs(this.originalLeftMargin);
					totalPagesEle.update(this.getTotalPages());
					currentPageEle.update(this.getCurrentPage()+'');
				}
			},
			getTotalPages: function(){
				if(this.totalPages === -1){
					if(!isNaN(Math.ceil(this.totalWidth / this.portwidth))){
						this.totalPages	= Math.ceil(this.totalWidth / this.portwidth);
					}
					if(this.totalPages < 1){
						this.totalPages	= 1;
					}
				}
				return this.totalPages;
			},
			getCurrentPage: function(){
				var itemcontainer, portwidth;
				itemcontainer	= this.list;
				portwidth 		= this.container.getWidth();
				return Math.ceil(Math.abs(parseInt(itemcontainer.getStyle('margin-left'), 10)) / portwidth);
			},
			onScroll: function(event){
				var direction, itemcontainer, portwidth, amountToScroll, amountToScrollMultiplyer, itemLeft, newLeft;
				console.info("nfl.videos.carousel.onScroll");
				if(this.container.identify() === event.memo.id){
					amountToScroll				= 0;
					amountToScrollMultiplyer	= this.scrollMultiplyer;
					direction 		= event.memo.direction;
					itemcontainer	= this.list;
					portwidth 		= this.container.getWidth()+ Math.abs(this.originalLeftMargin);
					if(event.memo.multiplyer){ amountToScrollMultiplyer	= event.memo.multiplyer;}
					try{ 
						itemLeft	= parseInt(itemcontainer.getStyle('margin-left'), 10);
					}catch(e){
						itemcontainer.setStyle({'margin-left':'0px'});
						itemLeft	= parseInt(itemcontainer.getStyle('margin-left'), 10);
					}
					switch(direction){
						case 'left':
							amountToScroll	= (itemLeft === (0+this.originalLeftMargin))?(0 - (portwidth * Math.floor((this.totalWidth - Math.abs(this.originalLeftMargin)) / portwidth))):(amountToScroll + portwidth);
							break;
						case 'right':
							amountToScroll	= ((itemLeft + (0 - portwidth)) <= (0 - parseInt(itemcontainer.getStyle('width'),10)))?(this.originalLeftMargin - itemLeft):(amountToScroll - portwidth);
							//nfl.log('('+ (itemLeft + (0 - portwidth)) +' <= (0 - '+ parseInt(itemcontainer.getStyle('width')) +') ? '+ ((itemLeft + (0 - portwidth)) <= (0 - parseInt(itemcontainer.getStyle('width')))));
							break;
						default:
							break;
					}
					amountToScroll	= (amountToScroll * amountToScrollMultiplyer);
					console.log("nfl.videos.carousel.onScroll: amountToScroll = "+ amountToScroll +"");
					//now perform scroll operation based on value outputs from switch statement above
					if(itemLeft % portwidth === (0+this.originalLeftMargin)){
						newLeft	= (itemLeft + amountToScroll);
						console.log("{nfl.videos.carousel.onScroll: newLeft = "+ newLeft +"}");
						itemcontainer.morph('margin-left: ' + newLeft + 'px;',{afterFinish: function(){document.fire('videos:carousel:pagechange',{id:this.container.identify()});}.bind(this), duration: 0.8, fps: 30});
					}else{
						console.warn('nfl.videos.carousel.onScroll: item is in play.');
					}
				}
			}
		}),
		Carousels: (function () {
			var _collection = [];
		
			function initializeCarousel( _a ) {
				return new nfl.videos.Carousel( _a[0], _a[1] );
			}
			function initialize( _e ) {
				_collection.map(initializeCarousel);
			}
			document.observe('dom:loaded', initialize);
			return {
				add: function( _ref, _options ) {
					_collection[_collection.length] = [_ref, _options];
				}
			};
		}())
	};
}());
