const MOWER_SPEED = 150;
const SPIDER_SPEED = 100;

function randomArrayValue(array) {
    return array[Math.floor(Math.random() * array.length)]
}

class GardenScene extends Phaser.Scene {
    constructor() {
        super("GardenScene");
    }

    preload() {
        this.load.path = "assets/";
        this.load.spritesheet("worryspider", "worryspider.png",
                            {frameWidth: 16, frameHeight: 16});
        this.load.spritesheet("lawnmower", "lawnmower.png",
                            {frameWidth: 16, frameHeight: 16});
        this.load.image("apple", "apple.png");
        this.load.tilemapTiledJSON("garden", "garden.json");
        this.load.image("gardentiles", "gardentiles.png");
        this.load.image("blood", "heart.png");
        this.load.audio("music", "music.mp3");
        this.load.audio("lawnmower", "lawnmower.ogg")
        this.load.audio("apple", "apple.ogg")
    }

    create() {
        // Initialize some important variables
        this.score = 0;
        this.hasApple = false;
        this.gameOver = false;

        // Create animations
        this.makeAnims("worryspider", [
            ["idle", 0, 3],
            ["down", 5, 8],
            ["up", 10, 13],
            ["left", 15, 19],
            ["right", 20, 24],
        ]);
        this.makeAnims("lawnmower", [
            ["down", 0, 1],
            ["up", 2, 3],
            ["left", 4, 5],
            ["right", 6, 7]
        ]);

        // Add objects
        this.map = this.make.tilemap({
            key: "garden",
            tileWidth: 16, tileHeight: 16
        });
        var tileset = this.map.addTilesetImage("tiles", "gardentiles");
        this.map.createStaticLayer("Grass", tileset);
        var obstacles = this.map.createStaticLayer("Obstacles", tileset);
        this.map.setCollision([1,2]);
        this.map.createStaticLayer("Scenery", tileset);

        this.worryspider = this.physics.add.sprite(
            this.map.widthInPixels / 2, this.map.heightInPixels / 2,
            "worryspider"
        );

        this.lawnmowers = this.add.group();
        for (const lawnmower of this.map.getObjectLayer("Lawnmowers").objects) {
            let newmower = this.physics.add.sprite(lawnmower.x, lawnmower.y, "lawnmower");
            newmower.orientation = lawnmower.properties[0].value;
            this.setMowerDirection(newmower);
            this.lawnmowers.add(newmower);
        }

        // Create a list of suitable spawning locations for apples, then spawn one
        this.applespawners = this.map.getObjectLayer("Applespawners").objects.map((spawner) => ({x: spawner.x - 8, y: spawner.y -8}));
        var firstspawner = randomArrayValue(this.applespawners);
        this.apple = this.physics.add.sprite(firstspawner.x, firstspawner.y, "apple");

        // Create hitbox for the basket
        var urnobj = this.map.getObjectLayer("Urn").objects[0];
        this.urn = this.add.zone(urnobj.x + 16, urnobj.y + 16, urnobj.width, urnobj.height);
        this.physics.world.enable(this.urn);

        // Create collisions
        this.physics.add.collider(this.worryspider, obstacles);

        // Worryspiders pick up apples
        this.physics.add.overlap(this.worryspider, this.apple, function() {
            this.hasApple = true;
        }, (function() { return !this.hasApple; }).bind(this), this);

        // Worryspiders drop apples in baskets
        this.physics.add.overlap(this.worryspider, this.urn, function() {
            this.hasApple = false;
            this.score += 1;
            this.sound.play("apple");

            var newspawn = randomArrayValue(this.applespawners);
            this.apple.body.x = newspawn.x;
            this.apple.body.y = newspawn.y;
        }, (function() { return this.hasApple; }).bind(this), this);

        // Lanwmowers run over worryspiders
        this.physics.add.overlap(this.worryspider, this.lawnmowers, function(ws) {
            this.gameOver = true;
            var position = ws.body.center;
            this.add.particles("blood", 0, {
                x: position.x,
                y: position.y,
                radial: true,
                speed: 200,
                lifespan: 1000,
            });
            ws.destroy();
            this.sound.play("lawnmower");
            this.time.delayedCall(2000, function() {
                this.sound.stopAll();
                this.scene.start("GameOverScene", {score: this.score});
            }, [], this);
        }, () => true, this);

        // Lawnmowers turn around when they hit walls
        this.physics.add.collider(this.lawnmowers, obstacles, function(mower) {
            mower.setVelocity(0);
            switch (mower.orientation) {
                case "up":
                    mower.orientation = "down";
                    break;
                case "down":
                    mower.orientation = "up";
                    break;
                case "right":
                    mower.orientation = "left";
                    break;
                case "left":
                    mower.orientation = "right";
                    break;
            }
            this.setMowerDirection(mower);
        }, () => true, this);

        this.cursors = this.input.keyboard.createCursorKeys();

        this.sound.play("music", {loop: true});
    }

    update(time, delta) {
        if (this.gameOver) {
            return;
        }

        // Worryspider's movement code
       this.worryspider.body.setVelocity(0);
        if (this.cursors.up.isDown) {
           this.worryspider.body.setVelocityY(-SPIDER_SPEED);
        } else if (this.cursors.down.isDown) {
           this.worryspider.body.setVelocityY(SPIDER_SPEED);
        }
        if (this.cursors.left.isDown) {
           this.worryspider.body.setVelocityX(-SPIDER_SPEED);
        } else if (this.cursors.right.isDown) {
           this.worryspider.body.setVelocityX(SPIDER_SPEED);
        }

        if (this.cursors.left.isDown) {
           this.worryspider.anims.play("worryspider-left", true);
        } else if (this.cursors.right.isDown) {
           this.worryspider.anims.play("worryspider-right", true);
        } else if (this.cursors.up.isDown) {
           this.worryspider.anims.play("worryspider-up", true);
        } else if (this.cursors.down.isDown) {
           this.worryspider.anims.play("worryspider-down", true);
        } else {
           this.worryspider.anims.play("worryspider-idle", true);
        }

        // Apple handling code past here
        if (this.hasApple) {
            this.apple.body.x = this.worryspider.body.x;
            this.apple.body.y = this.worryspider.body.y - 16; // pixels
        }

    }

    makeAnims(prefix, spec) {
        function makeAnim(name, start, end) {
            return {
                key: prefix + "-" + name,
                frames: this.anims.generateFrameNumbers(prefix, {start: start, end: end}),
                frameRate: 12,
                repeat: -1
            }
        }
        for (const anim of spec) {
            this.anims.create(makeAnim.apply(this, anim));
        }
    }

    setMowerDirection(mower)
    {
        mower.setVelocity(0);
        switch (mower.orientation) {
            case "up":
                mower.setVelocityY(-MOWER_SPEED);
                break;
            case "down":
                mower.setVelocityY(MOWER_SPEED);
                break;
            case "left":
                mower.setVelocityX(-MOWER_SPEED);
                break;
            case "right":
                mower.setVelocityX(MOWER_SPEED);
                break;
        }
        mower.anims.play("lawnmower-" + mower.orientation);
    }

}
