var display, particles, circle;

function $(id) {
	return document.getElementById(id);
}

function random(min, max) {
	return min + (max-min) * Math.random();
}

function particle(x, y) {
	this.x = x;
	this.y = y;
	this.vx = 0;
	this.vy = 0;
	this.crashed = false;
	this.age = 0;
	this.dead = false;
	this.ttl = random(30, particles.ttl);
	
	this.draw = function() {
		if (this.age < this.ttl) {
			if (this.crashed) {
				this.vx *= particles.spring;
				this.vy *= particles.spring;
				this.collide();
			}
			this.update();
		} else {
			this.dead = true;
			particles.items.splice(particles.items.indexOf(this), 1);
		}
		
		if (!this.dead) {
			display.set_pixel(this.x, this.y, true);
			this.age++;
		}
	}
	
	this.collide = function() {
		for (var i=0, len = particles.items.length; i<len; i++) {
			var p = particles.items[i];
			if (this != p) {
				var dx, dy, distance, angle, tx, ty, ax, ay;
				dx = p.x - this.x;
				dy = p.y - this.y;
				distance = Math.sqrt(dx*dx + dy*dy);
				if (distance < 1) {
					angle = Math.atan2(dy, dx);
					tx = this.x + Math.cos(angle);
					ty = this.y + Math.sin(angle);
					ax = (tx - p.x) * particles.spring;
					ay = (ty - p.y) * particles.spring;
					this.vx -= ax;
					this.vy -= ay;
					p.vx += ax;
					p.vy += ay;
				}
			}
		}
	}
	
	this.update = function() {
		this.vy += particles.gravity;
		this.x += this.vx;
		this.y += this.vy;
		
		if (this.y >= display.size.pixels.height) {
			this.crashed = true;
			this.y = display.size.pixels.height - 1;
			this.vy *= particles.friction;
		}
		
		if (this.x <= 0) {
			this.x = 0;
			this.vx *= particles.friction;
		}
		
		if (this.x >= display.size.pixels.width) {
			this.x = display.size.pixels.width;
			this.vx *= particles.friction;
		}
	}
	
	return this;
}

circle = {
	draw: function(x, y, r) {
		var points = this['r'+r]();
		for (var i=0; i<points.length; i++) {
			var point = points[i];
			particles.make(x + point[1], y + point[0]);
		}
	},
	r5: function() {
		return [
			[0, 3], [0, 4], [0, 5], [0, 6],
			[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7], [1, 8],
			[2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [2, 7], [2, 8],
			[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9],
			[4, 0], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [4, 7], [4, 8], [4, 9],
			[5, 0], [5, 1], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [5, 9],
			[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6], [6, 7], [6, 8], [6, 9],
			[7, 1], [7, 2], [7, 3], [7, 4], [7, 5], [7, 6], [7, 7], [7, 8],
			[8, 1], [8, 2], [8, 3], [8, 4], [8, 5], [8, 6], [8, 7], [8, 8],
			[9, 3], [9, 4], [9, 5], [9, 6]
		];
	},
	r4: function() {
		return [
			[0, 2], [0, 3], [0, 4], [0, 5],
			[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6],
			[2, 0], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [2, 7],
			[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7],
			[4, 0], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [4, 7],
			[5, 0], [5, 1], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7],
			[6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6],
			[7, 2], [7, 3], [7, 4], [7, 5]
		];
	},
	r3: function() {
		return [
			[0, 3],
			[1, 3],
			[2, 2], [2, 3], [2, 4],
			[3, 2], [3, 3], [3, 4],
			[4, 1], [4, 2], [4, 3], [4, 4], [4, 5],
			[5, 1], [5, 2], [5, 3], [5, 4], [5, 5],
			[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6],
			[7, 0], [7, 1], [7, 2], [7, 3], [7, 4], [7, 5], [7, 6],
			[8, 0], [8, 1], [8, 2], [8, 3], [8, 4], [8, 5], [8, 6],
			[9, 0], [9, 1], [9, 2], [9, 3], [9, 4], [9, 5], [9, 6],
			[10, 1], [10, 2], [10, 3], [10, 4], [10, 5],
			[11, 2], [11, 3], [11, 4],
		];
	}
}

particles = {
	initialize: function() {
		this.ttl = 80;
		this.gravity = 0.1;
		this.friction = -0.7;
		this.spring = 0.8;
		this.items = [];
		return this;
	},
	make: function(x, y) {
		var p = new particle(x, y);
		this.items.push(p);
		return p;
	}
}

display = {
	initialize: function() {
		this.images_mode = false;
		this.container = $('display');
		this.size = this.get_size();
		this.size.pixel = 20;
		this.size.pixels = {};
		this.pixels = this.make();
		this.particles = particles.initialize();
		
		window.addEventListener("click", function(e) {
			var r = 3;
			circle.draw(
				Math.floor(e.clientX / display.size.pixel) - r,
				Math.floor(e.clientY / display.size.pixel) - r,
			r);
		}, false);
		
		this.interval = setInterval(function() {
			display.tick();
		}, 40);
	},
	tick: function() {
		this.clear_pixels();
		for (var i=0, len = this.particles.items.length; i<len; i++) {
			if (i < this.particles.items.length) {
				var p = this.particles.items[i];
				p.draw();
			}
		}
	},
	make: function() {
		this.size.pixels.width = Math.floor(this.size.width / this.size.pixel);
		this.size.pixels.height = Math.floor(this.size.height / this.size.pixel);
		var len = this.size.pixels.width * this.size.pixels.height,
			pixel, pixels = [], x = 0, y = 0;
		this.len = len;
		
		for (var i=0; i<len; i++) {
			pixel = this.new_pixel(x * this.size.pixel, y * this.size.pixel);
			pixels.push(pixel);
			
			if (x + 1 >= this.size.pixels.width) {
				x = 0, y++;
			} else {
				x++;
			}
		}
		
		return pixels;
	},
	new_pixel: function(x, y) {
		if (!this.images_mode) {
			var pixel = document.createElement('input');
			pixel.type = 'checkbox';
		} else {
			var pixel = document.createElement('div');
		}
		pixel.style.left = x + 'px';
		pixel.style.top = y + 'px';
		this.container.appendChild(pixel);
		return pixel;
	},
	set_pixel: function(x, y, checked) {
		x = Math.floor(x);
		y = Math.floor(y);
		var pixel = this.pixels[y * this.size.pixels.width + x];
		if (pixel.className != 'checked forever') {
			if (!this.images_mode) {
				if (checked && !pixel.checked) {
					pixel.checked = true;
				} else if (!checked && pixel.checked) {
					pixel.checked = false;
				}
			} else {
				pixel.className = checked ? 'checked' : '';
			}
		}
		return pixel;
	},
	get_pixel: function(x, y) {
		x = Math.floor(x);
		y = Math.floor(y);
		return this.pixels[y * this.size.pixels.width + x].checked;
	},
	set_forever: function(x, y) {
		x = Math.floor(x);
		y = Math.floor(y);
		var pixel = this.pixels[y * this.size.pixels.width + x];
		if (!this.images_mode) {
			pixel.checked = true;
			pixel.className = 'forever';
		} else {
			pixel.className = 'checked forever';
		}
	},
	clear_pixels: function() {
		for (var i=0, len = this.pixels.length; i<this.len; i++) {
			if (this.pixels[i].className != 'checked forever')
			if (!this.images_mode) {
				this.pixels[i].checked = false;
			} else {
				this.pixels[i].className = '';
			}
		}
	},
	get_size: function() {
		return {width: window.innerWidth, height: window.innerHeight};
	}
}

if (window.addEventListener) {
	window.addEventListener("load", function() {
		display.initialize();
	}, false);
}