/*jslint browser: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true */
// ==ClosureCompiler==
// @output_file_name main.min.js
// @compilation_level SIMPLE_OPTIMIZATIONS
// ==/ClosureCompiler==
(function() {
	var $ = function(s) {
		return document.querySelectorAll(s);
	};
	var config = {
		previewTime: 5000,
		// Match this user agent, without version numbers
		// Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17
		match: /^.*Nexus One.*$/,
		forwardUrl: 'http://android.com/',
		droids: ['Abominable Applet','Robo-Ralphie','Runtime Rudolph','Nutcracker Hacker','SQL Snowman','Candycane Coder','Killer App Kringle','Patch Penguin','Christmas Cookie','Emulator Elf','Rock Star','Gmail Gifty']
	};
	if (!navigator.userAgent.match(config.match)) { document.location = config.forwardUrl; return; }
	function hasClass(ele,cls) {
		return ele.className.indexOf(cls) !== -1;
	}
	function addClass(ele,cls) {
		if (!hasClass(ele,cls)) { ele.className = ele.className + " " + cls; }
		return ele;
	}
	function removeClass(ele,cls) {
		ele.className = ele.className.replace(cls,'');
		return ele;
	}
	var game = {
		el: $('#game')[0],
		block: function() { return game.addClass('blocked'); },
		unblock: function() { return game.removeClass('blocked'); },
		addClass: function(c) { addClass(game.el,c); return game; },
		removeClass: function(c) { removeClass(game.el,c); return game; }
	};
	var elements = $('#game li'), numCards = elements.length, i = numCards,
			maxValue = numCards / 2, cards = new Array(numCards), cdtimers = [], startTime, timer;
	$('#down')[0].innerHTML = '0' + config.previewTime / 1000;
	$('#restart')[0].addEventListener('click',restartGame,false);
	$('#start')[0].addEventListener('click',startPreview,false);
	$('#playAgain')[0].addEventListener('click',playAgain,false);
	$('#continue')[0].addEventListener('click',hideRules,false);
	$('#rules-button')[0].addEventListener('click',toggleRules,false);
	addEventListener('load',resize, false);
	addEventListener('resize',resize,false);
	if (document.location.search.indexOf('black') !== -1) { game.addClass('black'); }
	removeClass($('#container')[0],'hidden');
	do { i = i - 1; cards[i] = new Card(elements[i],i); } while (i);
	var values = {};
	shuffleCards(false);
	function resize() {
		var container = $('#container')[0];
		if (screen.width > 600) { addClass(container,'landscape'); removeClass(container,'portrait'); }
		else { addClass(container,'portrait'); removeClass(container,'landscape'); }
		setTimeout(function() { scrollTo(0,1); }, 250);
	}
	function Card(cardEl,index) {
		var that = this;
		this.el = cardEl;
		this.index = index;
		this.value = -1;
		this.clazz = '';
		this.click = function(e) {
			e.stopPropagation();
			e.preventDefault();
			clickCard(that,index);
		};
		this.destroy = function() {
			cardEl = null;
			index = null;
			that = null;
			this.el = null;
			this.index = null;
			this.value = null;
		};
		this.setup = function(value) {
			cardEl.className = '';
			this.el.removeEventListener('click',that.click,false);
			this.el.addEventListener('click',that.click,false);
			this.value = value;
			this.clazz = 'card' + value;
			var front = cardEl.querySelector('a.front');
			if (front.innerHTML.match(/^-?\d+$/)) { front.innerHTML = value; }
		};
		this.reveal = function() {
			this.addClass('revealed').addClass(this.clazz);
			return that;
		};
		this.hide = function() {
			this.addClass('hiding').addClass('hidden');
			setTimeout(function() { that.removeClass(this.clazz).removeClass('revealed').removeClass('hidden').removeClass('hiding'); },500);
			return that;
		};
		this.addClass = function(c) {
			addClass(cardEl,c);
			return that;
		};
		this.removeClass = function(c) {
			removeClass(cardEl,c);
			return that;
		};
		addEventListener('beforeunload',that.destroy,false);
		document.body.addEventListener('unload',that.destroy,false);
	}
	function getCardForEl(el) {
		var i = numCards, result = null;
		do {
			i = i - 1;
			if (elements[i] === el) { result = cards[i]; }
		} while (i && !result);
		return result;
	}
	function setupCard(card) {
		var value = random();
		if (!values[value]) { values[value] = []; }
		if (values[value].length !== 2) {
			values[value].push(card);
			card.setup(value);
			if (value % 3 === 0) { card.addClass('shuffleSlow'); }
			else if (value % 3 === 1) { card.addClass('shuffleMed'); }
			else { card.addClass('shuffleFast'); }
		} else {
			setupCard(card);
		}
	}
	function random() {
		return Math.floor(Math.random() * maxValue);
	}
	function clickCard(card) {
		if (hasClass(card.el,'active')) { activeCard(card); }
		else if (hasClass(card.el,'revealed')) { revealedCard(card); }
		else { tryMatchCard(card); }
		var numMatched = $('li.matched').length;
		if (numMatched === numCards) {
			game.block();
			setTimeout(winGame,1250);
		}
	}
	function activeCard(card) {
		card.hide().removeClass('active');
	}
	function revealedCard(card) { }
	function tryMatchCard(card) {
		var active = $('li.active');
		card.reveal().addClass('active');
		if (active.length) { matchCards(active[0],card); }
		else { revealedCard(); }
	}
	function matchCards(active,card) {
		active = getCardForEl(active);
		if (isMatch(active,card)) {
			active.removeClass('active').addClass('matched');
			card.reveal().removeClass('active').addClass('matched');
		} else {
			card.reveal();
			setTimeout(function() { hideCards(active,card); },600);
		}
	}
	function isMatch(cardOne,cardTwo) {
		return cardOne.el !== cardTwo.el && cardOne.value === cardTwo.value;
	}
	function showRules() {
		game.block();
		addClass(removeClass($('#rules')[0],'hide'),'show');
		addClass($('#rules-button')[0],'rules-up');
	}
	function hideRules() {
		addClass(removeClass($('#rules')[0],'show'),'hide');
		removeClass($('#rules-button')[0], 'rules-up');
		if (!hasClass($('#up')[0],'off')) { game.unblock(); }
	}
	function toggleRules() {
		if (hasClass($('#rules')[0],'show')) { hideRules(); }
		else { showRules(); }
	}
	function hideCards(active,card) {
		active.hide().removeClass('active');
		card.hide().removeClass('active');
	}
	function shuffleCards(animate) {
		values = {};
		game.block();
		if (animate) {
			if (hasClass(game.el,'shuffling')) { game.removeClass('shuffling'); }
			else { game.addClass('shuffling'); }
		}
		var i = numCards;
		do { i = i - 1; setupCard(cards[i],i); } while (i);
	}
	function startPreview(e) {
		if (e) { e.preventDefault(); }
		var container = $('#container')[0];
		if (!hasClass(container,'started')) { setupWinCard(); }
		addClass(container,'started');
		hideRules();
		var i = cdtimers.length;
		if (i) { do { i = i - 1; clearTimeout(cdtimers.pop()); } while (i); }
		cdtimers.push(setTimeout(function() {
			var i = numCards;
			do { i = i - 1; cards[i].reveal(); } while (i);
			cdtimers.push(setTimeout(startCountdown,750));
		},600));
	}
	function endPreview() {
		var i = numCards;
		do { i = i - 1; cards[i].hide(); } while (i);
		clearInterval(timer);
		startGame();
	}
	function startCountdown() {
		var down = $('#down')[0];
		down.innerHTML = formatTimer(config.previewTime / 1000);
		removeClass(down,'off');
		addClass($('#up')[0],'off');
		timer = setInterval(timeDown,1000);
	}
	function timeDown() {
		var down = $('#down')[0];
		var current = parseInt(down.innerHTML,10) - 1;
		down.innerHTML = formatTimer(current);
		if (current === 0) {
			addClass(down,'off');
			endPreview();
		}
	}
	function startTimer() {
		var up = $('#up')[0];
		up.innerHTML = '00:00';
		removeClass(up,'off');
		startTime = new Date();
		timer = setInterval(timeUp,1000);
	}
	function formatTimer(n) {
		return n < 10 ? '0' + n : n;
	}
	function timeUp() {
		var now = new Date();
		var diff = (now - startTime) / 1000;
		var minutes = Math.floor(diff / 60);
		var seconds = Math.floor(diff % 60);
		$('#up')[0].innerHTML = formatTimer(minutes) + ':' + formatTimer(seconds);
	}
	function startGame() {
		if (!hasClass($('#rules')[0],'show')) { game.unblock(); }
		startTimer();
	}
	function resetGame() {
		addClass($('#up')[0],'off');
		addClass($('#down')[0],'off');
		game.removeClass('victory');
		clearInterval(timer);
		shuffleCards(true);
	}
	function restartGame(e) {
		if (e) { e.preventDefault(); }
		resetGame();
		setTimeout(startPreview,750);
	}
	function playAgain(e) {
		if (e) { e.preventDefault(); }
		setupWinCard();
		restartGame();
	}
	function setupWinCard() {
		var num = random();
		document.querySelector('#winnersImg').src = 'img/bigdroids/droid' + num + '.png';
		document.querySelector('#droidName').innerHTML = config.droids[num];
	}
	function winGame() {
		game.block().addClass('victory');
		removeClass($('#up')[0],'off');
		removeClass($('#header')[0],'countup');
		clearInterval(timer);
	}
})();

