
var dilemma = {

	dice: [],
	ctx: null,
	canvas: { 
		color: "black",
		size: 40,
		offset: 50,
		space: 10
	},

	positions: [
		[4,5,6,7,8,9], 		/* cell 0 */
		[8,9], 			/* cell 1 */
		[2,3,4,5,6,7,8,9], 	/* cell 2 */
		[6,7,8,9], 		/* cell 3 */
		[1,3,5,7,9], 		/* cell 4 */
		[6,7,8,9], 		/* cell 5 */
		[2,3,4,5,6,7,8,9], 	/* cell 6 */
		[8,9], 			/* cell 7 */
		[4,5,6,7,8,9] 		/* cell 8 */
	],
	cheat: null,
	start_auto_onload: true,
        roll_prop : {
                count: 0,
                max_count: 8,
                time: 350,
                prev: 0
        },
	
	countSides: function() {
	
		var solutions = this.countSolutions();
		if (solutions <= 3 || solutions == 6) {
			return 6;
		}
		else {
			return solutions;
		}
	},

	countSolutions: function() {
	
		var solutions = 0;
		
		$('.dilemma-solution').each(function() {
			if ( $.trim( $(this).val() ).length !== 0)
				solutions +=1 ;
		});
		
		return solutions;
	},

	recalculateAssignedNumbers: function(assignToDice) {
		
		var sidesPerSolution = this.countSides() / this.countSolutions();

		var ass = 1;
		$('#solutions li').each(function(index) {
			if ( $.trim( $(this).children('.dilemma-solution').val() ).length !== 0) {
				for(var i = 0; i < sidesPerSolution; i++) {
					dilemma.dice[ ass ] = index;
					ass += 1;
				}
			}
		});	
	},

	hashChange: function(e) {

		if (dilemma.solving)
			return;

		dilemma.deserialize();

	},

	addRow: function(animate) {
                
		if ($('#solutions li').length >= 9)
		        return;

                var clone = $('#solutions li:last').clone(true);
                clone.children('input').val('');
                clone.children('.assigned-number').text('');
                $('#solutions').append( clone );

		if (animate)
	                $('#solutions li:last').hide().slideDown();
 
 		$('#solutions li:last input').focus();
																				
	},
	
	parseLocation: function (parseMe) {
		var urlParams = {};
		var e,
		a = /\+/g,  // Regex for replacing addition symbol with a space
		r = /([^&=]+)=?([^&]*)/g,
		d = function (s) { return decodeURIComponent(s.replace(a, " ")); };
		
		while (e = r.exec(parseMe)) {
			urlParams[d(e[1])] = $.trim( d(e[2]) );
		}
			
		return urlParams;
	},

	deserialize: function(fromOnload) {
		var urlParams;

		var currentHash = (location.href.split("#")[1] || "");

		if (currentHash.length !== 0) {
			urlParams = this.parseLocation(currentHash);
		} else {
			urlParams = this.parseLocation(location.search.substring(1));

			/* convert old style query string */
			var s = [];
			if (urlParams['s1']) s.push( urlParams['s1'] );
			if (urlParams['s2']) s.push( urlParams['s2'] );
			if (urlParams['s3']) s.push( urlParams['s3'] );
			
			urlParams['s'] = s.join('|');
		}
	
		if (urlParams['d']) {
			$('#description').val(urlParams['d']);
		}
		
		if (urlParams['a']) {
			this.cheat = urlParams['a'];
		}
		
		if (urlParams['auto'] == 0) {
			this.start_auto_onload = false;
		}
	
		if (urlParams['s']) {
			var solutions = urlParams['s'].split('|', 9);

			for(var i = 0; i < solutions.length; i++)
				solutions[i] = $.trim( solutions[i] );


			for(var i = $('.dilemma-solution').length; i < solutions.length; i++) {
				this.addRow(false);
			}

			var index = 0;
			$('.dilemma-solution').each(function() {

				if ( solutions[ index ]) {
					$(this).val( solutions[ index ]);
				} else {
					$(this).val('');
				}

				index += 1;
			});

			this.recalculateAssignedNumbers();

			if (this.start_auto_onload && fromOnload) {
				this.solve(fromOnload);
			}
		}

	},

	serialize: function() {

		var hash = '';

		if ( $.trim( $('#description').val() ).length) {
			hash += 'd=' + encodeURIComponent( $.trim( $('#description').val() ) ).replace(/%20/g, '+');
		}

		var count = 0;
		$('.dilemma-solution').each(function() {

			if ( $.trim( $(this).val() ).length) {

				if (count == 0) {
					if (hash) hash += '&';
					hash += 's=';
				}
				if (count++) hash += '|';
				hash += encodeURIComponent( ( $.trim($(this).val()) )).replace(/%20/g, '+');
			}
		});
		
		if (!this.start_auto_onload) {
			if (hash) hash += '&';
			hash += 'auto=0';
		}

		if (hash)
			location.hash = '#' + hash;

	},

	enable: function() {
	        $('#add-solution, #solve, #description, .dilemma-solution').removeAttr('disabled').removeClass('disabled');
	},

	disable: function() {
		$('#add-solution, #solve, #description, .dilemma-solution').attr('disabled', 'disabled').addClass('disabled');
	},

	solving: false,
	solve: function(fromOnload) {
	
		this.recalculateAssignedNumbers(true);
		
		this.serialize();

		if (location.search.length !== 0) {
			location.search = '';
			return;
		}
  
		if (this.countSolutions() < 2) {
			if (!fromOnload) {
				$('#error-message').show();
                                $('#found-solution-okay').hide();
				$('#found-solution-wrapper').fadeIn(400, function() {
					$('html').addClass('containerVisible');
				});
			}
			return;
		}

		$('#error-message').hide();
		$('#found-solution-okay').show();

		var description = $.trim( $('#description').val() );

		if (fromOnload && window._gaq) window._gaq.push(['_trackEvent', 'button', 'from-onload']);

                if (window._gaq) window._gaq.push(['_trackEvent', 'roll', 'dilemma-length', 'length-'+ description.length.toString(), description.length]);
                if (window._gaq) window._gaq.push(['_trackEvent', 'roll', 'options-length',  'count-'+ this.countSolutions().toString(),  this.countSolutions()]);

                if ( description.length) {
                        $('#found-solution-stated-dilemma').show();
                        $('#found-solution-nonstated-dilemma').hide();
                        $('#found-solution-description').text( description ).show();
                } else {
                        $('#found-solution-stated-dilemma').hide();
                        $('#found-solution-nonstated-dilemma').show();
                }

		$('#found-solution-found').hide();
		$('#found-solution-wait').show()
		
                this.solving = true;
                this.disable();
                this.roll_prop.count = 0;

                $('#found-solution-wrapper').fadeIn(400, function() {
                	$('html').addClass('containerVisible');
                	
                	/* hack around IE6-8*/
                	if (window.G_vmlCanvasManager) {
                	
	                	$('#dice').remove();
	                	var canvas = document.createElement("canvas");
				canvas.width = 300;
				canvas.height = 300; 
				canvas.id = "dice";

				$('#fake-dice').append( canvas );
				if (window.G_vmlCanvasManager)
					window.G_vmlCanvasManager.initElement(canvas); 
			}
			
			var canvas = document.getElementById('dice');
		        if (canvas && canvas.getContext)
				dilemma.ctx = canvas.getContext('2d');
                	
			setTimeout('dilemma.roll()', dilemma.roll_prop.time);
		});
	},

	rolled: function(number) {

		var solution = '';
		
		if (window._gaq) window._gaq.push(['_trackEvent', 'roll', 'number', 'options-length-' + this.countSolutions().toString(), number]);

		if (this.cheat) {
			solution = this.cheat;
			this.cheat = null;
			
			if (window._gaq) window._gaq.push(['_trackEvent', 'roll', 'cheating']);
			
		} else {
			solution = $('.dilemma-solution:eq('+ this.dice[ number ] +')').val();
		}

		$('#found-solution-answer').text( solution );

		$('#found-solution-wait').slideUp();
		$('#found-solution-found').slideDown(400, function() {
			$('#found-solution-dismiss').focus();
			dilemma.solving = false;
		});


	},

	roll: function() {
	
		if (this.roll_prop.count == this.roll_prop.max_count) {
			this.rolled(this.roll_prop.prev);
			return;
		}

		this.roll_prop.count += 1;
		var thrown = 0;
		var sides = this.countSides();
		do {
			thrown = Math.floor(Math.random() * sides) + 1;
		} while(thrown == this.roll_prop.prev);

		this.roll_prop.prev = thrown;

		this.draw(thrown);
		
		setTimeout('dilemma.roll()', this.roll_prop.time);


	},

	dismiss: function() {
		$('#found-solution-wrapper').fadeOut(400, function() {
			$('html').removeClass('containerVisible');
		});
		this.enable();
	},

	draw: function(number) {

		if (!this.ctx)
			return;

		this.ctx.clearRect(0, 0, $('#dice').attr('width'), $('#dice').attr('height'));

		var counter = 0;
		for (var i = 0; i < 3; i++) {
			for (var j = 0; j < 3; j++) {
				if ($.inArray(number, this.positions[ counter ]) !== -1) {
					this.ctx.beginPath();
					this.ctx.arc(
						this.canvas.offset + j *2 * (this.canvas.size + this.canvas.space),
						this.canvas.offset + i *2 * (this.canvas.size + this.canvas.space),
						this.canvas.size,
						0, 
						2 * Math.PI, 
						false
					);
					this.ctx.fill();
				}
				counter++;
			}
		}

	}


};

$(document).ready(function() {

	$('#found-solution-needs-js').hide();
	$('#found-solution-has-js').show();

	$('#found-solution-wrapper').hide(0, function() {
		$('html').removeClass('containerVisible');
	});

	$(window).bind('hashchange', dilemma.hashChange );

	$('#add-solution').click(function() {
	
		if (dilemma.solving)
			return;
	
               if (_gaq) _gaq.push(['_trackEvent', 'button', 'add', 'field-'+ $('.dilemma-solution').length.toString(), $('.dilemma-solution').length ]);

		dilemma.addRow(true);
	});
	
	$('.dilemma-solution').keyup(function(event) {
		dilemma.countSolutions();

		if (event.which == 13) {
			$('#solve').click();
			event.preventDefault();
		}
	});

	$('#found-solution-dismiss').click(function() {

		if (_gaq) _gaq.push(['_trackEvent', 'button', 'dismiss']);

		dilemma.dismiss();
	});
	
	$('#found-solution-error').click(function() {
	
		if (_gaq) _gaq.push(['_trackEvent', 'button', 'dismiss-error']);

		dilemma.dismiss();
	});

	$('#solve').click(function() {
	
		if (dilemma.solving)
			return;
               
		if (_gaq) _gaq.push(['_trackEvent', 'button', 'solve']);

		dilemma.solve(false);
	});


	$('#found-solution-wrapper').keyup(function(e) { 
		if (e.which == 27) { // esc
			$('#found-solution-dismiss').click();
			event.preventDefault();
		}
	});

	$('.button').keyup(function(e) {
		if (e.which == 32) { // space
			$(this).click();
			event.preventDefault();
		}
	});



	dilemma.enable();
	dilemma.deserialize(true);

});


