class Vector2D {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

class Entity {
    constructor(pos, vel, size, color) {
        this.pos = pos;
        this.vel = vel;
        this.size = size;
        this.color = color;
    }

    collides(e) {
        return !(this.pos.x > e.pos.x + e.size.x || this.pos.x + this.size.x < e.pos.x)
            && !(this.pos.y > e.pos.y + e.size.y || this.pos.y + this.size.y < e.pos.y);
    }
}

var player = new Entity(
    new Vector2D(50, 0),
    new Vector2D(0, 0),
    new Vector2D(100, 100),
    "#FF0000"
);

var enemies = [];

var spawnCooldown = 0;

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

// resize the canvas to fill browser window dynamically
window.addEventListener('resize', resizeCanvas, false);

document.onkeypress = function(evt) {
    evt = evt || window.event;
    var charCode = evt.keyCode || evt.which;
    var charStr = String.fromCharCode(charCode);
    evt.preventDefault();
    onKeyPress(charStr);
};

function resizeCanvas() {
    c.width = window.innerWidth;
    c.height = window.innerHeight;

    draw();
}

resizeCanvas();

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

function drawEntity(e) {
    ctx.fillStyle = e.color;
    ctx.fillRect(e.pos.x, e.pos.y, e.size.x, e.size.y);
}

function draw() {
    ctx.clearRect(0, 0, c.width, c.height);
    drawEntity(player);

    enemies.forEach(drawEntity);
}

function update() {
    // Spawn enemies
    if (enemies.length < 5 && spawnCooldown <= 0) {
        enemies.push(new Entity(new Vector2D(c.width + randInt(50, 100), 0), new Vector2D(randInt(-15, -5), 0), new Vector2D(randInt(50, 200), randInt(50, 200)), "#00FF00"));
        spawnCooldown = randInt(1 * 60, 3 * 60); // 1-3 seconds
    }
    spawnCooldown--;

    // Apply physics to all entities
    (enemies.concat([player])).forEach(function (e) {
        e.pos.x += e.vel.x;
        e.pos.y += e.vel.y;

        e.vel.y += 1;
        if (e.pos.y + e.size.y > c.height) {
            e.vel.y = 0;
            e.pos.y = c.height - e.size.y;
        }

    });

    // Recolor enemies
    enemies.forEach(function (e) {
        if (e.pos.x < player.pos.x) {
            e.color = "#0000FF";
        }
    });

    // Kill enemies
    enemies = enemies.filter(function (e) {
        return e.pos.x > -e.size.x;
    });

    // Kill player
    enemies.forEach(function (e) {
        if (e.collides(player)) {
            console.log("Game over!");
            clearInterval(interval);
        }
    });
}

function onKeyPress(key) {
    switch (key) {
        case "w":
            if (player.pos.y + player.size.y == c.height) {
                player.vel.y = -40;
            }
            break;
    }
}

function mainloop() {
    update();
    draw();
}

var interval = setInterval(mainloop, 1000 / 60); // 60 fps
