ig.module(
	'game.entities.player'
)
.requires(
	'impact.entity',
	'game.entities.particle'
)
.defines(function () {

    EntityPlayer = ig.Entity.extend({

        name: 'Player',

        size: { x: 32, y: 2 },
        offset: { x: 0, y: 4 },
        halfWidth: 16,

        maxVel: { x: 15, y: 10 },
        friction: { x: 2, y: 0 },
        gravityFactor: 0,
		health: 100,
        accelWater: 50,

        numMissilesShot: 0,
        numDepthChargesShot: 0,

        type: ig.Entity.TYPE.A, 										// Player friendly collision group
        checkAgainst: ig.Entity.TYPE.NONE,
        collides: ig.Entity.COLLIDES.PASSIVE,

        waveTimer: null,
        depthChargeTimer: null,
        smokeTimer: null,
        smokeDelay: 1,

        animSheet: new ig.AnimationSheet('media/player.png', 32, 8),
        soundMissile: new ig.Sound('media/soundMissile.ogg'),
        soundDepthChargeSplash: new ig.Sound('media/soundDepthChargeSplash.ogg'),

        soundMayday: new ig.Sound('media/soundMayDay.ogg'),
        soundPlayMayday : true,



		//***********************
		// Initialise
		//***********************
        init: function (x, y, settings) {
            this.parent(x, y, settings);

            // Add the animations
            this.addAnim('idle', 0.2, [0, 1, 2]);
			this.addAnim('hit', 0.1, [1,2]);

            this.waveTimer = new ig.Timer();
            this.depthChargeTimer = new ig.Timer();
            this.smokeTimer = new ig.Timer();

            this.health = 100;
            this.soundPlayMayday;
            this.soundPlayMayday = true;

            ig.game.player = this;
        },

		
		//***********************
		// Update
		//***********************
        update: function () {

//            //Keyboard support
//            if (ig.input.state('left')) {
//                this.accel.x = -this.accelWater;
//            }
//            else if (ig.input.state('right')) {
//                this.accel.x = this.accelWater;
//            }
//            else {
//					this.accel.x = 0;
//            }


            //Accelerometer support for landscape mode
            if (ig.input.accel.y < -1 || ig.input.accel.y > 1) {
                this.accel.x = ig.input.accel.y * 1.5;
            }
            else {
                this.accel.x = 0;
            }


            //Waves
            if (this.waveTimer.delta() > 0.1) {
                if (this.vel.x < -5) {
                    ig.game.spawnEntity(EntityWaveParticle, this.pos.x + this.size.x-2, this.pos.y + 3, { vel: {x: 10, y: 5}, restrictY: true, gravityFactor: 0 });
                    ig.game.spawnEntity(EntityWaveParticle, this.pos.x, this.pos.y + 3, { vel: {x: 10, y: 5}, restrictY: true, gravityFactor: 0 });
                }
                else if (this.vel.x > 5) {
                    ig.game.spawnEntity(EntityWaveParticle, this.pos.x, this.pos.y + 3, { vel: {x: -10, y: 5}, restrictY : true, gravityFactor: 0 });
                    ig.game.spawnEntity(EntityWaveParticle, this.pos.x + this.size.x-2, this.pos.y + 3, { vel: {x: -10, y: 5}, restrictY : true, gravityFactor: 0 });
                }
                this.waveTimer.set(0);
            }

            //Smoke
            if (this.health > 0 && this.health < 90 && this.smokeTimer.delta() > this.smokeDelay) {
                var randomPos =  Math.random() * this.size.x;
                ig.game.spawnEntity(EntitySmokeParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                ig.game.spawnEntity(EntityFireParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                ig.game.spawnEntity(EntitySmokeParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                this.smokeDelay = this.health/100;
                this.smokeTimer.set(0);
            }


			//Keep within bounds of play area
			if (this.pos.x > ig.game.width - this.halfWidth)
				this.pos.x = ig.game.width - this.halfWidth;
			if (this.pos.x < 0 - this.halfWidth)
				this.pos.x = 0 - this.halfWidth;
            //If we are below the screen we must have fully sunk - so indicate we are ready to play again
            if (this.pos.y > ig.game.height) {
                this.kill();
                ig.game.setGameOver();
            }


            //Shoot
            if (ig.input.state('shoot')) {

                if (ig.input.mouse.y < this.pos.y+2) {
                    //Shoot missile
                    if (this.numMissilesShot < 1) {
                        this.soundMissile.play();
                        ig.game.spawnEntity(EntityMissile, this.pos.x + this.halfWidth, this.pos.y + 2, { targetX: ig.input.mouse.x, targetY: ig.input.mouse.y });
                        this.numMissilesShot += 1;
                    }
                }
                else {
                    //Drop depth charge
                    if (this.numDepthChargesShot < 5 && this.depthChargeTimer.delta() > 1) {

                        this.soundDepthChargeSplash.play();

                        for (var i = 0; i< 5; i++) {
                            ig.game.spawnEntity(EntityWaveParticle, this.pos.x + this.halfWidth+1, this.pos.y + 6, { vel: {x: -20, y: -40}, restrictY : true });
                        }

                        ig.game.spawnEntity(EntityDepthCharge, this.pos.x + this.halfWidth, this.pos.y + 2);
                        this.numDepthChargesShot += 1;
                        this.depthChargeTimer.set(0);

                    }
                }

            }

            //Are we sinking yet?
            if (this.health <= 0) {
                if (this.soundPlayMayday) {
                    this.gravityFactor = 0.2;
                    this.soundMayday.play();
                    this.soundPlayMayday = false;
                    this.currentAnim.alpha = 0.3;
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 2, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 4, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 6, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 8, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 10, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 12, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 14, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 16, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 18, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 20, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 22, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 24, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 26, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 28, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 30, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                    ig.game.spawnEntity(EntityOilParticle, this.pos.x + 32, this.pos.y, { vel: {x: 20, y: -4}, restrictY : true });
                }
                else {
                    //Wave particles when sinking
                    if (this.pos.y > 60 && this.smokeTimer.delta() > 0.1) {
                        var randomPos =  Math.random() * this.size.x;
                        ig.game.spawnEntity(EntityWaveParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                        ig.game.spawnEntity(EntityWaveParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                        ig.game.spawnEntity(EntityWaveParticle, this.pos.x + randomPos, this.pos.y + 1, { vel: {x: 15, y: -5}, restrictY: true, gravityFactor: 0 });
                        this.smokeTimer.set(0);
                    }

                }
            }

            //Move!
            this.parent();
			
        }


    });



    //These entities are NOT in a separate file, because we don't need to be able to place them in weltmeister
    //They are just used here in the code. Only entities that should be usable in Weltmeister need to be in their own file.

    EntityWaveParticle = EntityParticle.extend({
        lifetime: 1,
        fadetime: 1,
        bounciness: 0,
        gravityFactor: 0.1,
        vel: {x: 10, y: 0},
        offset: {x: 0, y: 0},

        animSheet: new ig.AnimationSheet( 'media/waveParticle.png', 1, 1 ),

        init: function( x, y, settings ) {
            this.addAnim( 'idle', 0.1, [0, 1] );
            this.parent( x, y, settings );
        }
    });


    EntityMissile = ig.Entity.extend({
        name: 'Missile',
        size: { x: 4, y: 2 },
        offset: { x: 0, y: 0 },
        maxVel: { x: 100, y: 40 },
        gravityFactor: 0,
        spawnPoint: { x: 0, y: 0 },
        target: { x: 0, y: 0 },

        type: ig.Entity.TYPE.NONE,
        checkAgainst: ig.Entity.TYPE.B, 				// Check for collisions Against B - our evil enemy group
        collides: ig.Entity.COLLIDES.PASSIVE,

        animSheet: new ig.AnimationSheet('media/missile.png', 4, 2),

        init: function (x, y, settings) {
            this.parent(x, y, settings);
            this.addAnim('idle', 0.05, [0, 1]);

            //Remember where this missile was spawned and where its heading
            this.spawnPoint.x = x;
            this.spawnPoint.y = y;
            this.target.x = settings.targetX;
            this.target.y = settings.targetY;

            //Find the unit vector of the missile to determine it's velocity
            //We use a fast approximation of a unit vector to avoid using square roots
            var missileSpeed = 100;
            var xDist = this.target.x - this.spawnPoint.x;
            var yDist = this.target.y - this.spawnPoint.y;
            var mag = Math.sqrt(xDist *xDist + yDist * yDist);
            this.vel.x = xDist / mag * missileSpeed;
            this.vel.y = yDist / mag * missileSpeed;

             if (this.vel.x < 0) {
                this.currentAnim.flip.x = true;
            }



        },


        update: function () {
            this.parent();

            //Kill missile if it goes out of bounds
            if ((this.pos.y < -10)  ||
                (this.pos.y > this.spawnPoint.y+4) ||
                (this.pos.x < -20) ||
                (this.pos.x > ig.game.width + 20)
                )  {
                this.killMe();
            }
        },



        //This function is called when this entity overlaps anonther entity of the
        //checkAgainst group. i.e. for this entity, all entities in the B group.
        //So kill whatever entity the missile hit
        check: function (other) {
            if (other.type == ig.Entity.TYPE.B) {
                ig.game.currentScore += 300;
                other.dying = true;
                other.currentAnim = other.anims.dying;
                ig.game.soundMissileHit.play();
            }

            this.killMe();
        },



        //Remove this entity and reduce the number of missiles shot by the player
        killMe: function () {
            this.kill();
            var player = ig.game.getEntityByName('Player');
            if (player != null) player.numMissilesShot -= 1;
        }


    });


    EntityDepthCharge = ig.Entity.extend({
        name: 'DepthCharge',
        size: { x: 3, y: 3 },
        offset: { x: 0, y: 0 },
        vel: { x: 0, y: 10 },
        gravityFactor: 0,
        spawnPoint: { x: 0, y: 0 },
        target: { x: 0, y: 0 },

        type: ig.Entity.TYPE.NONE,
        checkAgainst: ig.Entity.TYPE.B, 				// Check for collisions Against B - our evil enemy group
        collides: ig.Entity.COLLIDES.PASSIVE,
        particleTimer: null,

        animSheet: new ig.AnimationSheet('media/depthCharge.png', 3, 3),
        soundSubmarineHit: new ig.Sound('media/soundSubmarineHit.ogg'),

        init: function (x, y, settings) {
            this.parent(x, y, settings);
            this.addAnim('idle', 1, [0]);

            //Remember where this depth charge was spawned
            this.spawnPoint.x = x;
            this.spawnPoint.y = y;

            this.particleTimer = new ig.Timer();
        },


        update: function () {
            this.parent();

            if (this.pos.y > this.spawnPoint.y + 10) {
                if( this.particleTimer.delta() > 0.3 ) {
                    ig.game.spawnEntity(EntityDepthChargeParticle, this.pos.x+1, this.pos.y-1.5, { vel: {x: 11, y: -10}, restrictY : true });
                    this.particleTimer.set(0);
                }
            }


            //Kill depth charge if it goes out of bounds
            if (this.pos.y > ig.game.height) {
                this.killMe();
            }
        },



        //This function is called when this entity overlaps anonther entity of the
        //checkAgainst group. i.e. for this entity, all entities in the B group.
        //So kill whatever entity the missile hit
        check: function (other) {
            if (other.type == ig.Entity.TYPE.B) {
                ig.game.currentScore += ( Math.floor(other.pos.y * 10) + other.vel.x * 5);
                this.soundSubmarineHit.play();
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                ig.game.spawnEntity(EntityOilParticle, other.pos.x + other.halfWidth, this.pos.y+3, { vel: {x: 30, y: -3}, restrictY : true });
                other.kill();
                ig.game.numSubs -= 1;
            }

            this.killMe();
        },



        //Remove this entity and reduce the number of missiles shot by the player
        killMe: function () {
            this.kill();
            var player = ig.game.getEntityByName('Player');
            if (player != null) player.numDepthChargesShot -= 1;
        }

    });


    EntityDepthChargeParticle = EntityParticle.extend({
        lifetime: 1,
        fadetime: 1,
        bounciness: 0,
        gravityFactor: 0,
        vel: {x: 10, y: 0},
        offset: {x: 0, y: 0},

        animSheet: new ig.AnimationSheet( 'media/depthChargeParticle.png', 1, 1 ),

        init: function( x, y, settings ) {
            this.addAnim( 'idle', 0.1, [0, 1] );
            this.parent( x, y, settings );
        }
    });


    EntitySmokeParticle = EntityParticle.extend({
        lifetime: 1,
        fadetime: 1,
        bounciness: 0,
        gravityFactor: 0,
        vel: {x: 10, y: 0},
        offset: {x: 0, y: 0},

        animSheet: new ig.AnimationSheet( 'media/smokeParticle.png', 1, 1 ),

        init: function( x, y, settings ) {
            this.addAnim( 'idle', 1, [0] );
            this.parent( x, y, settings );
        }
    });


    EntityOilParticle = EntityParticle.extend({
        lifetime: 2,
        fadetime: 1,
        bounciness: 0,
        gravityFactor: 0,
        vel: {x: 10, y: 0},
        offset: {x: 0, y: 0},

        type: ig.Entity.TYPE.NONE,

        animSheet: new ig.AnimationSheet( 'media/oilParticle.png', 8, 8 ),

        init: function( x, y, settings ) {
            this.addAnim( 'idle', 1, [0] );
            this.parent( x, y, settings );
        }
    });

});