window.jQuery && $(document).ready(function() {
	snow.maxLeft = document.body.clientWidth - 20;
	snow.nearMaxLeft = snow.maxLeft - 30;
	//snow.maxTop = document.body.scrollHeight + 20;
	snow.maxTop = $(document).height();

	$(".drift").each(function() {
		var driftOffset = $(this).offset();
		if (snow.drifts[driftOffset.top]) {
			var driftLength = snow.drifts[driftOffset.top].length;
			snow.drifts[driftOffset.top][driftLength] = driftOffset.left;
			snow.drifts[driftOffset.top][driftLength+1] = driftOffset.left+$(this).width();
		} else {
			snow.drifts[driftOffset.top] = [driftOffset.left, driftOffset.left+$(this).width()];
		}
	});

	snow.$flakes = $("div.snow.falling");
	$("#header")
		.click(function(event) {
			snow.toggle();
		})
		.mousedown(function () {
			var newBorderStyle =
				(snow.falling ? 'outset' : 'inset');
			$(this).css('border-style', newBorderStyle);
		});


	//snow.alpha = $("#header").text();
});

var snow = {
	falling: false,
	maxLeft: 0,
	nearMaxLeft: 0,
	nearMinLeft: 30,
	maxTop: 0,
	maxMass: 5,
	maxDx: 4,
	gravity: 0.5,
	wind: 0,
	alpha: '❄❅❆❇❉❃',
	$flakes: {},
	drifts: {},
	sizeMap: {
		1: {size: 4, bottom: 3},
		2: {size: 8, bottom: 6},
		3: {size: 12, bottom: 9},
		4: {size: 16, bottom: 12},
		5: {size: 20, bottom: 15}
	},
	/*
	sizeMap: {
		1: {size: 4, bottom: 15},
		2: {size: 8, bottom: 17},
		3: {size: 12, bottom: 18},
		4: {size: 16, bottom: 20},
		5: {size: 20, bottom: 22}
	},
	*/
	random: function(min, max) {
		return Math.round(Math.random()*(max-min)+min);
	},
	oneOutOf: function(chance) {
		return Math.random() <= 1/chance;
	},
	stepTop: function(flake) {
		var flakeTop = parseInt(flake.style.top) + flake.dy;
		return flakeTop;
	},
	stepLeft: function(flake) {
		var flakeLeft = parseInt(flake.style.left);
		if (flakeLeft > snow.nearMaxLeft) {
			flake.dx--;
		} else if (flakeLeft < snow.nearMinLeft) {
			flake.dx++;
		}
		flakeLeft += flake.dx + snow.wind;
		return Math.min(snow.maxLeft, flakeLeft);
	},
	step: function() {
		var newTop = snow.stepTop(this);
		var newLeft = snow.stepLeft(this);
		if (newTop >= snow.maxTop - this.dy + snow.sizeMap[this.mass].bottom || snow.drift(this)) {
			$(this).removeClass('falling');
			snow.$flakes = snow.$flakes.not(this);
		} else {
			$(this).css({
				top: newTop + 'px',
				left: newLeft + 'px'
			});
			if (snow.oneOutOf(20)) {
				this.dy = Math.min(this.weight+3, Math.max(Math.max(1,this.weight-3), this.dy+snow.random(-1,1)));
			}
			if (snow.oneOutOf(5)) {
				this.dx = Math.min(snow.maxDx/this.weight, Math.max(-snow.maxDx/this.weight, this.dx+snow.random(-1,1)));
			}
		}
	},
	drift: function(flake) {
		if (snow.oneOutOf(3)) {
			var flakeTop = parseInt(flake.style.top);
			var flakeBottom = flakeTop + snow.sizeMap[flake.mass].bottom;
			var withinDrift = false;
			var withinDriftRange = Math.ceil(flake.dy);
			var delta;
			for (delta=0; delta<=withinDriftRange; delta++) {
				if (snow.drifts[flakeBottom+delta]) {
					withinDrift = true;
					break;
				}
			}
			if (withinDrift) {
				var flakeLeft = parseInt(flake.style.left);
				var driftX = snow.drifts[flakeBottom+delta];
				for (i=0; i<driftX.length; i+=2) {
					if (flakeLeft >= driftX[i] && flakeLeft <= driftX[i+1]) {
						$(flake).css('top',flakeTop+delta+'px');
						return true
					}
				}
			}
		}
		return false;
	},
	fall: function() {
		if (snow.falling) {
			return;
		}
		snow.falling = true;
		clearInterval(snow.stepInterval);
		clearInterval(snow.windInterval);
		snow.snowInterval = setInterval(function() {
			var mass = snow.random(1,snow.maxMass);
			var randAlphaIndex = snow.random(0,snow.alpha.length-1);
			while (snow.alpha.slice(randAlphaIndex,randAlphaIndex+1) == ' ') {
				randAlphaIndex = snow.random(0,snow.alpha.length-1);
			}
			$('<div class="snow snow-alpha snow'+mass+' falling">'+snow.alpha.slice(randAlphaIndex,randAlphaIndex+1)+'</div>')
				.appendTo("body")
				.css({
					top: '-20px',
					left: snow.random(0, snow.maxLeft) + 'px'
				})
				.each(function() {
					this.mass = mass;
					this.weight = mass * snow.gravity;
					this.dy = this.weight;
					this.dx = snow.random(-snow.maxDx,snow.maxDx) / this.weight;
					snow.$flakes = snow.$flakes.add(this);
				})
		}, 2500);

		snow.stepInterval = setInterval(function() {
			snow.$flakes.each(snow.step);
		}, 50);

		snow.windInterval = setInterval(function() {
			if (snow.oneOutOf(5)) {
				var windVelocity = snow.random(-6,6);
				var windDuration = snow.random(3000,7000);
				snow.wind = Math.ceil(windVelocity/5);
				setTimeout(function() {
					snow.wind = Math.ceil(windVelocity/2);
				}, 500);
				setTimeout(function() {
					snow.wind = windVelocity;
				}, 1500);
				setTimeout(function() {
					snow.wind = Math.ceil(windVelocity/2);
				}, windDuration-1500);
				setTimeout(function() {
					snow.wind = Math.ceil(windVelocity/5);
				}, windDuration-500);
				setTimeout(function() {
					snow.wind = 0;
				}, windDuration);
			}
		}, 10000);
	},
	stop: function() {
		if (!snow.falling) {
			return;
		}
		snow.falling = false;
		clearInterval(snow.snowInterval);
		//clearInterval(snow.stepInterval);
		//clearInterval(snow.windInterval);
	},
	toggle: function() {
		if (snow.falling) {
			snow.stop();
		} else {
			snow.fall();
		}
	}
}
