﻿function Particle(x, y) {

	// Initialise position and velocity
	this.X = x;
	this.Y = y;
	this.velX = 0;
	this.velY = 0;

	// Initial size
	this.size = 1;

	// Scaling over time coefficient, 0 = no change, values below 1 will cause it to shrink, values above 1 will cause it to grow
	this.shrink = 1.06;

	// Drag coefficient, 0 = no drag, 1 = maximum drag
	this.drag = 1;

	// Increases Y velocity by this value every frame to simulate gravity
	this.gravity = 0;

	// Opacity of the particle
	this.alpha = 1;

	// Fade coefficient, 0 = no change, 1 = instantly disappears
	this.fade = 0;

	// Values saved, now pre-calculate data
	this.drag = 1 / this.drag;

	var randomShift = function () {
		return Math.ceil(Math.random() * 10);
	};

	this.red = 255;
	this.blue = 255;
	this.green = 255;

	this.redShift = randomShift();
	this.blueShift = randomShift();
	this.greenShift = randomShift();

	this.update = function () {

		// simulate drag
		this.velX *= this.drag;
		this.velY *= this.drag;

		// add gravity force to the y velocity 
		this.velY += this.gravity;

		// Invert velocity when we drift out of bounds
		if (this.X >= window.innerWidth || this.X <= 0) {
			this.velX *= -1;
		}

		if (this.Y >= window.innerHeight || this.Y <= 0) {
			this.velY *= -1;
		}

		// and the velocity to the position
		this.X += this.velX;
		this.Y += this.velY;

		// shrink the particle
		if (this.shrink) {
			// If we have gotten too bug, invert the growth coefficient
			if (this.size >= 12 || this.size < 1) {
				this.shrink = 1 / this.shrink;
			}

			this.size *= this.shrink;
		}

		// Todo: make this less rubbish
		var shifts = ["red", "blue", "green"];

		for (var i = 0; i < shifts.length; ++i) {
			var colour = shifts[i];

			var val = this[colour];

			val += this[colour + "Shift"];

			if (val >= 255) {
				this[colour + "Shift"] *= -1;
				val = 255;
			}
			else if (val <= 5) {
				this[colour + "Shift"] *= -1;
				val = 5;
			}

			this[colour] = val;
		}

		// and fade it out
		this.alpha -= this.fade;
	}

	this.render = function (c) {
		// Skip if this particle is fully transparent
		if (this.alpha == 0) return;

		// Save the current canvas state
		c.save();

		this.colour = "rgba(" + this.red + "," + this.green + "," + this.blue + "," + this.alpha + ")";

		// set the fill style to have the right alpha
		c.fillStyle = this.colour;

		// draw a circle of the required size
		c.beginPath();
		c.arc(this.X, this.Y, this.size, 0, Math.PI * 2, true);
		c.closePath();

		// set the alpha to the particle's alpha
		c.globalAlpha = this.alpha;

		// set the composition mode
		c.globalCompositeOperation = 'lighter';

		// and fill it
		c.fill();

		c.restore();
	}
}
