var GamesList = Class.create();
GamesList.prototype = {
	effectParams: {
		duration: 0.75,
		transition: Effect.Transitions.EaseFromTo
	},
	initialize: function(gamesListSelector, forcedParams) {
		var gamesList = $$(gamesListSelector).first();
		this.gamesContainer = gamesList.getElementsBySelector('ul.games').first();
		this.games = this.gamesContainer.getElementsBySelector('li');
		
		// check for a Cookie'd (or queryParam'd) sort preference and platform preference
		var params = window.location.href.toQueryParams();
		this.filters = {
			platform: forcedParams.platform || params.platform || Cookie.get('gameslist_filter_platform') || null,
			sort: forcedParams.sort || params.sort || Cookie.get('gameslist_filter_sort') || 'release_date'
		};
		
		// hook into the platform selection dropdown
		var platformFilterSelect = gamesList.getElementsBySelector('select.platform').first();
		this.initializePlatformSelect(platformFilterSelect, this.filters.platform);
		
		// hook into the sorting links
		var sortingLinks = gamesList.getElementsBySelector('dl.filter a');
		this.initializeSortingLinks(sortingLinks, this.filters.sort);
		
		// do the initial filter
		this.filter();
		
		// unhide all of the games
		this.games.each(function(game) {
			game.setStyle({visibility: 'visible'});
		});
	},
	initializePlatformSelect: function(element, initialPlatform) {
		if(initialPlatform) {
			if(initialPlatform == 'all') {
				var optionToSelect = {index: 0};
			} else {
				var optionToSelect = $A(element.options).find(function(option, index) {
					if(option.value == initialPlatform) {
						return true;
					}
				});
			}
			if(optionToSelect) element.selectedIndex = optionToSelect.index;
		}
		
		Event.observe(element, 'change', function(evt) {
			this.filter({ platform: (Event.element(evt).value || null) });
		}.bindAsEventListener(this));
	},
	initializeSortingLinks: function(links, initialCriterion) {
		links.each(function(link) {
			var sort = link.href.toQueryParams().sort;
			
			if(sort == initialCriterion) link.addClassName('active');
			
			Event.observe(link, 'click', function(evt) {
			   links.each(function(link) { link.removeClassName('active');});
				Event.element(evt).addClassName('active');
				
				this.filter({sort: sort});
				
				Event.stop(evt);
			}.bindAsEventListener(this));
			
		}.bind(this));				
	},
	filter: function(params) {
		var actions = {};
		var runAll = params ? false : true;
		
		// store the filters and decide whether or not there has been a change
		$H(params).each(function(pair) {
			if(this.filters[pair[0]] != pair[1]) actions[pair[0]] = true;
			this.filters[pair[0]] = pair[1];
			if(Cookie.accept()) Cookie.set('gameslist_filter_' + pair[0], pair[1], {path:'/', expires:365*24*60*60});
		}.bind(this));
		
			
		if(actions.platform || runAll) {
			this.games.each(function(game) {
				this.filters.platform ? (this.filters.platform == 'all' || game.hasClassName(this.filters.platform) ? game.show() : game.hide()) : game.show();
			}.bind(this));
			actions.sort = true; // must cause a re-sorting if there's been a platform filter
			var doNotAnimateSort = true; // no need to animate the sort if there's been a platform filter
		}
		if(actions.sort || runAll) {
			// get an array of sorted games
			var newlySortedGames = this.games.select(function(game) { return game.getStyle('display') != 'none'; }).clone();
			newlySortedGames.sort(this.sortFunctions[this.filters.sort]);
			// move each game into place
			this.games.sortBy(function(game) { return parseInt(game.getStyle('top')); }).each(function(game, oldIndex) {
				newlySortedGames.each(function(sortedGame, index) {
					if(sortedGame.id == game.id) {
						//find out the vertical position this game needs to go to
						var verticalPosition = 0;
						(index).times(function(ticker) {
							verticalPosition += newlySortedGames[ticker].getHeight();
						});
						
						//send the game to this position
						var newVerticalPosition = parseInt(game.getStyle('top') || 0) + (verticalPosition - Position.positionedOffset(game)[1]);
						
						if(runAll || doNotAnimateSort) {
							game.setStyle({top: newVerticalPosition + 'px'});
						} else {
							/*
							new Effect.Morph(game, $H({style: 'opacity: 0', delay: (index * this.effectParams.duration) / 10, afterFinish: function() {
									game.setStyle({top: newVerticalPosition + 'px'});
									new Effect.Morph(game, $H({style: 'opacity: 1'}).merge(this.effectParams));
								}
							}).merge(this.effectParams));
							*/
							var effect = new Effect.Morph(game, $H({
								style: 'top: ' + newVerticalPosition + 'px'
							}).merge(this.effectParams));
						}
						return;
					}
				}.bind(this));
			}.bind(this));	
		}
		this.sortedGames = newlySortedGames;
	},
	sortFunctions: {
		title: function(a, b) {
			var titles = [a.getElementsBySelector('dt a').first().innerHTML.toLowerCase(), b.getElementsBySelector('dt a').first().innerHTML.toLowerCase()];
			return (titles[0] == titles[1]) ? 0 : ((titles[0] > titles[1]) ? 1 : -1);
		},
		release_date: function(a,b) {
			var aClasses = a.classNames().entries()[1];
			var aDate = aClasses ? aClasses.split('-') : [9999,1,0];
			aDate[1] -= 1;
		
			var bClasses = b.classNames().entries()[1];
			var bDate = bClasses ? bClasses.split('-') : [9999,1,0];
			bDate[1] -= 1;
	
			var releases = [
				new Date(aDate[0], aDate[1], aDate[2]),
				new Date(bDate[0], bDate[1], bDate[2]),
			]
			return (releases[0] == releases[1]) ? 0 : ((releases[0] > releases[1]) ? -1 : 1);
		}
	}
}