class Map 
{
    static SIZE = 8192;
    static MAX_CRYSTALS = 200;
    static CRYSTAL_SPAWN_TIME = 2;
    static IMPACT_TIME = 300;
    static LAUNCH_COST = 40;

    static STATE_INTRO = 0;
    static STATE_GAME = 1;
    static STATE_VICTORY = 4;
    static STATE_GAMEOVER = 5;

    constructor( engine )
    {
        this.engine = engine;
        this.b_canUnload = false;
        this.ground = new Sparrow.Quad( this.engine , -Map.SIZE/2 , -Map.SIZE/2 , Map.SIZE , Map.SIZE , { file: "img/bg.png" , filter: this.engine.gl.NEAREST } );
        this.unloadingArea = new Sparrow.Quad( this.engine , -50 , -50 , 100 , 100 , { file: "img/door.png" , filter: this.engine.gl.NEAREST } );
        this.unloadingText = new Sparrow.Text( this.engine , "[E] Unload, [F] Shop" , -100 , -75 , { font: "monospace" , size: 20 , color: Color4b.WHITE } );

        this.car = new Car( this.engine , this );

        this.tracks_1 = new Tracks( this.engine , this.car , -Car.WIDTH/2+2 , -Car.HEIGHT/2+6 );
        this.tracks_2 = new Tracks( this.engine , this.car , Car.WIDTH/2-2 , -Car.HEIGHT/2+6 );
        this.tracks_3 = new Tracks( this.engine , this.car , -Car.WIDTH/2+2 , Car.HEIGHT/2-6 );
        this.tracks_4 = new Tracks( this.engine , this.car , Car.WIDTH/2-2 , Car.HEIGHT/2-6 );

        this.numberOfCrystals = 0;
        this.crystalSpawnTimer = 0;

        this.crystalTexture = Sparrow.Texture.createFromFile( this.engine , "img/crystal.png" , "crystal" , { filter: this.engine.gl.NEAREST } );

        this.defaultTexture = Sparrow.Texture.createFromFile( this.engine , "img/door.png" , "door" , { filter: this.engine.gl.NEAREST } );
        this.openTexture = Sparrow.Texture.createFromFile( this.engine , "img/door_open.png" , "door_open" , { filter: this.engine.gl.NEAREST } );

        this.init();

        this.ui = null;

        this.state = Map.STATE_INTRO;

        this.timeUntilImpact = Map.IMPACT_TIME;
        this.impactTimer = 0;

        this.b_endless = false;

        this.rocket = new Rocket( this.engine , this , 0 , 0 );
    }

    start()
    {
        this.state = Map.STATE_GAME;
        this.car.start();
        this.rocket.reset();
        this.unloadingArea.setTexture( this.defaultTexture );
    }

    restart()
    {
        this.car.restart();

        this.tracks_1.reset();
        this.tracks_2.reset();
        this.tracks_3.reset();
        this.tracks_4.reset();

        // this.tracks_1 = new Tracks( this.engine , this.car , -Car.WIDTH/2+2 , -Car.HEIGHT/2+6 );
        // this.tracks_2 = new Tracks( this.engine , this.car , Car.WIDTH/2-2 , -Car.HEIGHT/2+6 );
        // this.tracks_3 = new Tracks( this.engine , this.car , -Car.WIDTH/2+2 , Car.HEIGHT/2-6 );
        // this.tracks_4 = new Tracks( this.engine , this.car , Car.WIDTH/2-2 , Car.HEIGHT/2-6 );

        this.numberOfCrystals = 0;
        this.crystalSpawnTimer = 0;

        this.init();

        this.state = Map.STATE_INTRO;

        this.timeUntilImpact = Map.IMPACT_TIME;
        this.impactTimer = 0;

        this.ui.intro.show();
        this.ui.gameOver.hide();

        this.b_endless = false;

        this.rocket.reset();

        this.unloadingArea.setTexture( this.defaultTexture );
    }

    launchRocket()
    {
        this.car.x = 0;
        this.car.y = -100;
        this.car.camera.setFocus( this.car.x , this.car.y );
        this.car.speed = 0;
        this.rocket.x = this.car.camera.x - this.car.x;
        this.rocket.y = this.car.camera.y - this.car.y;
        this.car.b_canMove = false;

        setTimeout( () => {
            this.unloadingArea.setTexture( this.openTexture );
        } , 500 );
        setTimeout( () => {
            this.rocket.launch();
        } , 1000 );
    }

    init()
    {
        this.crystals = [];
        // spawn some initial crystals
        for ( let i = 0 ; i < 150 ; ++i )
        {
            var x = -Map.SIZE/2+Math.random()*Map.SIZE;
            var y = -Map.SIZE/2+Math.random()*Map.SIZE;
            this.crystals.push( new Crystal( this.engine , this , x , y ) );
        }
    }

    victory()
    {
        this.state = Map.STATE_VICTORY;
        this.ui.victory.show();
        this.car.stop();
    }

    gameOver()
    {
        this.state = Map.STATE_GAMEOVER;
        this.car.stop();
        this.ui.gameOver.sound.play();
        setTimeout( () => {
            this.ui.gameOver.show();
        } , 2700 );
    }

    unload()
    {
        this.numberOfCrystals += this.car.numberOfCrystals;
        this.ui.lbl_crystals.setStr( "Crystals: "+this.numberOfCrystals );
    }

    pay( cost )
    {
        this.numberOfCrystals -= cost;
        this.ui.lbl_crystals.setStr( "Crystals: "+this.numberOfCrystals );
    }

    update( dt )
    {
        this.car.update( dt );

        this.tracks_1.update( dt );
        this.tracks_2.update( dt );
        this.tracks_3.update( dt );
        this.tracks_4.update( dt );

        this.crystalSpawnTimer += dt;
        if ( this.crystalSpawnTimer > Map.CRYSTAL_SPAWN_TIME )
        {
            this.crystalSpawnTimer = 0;
            if ( this.crystals.length < Map.MAX_CRYSTALS )
            {
                var x = -Map.SIZE/2+Math.random()*Map.SIZE;
                var y = -Map.SIZE/2+Math.random()*Map.SIZE;
                this.crystals.push( new Crystal( this.engine , this , x , y ) );
            }
        }

        if ( !this.b_endless )
        {
            this.impactTimer += dt;
            if ( this.impactTimer >= 0.1 )
            {
                this.timeUntilImpact -= this.impactTimer;
                this.timeUntilImpact = Math.floor( this.timeUntilImpact*10 )/10;
                this.impactTimer = 0;
                this.ui.updateImpactTimer();

                if ( this.timeUntilImpact <= 0 )
                {
                    this.gameOver();
                }
            }
        }

        this.rocket.update( dt );
    }

    draw()
    {
        this.engine.defaultShader2D.setUniformModel( this.car.camera.M_view );

        this.ground.draw();
        this.unloadingArea.draw();

        for ( let i = 0 ; i < this.crystals.length ; ++i )
        {
            this.crystals[i].draw();
        }

        this.tracks_1.draw();
        this.tracks_2.draw();
        this.tracks_3.draw();
        this.tracks_4.draw();

        this.engine.gl.enable( this.engine.gl.SCISSOR_TEST );
        this.engine.gl.scissor( 0 , this.engine.gl.viewportHeight-0-this.engine.gl.viewportHeight/2+70 , this.engine.gl.viewportWidth , this.engine.gl.viewportHeight/2+70 );
        this.rocket.draw();
        this.engine.gl.disable( this.engine.gl.SCISSOR_TEST );


        this.car.draw();

        this.engine.defaultShader2D.setUniformModel( this.car.camera.M_view );

        if ( this.b_canUnload ) this.unloadingText.draw();

        this.engine.restoreDefaultUniforms();
        // this.car.debugText.draw();
        this.car.txt_maxSpeed.draw();
        this.car.txt_acceleration.draw();
        this.car.txt_pickUpDistance.draw();
        this.car.txt_capacity.draw();
    }
}