var Vector = function(x, y){
    this.x = x;
    this.y = y;

    this.sub = function(other){
        return new Vector(
            this.x - other.x,
            this.y - other.y
        );
    }
    this.isub = function(other){
        this.x -= other.x;
        this.y -= other.y;
    }
    this.iadd = function(other){
        this.x += other.x;
        this.y += other.y;
    }
    this.length = function(){
        return Math.sqrt(this.x*this.x + this.y*this.y);
    }
    this.idiv = function(scalar){
        this.x /= scalar;
        this.y /= scalar;
    }
    this.zero = function(){
        this.x = 0;
        this.y = 0;
    }
	this.imul = function(scalar) {
		this.x *= scalar;
		this.y *= scalar;
	}
    this.validate = function(){
        if(isNaN(this.x+this.y)){
            this.x = 0;
            this.y = 0;
        }
    }
}
            
var Particle = function(canvas){

	var p1_score = 0;
	var p2_score = 0;
	var p1_score_text = document.getElementById('p1-score');
	var p2_score_text = document.getElementById('p2-score');

    var initial_speed = 2.0;
    var speed_limit = 6.0;
    var bounce_damping = 1; // No damping
    
    this.acceleration = new Vector(0, 0);

    this.velocity = new Vector(
        Math.random() * initial_speed - initial_speed * 0.5,
        Math.random() * initial_speed - initial_speed * 0.5
    )
    this.position = new Vector(
        //Math.random() * canvas.width,
		canvas.width /2,
        Math.random() * canvas.height
    )

	this.resetScore = function() {
		p1_score = 0;
		p2_score = 0;
		p2_score_text.innerHTML = p1_score;
		p2_score_text.innerHTML = p2_score;
	}
	this.resetParticle = function() {
		//TODO: Make sure angle is not too extreme!
		this.velocity = new Vector(
	        Math.random() * initial_speed - initial_speed * 0.5,
	        Math.random() * initial_speed - initial_speed * 0.5)
	    this.position = new Vector(canvas.width /2, Math.random() * canvas.height);
	}

    this.step = function(colliders){
        this.acceleration.validate();
        this.velocity.iadd(this.acceleration);
       
        speed = this.velocity.length();
        if(speed > speed_limit){
            this.velocity.idiv(speed/speed_limit);
        }
        this.position.iadd(this.velocity);
        this.acceleration.zero();

		for(var i = 0; i < 2; i++) {
			if(colliders[i].collides(this.position)) {
				this.velocity.x *= -bounce_damping;
				//(Check velocity vector and do border bounce in right direction. Eventually checking where it hit on paddle).
			}
		}

        // border bounce
        if(this.position.x < 0){
			p2_score++;
			p2_score_text.innerHTML = p2_score;
			
			//Reset Particle... 
			this.resetParticle();
        }
        else if(this.position.x > canvas.width){
			p1_score++;
			p1_score_text.innerHTML = p1_score;
			//Reset Particle...
			this.resetParticle();

        }

        if(this.position.y < 0){
            this.position.y = 0;
            this.velocity.y *= -bounce_damping;
			this.velocity.iadd(this.velocity);
        }
        else if(this.position.y > canvas.height){
            this.position.y = canvas.height;
            this.velocity.y *= -bounce_damping;
			this.velocity.iadd(this.velocity);
        }
    }
    this.draw = function(context){
        context.beginPath();
        context.arc(this.position.x, this.position.y, 2.5, 0, Math.PI*2, false);
        context.fill();
    }
}

var Paddle = function(canvas, xPos) {

	var height = 26;
	var width = 6;
	this.position = new Vector(xPos, canvas.height/2 - (height/2));
	
	var stepDir = 0;
	var stepSpeed = 2;
	
	this.step = function() {
		if(!(this.position.y > canvas.height - (height+2) && stepDir > 0) && !(this.position.y < 2 && stepDir < 0)) {
			this.position.y +=stepDir;
		}
	}
	
	this.draw = function(context) {
		context.fillRect(this.position.x - (width/2), this.position.y, width,height);
	}
	this.moveUp = function() {
		stepDir = -stepSpeed;
	}
	this.moveDown = function() {
		stepDir = stepSpeed;
	}
	this.stopMove = function() {
		stepDir = 0;
	}
	
	this.collides = function(other){
		if(this.position.x < other.x && this.position.x+width > other.x && this.position.y < other.y && this.position.y+height > other.y){
			return true;
		}
		else {
			return false;
		}
	}
}
var AIPaddle = function(canvas,xPos) {
	var paddle = new Paddle(canvas, xPos);
	
	this.step = function(particle) {
		if(particle.position.y < paddle.position.y + 13) {
			paddle.moveUp();
		}
		else if(particle.position.y > paddle.position.y + 13) {
			paddle.moveDown();
		}
		else {
			paddle.stopMove();
		}
		paddle.step();
	}
	this.draw = function(context) {
		paddle.draw(context);
	}
	
	this.collides = function(other) {
		return paddle.collides(other);
	}
}

var System = function(amount, milliseconds){
    var factor = 9;
    var min_proximity = 4;

    var canvas = document.getElementById('particles');
    var context = canvas.getContext('2d');

    var particles = [];
    for(var i=0; i<amount; i++){
        particles.push(new Particle(canvas));
    }

	var userpaddle = new Paddle(canvas,5);
	var aipaddle = new AIPaddle(canvas, canvas.width-5);

	var colliders = [];
	colliders.push(userpaddle);
	colliders.push(aipaddle);

	document.onkeydown = function(event) {
		var keyCode;
		if(event == null) {
			keyCode = window.event.keyCode; 
		}
		else {
			keyCode = event.keyCode;
		}
		switch(keyCode) {
			case 65: //up
				userpaddle.moveUp();
			break;
			case 90: //down
				userpaddle.moveDown();
			break;
			case 82:
				particles[0].resetScore();
			break;
			default:
			break;
		}
	}
	document.onkeyup = function(event) {
		var keyCode;
		if(event == null) {
			keyCode = window.event.keyCode; 
		}
		else {
			keyCode = event.keyCode;
		}
		switch(keyCode) {
			case 65: //up
				userpaddle.stopMove();
			break;
			case 90: //down
				userpaddle.stopMove();
			break;
			default:
			break;
		}
	}
	
    setInterval(function(){
        // fading
        context.globalCompositeOperation = 'source-in';
        context.fillStyle = 'rgba(128,128,128,0.85)';
        context.fillRect(0, 0, canvas.width, canvas.height);

        // dot drawing style
        context.globalCompositeOperation = 'lighter';
        context.fillStyle = 'rgba(128,128,128,0.5)';

		//Drawing center dotted line:
		var middleLines = parseInt(canvas.height/20);
		for(var i = 0; i < middleLines; i++) {
			context.fillRect(canvas.width/2, i*20+5, 5, 16);
		}
		//Draw Border Lines
		context.fillRect(0,0, canvas.width, 2);
		context.fillRect(0,canvas.height-2, canvas.width, 2);
		
        for(var i=0, il=amount; i<il; i++){
            var a = particles[i];
            a.step(colliders);
            a.draw(context);
        }
		userpaddle.step();
		userpaddle.draw(context);
		aipaddle.step(particles[0]);
		aipaddle.draw(context);
		
    }, milliseconds);
}

var main = function(){
    var system = new System(1, 40);
};
