let mapWidth = 210.;
let mapHeith = 100.;
const playerSize = 50.;
const playerSpeed=.2;
const halfSqrtTwo=0.70710678118;
class Player
{
    constructor (id,x,y,name, dir)
    {
        this.name=name;
        this.x=x;
        this.y=y;
        this.id=id;
        this.visibleDir=1;
        this.dir=dir;//0=standStill
                   //1=North
                   //2=North-East
                   //3=East
                   //4=South-East
                   //5=South
                   //6=South-West
                   //7=West
                   //8=North-West
        this.ammo=10;
        this.health=10;
    }

    takeDamage(amount)
    {
        this.health-=amount;
        if(this.health<=0)
        {
            //send death message to server
            //this.reset()
        }
    }

    retrieveServerInfo(id,x,y,dir)
    {
        if(this.id==id)
        {
            this.x=x;
            this.y=y;
            this.dir=dir;
            if(dir!=0)
                this.visibleDir=dir;
        }
    }

    changeDirection(newDirection){
        this.dir = newDirection;
        if(this.dir!=0){
            this.visibleDir = newDirection;
        }
        //console.log("Should send: {type='update', dir=",this.dir,", x=",this.x,", y=",this.y,"}");
    }

    update(squares,circles, dt)//update position
    {
        if(this.dir==0)
            return;

        let dx,dy;
        switch(this.dir)
        {
            case 1: dx=0.;dy=-playerSpeed;break;
            case 2: dx=halfSqrtTwo*playerSpeed;dy=-halfSqrtTwo*playerSpeed;break;
            case 3: dx=playerSpeed;dy=0.;break;
            case 4: dx=halfSqrtTwo*playerSpeed;dy=halfSqrtTwo*playerSpeed;break;
            case 5: dx=0.;dy=playerSpeed;break;
            case 6: dx=-halfSqrtTwo*playerSpeed;dy=halfSqrtTwo*playerSpeed;break;
            case 7: dx=-playerSpeed;dy=0.;break;
            case 8: dx=-halfSqrtTwo*playerSpeed;dy=-halfSqrtTwo*playerSpeed;break;
            default:
        }
        this.x += dx*dt;
        this.y += dy*dt;

        for(let square in squares)
        {
            if(square.collide(this))
            {
                this.x-=dx;
                this.y-=dy;
                this.dir=0;
                return;
            }
        }
        for(let circle in circles)
        {
            if(circle.collide(this))
            {
                this.x-=dx;
                this.y-=dy;
                this.dir=0;
                return;
            }
        }
    }

    get angle()
    {
        return (this.visibleDir-3)*3.1415926535/4.;
    }
}

function dist(A,B)
{
    return sqrt((A.x-B.x)**2+(A.y-B.y)**2);
}

class Bullet
{
    constructor (x,y,dx,dy)
    {
        this.x=x;
        this.y=y;
        this.dx=dx;
        this.dy=dy;
        this.deleted=false;
    }

    update()
    {
        if(!this.deleted)
        {
            this.x+=this.dx;
            this.y+=this.dy;
        }
    }

    checkCollisions(player,squares,circles)//only the client's player /!\
    {
        if(!this.deleted)
        {
            if(dist(player,this)<playerSize/2)
            {
                player.takeDamage(1);
                this.deleted=true;
                return;
            }

            for(let square in squares)
            {
                if(square.collide(this))
                {
                    this.deleted=true;
                    return;
                }
            }

            for(let circle in circles)
            {
                if(circle.collide(this))
                {
                    this.deleted=true;
                    return;
                }
            }
        }
    }

}

class Square
{
    constructor(x,y,width,heigth)
    {
        this.x=x;
        this.y=y;
        this.w=width;
        this.h=heigth;
    }

    collide(point)
    {
        return (this.x<=point.x && point.x<=this.x+this.w && this.y<=point.y && point.y<=this.y+this.h);
    }
}

class Circle
{
    constructor(x,y,radius)
    {
        this.x=x;
        this.y=y;
        this.r=radius;
    }

    collide(point)
    {
        return ((point.x-this.x)**2+(point.y-this.y)**2<=this.r**2);
    }
}