//the ending entity controls all the stuff that happens 
//when the game ends, it changes the game's scale and moves the
//player and ralph around to the correct positions
ig.module('game.entities.ending')
.requires(
    'impact.impact',
    'game.entities.building-top',
    'game.entities.person',
    'game.entities.win-cube',
    'game.entities.bush',
    'game.people',
    'game.entities.ralph',
    'game.behavior',
    'game.movement-style',
    'game.path'
)
.defines(function () {
    "use strict";
    ig.global.EntityEnding = ig.Entity.extend({
        people: null,
        roof: null,
        block: null,
        isEnding: true,
        stage: 0, //this is the part of the ending sequence we are at
        init: function (x, y, settings) {
            //we only want to lock updates not rundering
            ig.game.player.updateLock = true;
            //since we have just finished a transition the player is likely
            //locked, we should unlock him
            ig.game.player.lock = false;
            var ralph = ig.game.ralph;
            UI.Timer.pauseTimer();
            this.people = new People();
            this.roof = ig.game.spawnEntity(EntityBuildingTop, 0, 0);
            this.roof.pos.x = ig.system.width / 2 - this.roof.size.x / 2;
            this.roof.pos.y = ig.system.height - this.roof.size.y;

            //lock and position ralph
            //set his behaivor to nothing so that we can take control
            ralph.behavior = function () { };
            //set his animation to the big idle animation
            ralph.currentAnim = ralph.endingAnims.idle;
            //set the offset to zero so we can reason about ralph's position
            ralph.offset = { x: 0, y: 0 };
            ralph.vel = { x: 0, y: 0 };
            ralph.renderLock = false;
            //set his position to be standing on the roof and
            //just a tad to the right of the center of the roof
            ralph.pos.x = this.roof.pos.x + this.roof.size.x / 2 + IMG.SIZE(20);
            ralph.pos.y = this.roof.pos.y - ralph.currentAnim.sheet.height;

            //spawn the little block thing
            this.block = ig.game.spawnEntity(EntityWinCube, 0, 0);
            this.block.pos.x = this.roof.pos.x + (this.block.size.x / 2);
            this.block.pos.y = this.roof.pos.y - this.block.size.y;

            this.people.setPosition(this.roof.pos.x + IMG.SIZE(200) + this.block.size.x, this.roof.pos.y - this.people.entities[0].size.y);
            //we want the first person to be back a ways
            this.people.entities[0].pos.x = this.roof.pos.x + this.people.entities[0].size.x;

            this.people.entities[0].movement = this.constructFirstMovement();

            //set the player's position
            ig.game.player.pos.x = this.roof.pos.x + 2.2 * ig.game.player.size.x;
            ig.game.player.pos.y = this.roof.pos.y - IMG.SIZE(240);
            ig.game.player.currentAnim = ig.game.player.winAnim;

            ig.game.sortEntities();
            this.parent(x, y, settings);
        },
        constructFirstMovement: function () {
            var start = {
                x: this.people.entities[0].pos.x,
                y: this.people.entities[0].pos.y
            };
            var end = {
                x: this.people.entities[1].pos.x - this.people.entities[0].size.x - IMG.SIZE(10),
                y: this.people.entities[0].pos.y
            };
            return new Movement(start, end, 1);
        },
        constructSecondMovement: function () {
            var start = {
                x: this.people.entities[0].pos.x + IMG.SIZE(60),
                y: this.people.entities[0].pos.y
            };
            var end = {
                x: this.roof.pos.x + this.roof.size.x - this.people.getSize().x,
                y: this.roof.pos.y - this.people.getSize().y
            };
            return new Movement(start, end, 2);
        },
        constructThirdMovement: function () {
            var ralph = ig.game.ralph;
            var start = {
                x: ralph.pos.x,
                y: ralph.pos.y
            };
            var end = {
                x: ig.system.width + ralph.currentAnim.sheet.width,
                y: ralph.pos.y
            };
            var style = function (time) { return IMG.SIZE(-100) * MovementStyle.sin(time); };
            return new PathBase([start, end], 1, [style]);

        },
        update: function () {
            switch (this.stage) {
                case 0:
                    if (this.people.entities[0].movement.isDone()) {
                        this.stage += 1;
                        this.people.setMovement(this.constructSecondMovement());
                    }
                    break;
                case 1:
                    var ralph = ig.game.ralph;
                    //have the people pick up ralph
                    //note that because this changes ralph's position
                    //once this is true the first time it will be true
                    //for the rest of the stage
                    if (this.people.getPosition().x >= ralph.pos.x) {
                        ralph.currentAnim = ralph.endingAnims.carry;
                        ralph.offset = { x: 0, y: IMG.SIZE(117) };
                        ralph.pos = this.people.getPosition();
                    }
                    if (this.people.entities[0].movement.isDone()) {
                        var path = this.constructThirdMovement();
                        ralph.behavior = Behavior.followBasicPath.bind(window, new ig.Timer(), ralph, path, function () { });
                        this.stage += 1;
                    }
                    break;
                case 2:
                    var ralph = ig.game.ralph;

                    if (ralph.pos.x >= ig.system.width) {
                        ralph.behavior = function () { };
                        ig.game.spawnEntity(EntityFall, 0, 0);
                        this.kill();
                    }
                    break;
            }
            this.parent();
        },
        kill: function () {
            this.roof.kill();
            this.people.kill();
            this.block.kill();
            this.parent();
        }
    });
    ig.global.EntityFall = ig.Entity.extend({
        fallLevel: null,
        ralph: null,
        spinTimer: null,
        spinFrequency: 1, //number of seconds between spins
        bushes: [],
        init: function (x, y, settings) {
            //ig.game.spawnEntity(EntityBush, 0, 0);
            //now we really do want to stop the player from drawing
            ig.game.player.lock = true;
            //we are going to use the first level as the backdrop for our falling
            this.fallLevel = XmlLoader.parseXLevel(XmlLoader.getXLevel(XmlLoader.getXStage(0), 0), IMG.SIZE(-1500), -ig.system.width / 2 - IMG.SIZE(1010 / 4));
            this.ralph = ig.game.ralph;

            var bottomSegment = this.fallLevel.floors[0].getBuildingSegment();
            this.spawnBushes(0, bottomSegment.pos.y);
            this.ralph.offset = { x: 0, y: 0 };
            this.ralph.pos.x = 2 * (this.fallLevel.floors[0].getBuildingSegment().size.x / 5);
            this.ralph.pos.y = ig.system.height - this.fallLevel.floors[0].getBuildingSegment().size.y - IMG.SIZE(200);
            this.ralph.currentAnim = this.ralph.endingAnims.fall;
            UI.Sizeing.scale(2);
            this.fallLevel.setProperty("vel", { x: 0, y: IMG.SIZE(-500) });
            this.bushes.forEach(function (val) { val.vel = { x: 0, y: IMG.SIZE(-500)} });
            this.spinTimer = new ig.Timer();
            this.parent(x, y, settings);


        },
        spawnBushes: function (x, y) {
            //make a first entity to calculate size and whatnoe
            this.bushes.push(ig.game.spawnEntity(EntityBush, x, y));
            var realy = y - this.bushes[0].size.y;
            //this should more or less cover the whole bottom of the screen once we have shrunk it
            var numBushes = Math.round(ig.system.width / this.bushes[0].size.x);
            this.bushes[0].pos.y = realy;
            var stride = this.bushes[0].size.x;
            for (var i = 1; i < numBushes; i++) {
                this.bushes.push(ig.game.spawnEntity(EntityBush, i * stride, realy));
            }
        },
        update: function () {
            if (this.spinTimer.delta() >= this.spinFrequency && this.ralph.currentAnim === this.ralph.endingAnims.fall) {
                this.spinTimer.reset();
                this.ralph.currentAnim.angle += Math.PI / 4;
            }
            //check if we have hit the ground
            if (this.fallLevel.floors[0].getBuildingSegment().pos.y <= this.ralph.pos.y - this.fallLevel.floors[0].getBuildingSegment().size.y + this.ralph.size.y) {
                this.fallLevel.setProperty("vel", { x: 0, y: 0 });
                this.bushes.forEach(function (val) { val.vel = { x: 0, y: 0} });
                this.ralph.offset = { x: 0, y: IMG.SIZE(-211) };
                this.ralph.size = { x: IMG.SIZE(260), y: IMG.SIZE(116) };
                this.ralph.currentAnim = this.ralph.endingAnims.smash;
                window.setTimeout(UI.MainMenu.showMainMenu, 5000);
            }
            this.parent();
        }
    });
});
