#include "game.hpp"

game::game()
{
	_world = loadDisk("../data/battleflight.disk");
    _arwing = fly(loadShell("../data/arwing.shell"));
    _arwing.setPos(point(0,-2,_world.getRadius()-1));

    _cam.setRadius(10);
	_thirdPerson = true;

    _bulletModel = loadShell("../data/bullet.shell");

    _explosionModel = loadShell("../data/Explosion.shell");
    _petiteExplosionModel = _explosionModel;
    _petiteExplosionModel.mulS(0.25);

    tank t = tank(loadShell("../data/sweedish.shell"));
    t.setPos(point(2,-2,2));
    _enemy.push_back(t);

    _life = 100;

    _continu = true;
}

void game::update()
{
    //reinitialiser l'arriere plan
    _bg = color(0,0,0);

    //remet le continu a vraie
    _continu = true;

    //bouger l'avion avec sa detection de collision
    if(_world.gettingOutOfTheWorld(_arwing.getShell(), _arwing.getDir()*_arwing.speed()))
    {
        //_arwing.loop();
        _arwing.turnLeft(pi/10);
    }
    if(_world.willCollide(_arwing.getShell(), point()))//_arwing.getDir()*-0.1))
        _bg = color(128, 0, 0);
    _arwing.forward(_arwing.speed());

    //affiche l'avion
    _cam.addShell(_arwing.getShell());

    if(_thirdPerson)
    {
        _cam.moveTo(point(0,0.3,2).rotY(_arwing.getRadY()) - _arwing.getPos());
        _cam.turnY(-_arwing.getRadY());
        _cam.turnX(0);
    }
    else
    {
        _cam.moveTo(point(0,6,0)-_arwing.getPos());
        _cam.turnX(pi/2);
        _cam.turnY(0);
    }
    //process bullet
    for(list<bullet>::iterator it= _bulletList.begin(); it!=_bulletList.end(); it=it->next())
    {
        //quand la bullet entre en collision avec le world
        if(_world.willCollide(it->data().getShell(),point()) ||
           _world.gettingBelowTheFloor(it->data().getShell(),point()) ||
           _world.gettingOverTheTop(it->data().getShell(), point()) ||
           _world.gettingOutOfTheWorld(it->data().getShell(), point()))
        {
            //disparait
            it->data().setExpire(0);
           // bang(it->data().getPos(), it);
        }

        //quand le hero mange une bullet
        if(_arwing.getShell().collide(it->data().getShell()))
        {
            _bg = color(255, 255, 0);
            it->data().setExpire(0);
            _arwing.damage();
            //verifie si le jeu est fini
            _continu = false;
        }

        //quand l'enemy mange une bullet
        for (unsigned int i=0;i<_enemy.size();i++)
        {
            if(_enemy[i].getShell().collide(it->data().getShell()))
            {
                it->data().setExpire(0);                            //la bullet en cours est detruite
                _enemy[i].damage();
                bang((it->data().getPos()), it);
                //verifie si le jeu est fini
                _continu = false;
            }
        }

        if(it->data().update())
            _cam.addShell(it->data().getShell());
        else
        {
            it = it->remove();
        }
    }
    //render world
    for (int i=0;i<_world.size();i++)
    {
        shell tmp(_world.get(i));
        _cam.addShell(tmp);
    }
    //render enemy
    for (unsigned int i=0;i<_enemy.size();i++)
    {
        _enemy[i].update();
        if(_enemy[i].watch(_arwing))
        {
            _bulletList.push_back(_enemy[i].shoot(_arwing,_bulletModel));
        }
        _cam.addShell(_enemy[i].getShell());
    }
    for(unsigned int i=0;i<_enemy.size();i++)
    {
        if(!_enemy[i].health())
            _enemy.pop_back();
    }
}

void game::left()
{
    _arwing.turnLeft(pi/200);
}

void game::right()
{
	_arwing.turnRight(pi/200);
}

void game::down()
{
    if (!_world.gettingOverTheTop(_arwing.getShell(), point(0,-0.015,0)))
        _arwing.climb(0.015);
}

void game::up()
{
    if (!_world.gettingBelowTheFloor(_arwing.getShell(), point(0,0.015,0)))
        _arwing.descent(0.015);
}

void game::space()
{
//    if ((++_bulletSlower%=20)==0)
    if(_arwing.cool())
        _bulletList.push_back(_arwing.shoot(_bulletModel));
}

void game::shift()
{
    if(_arwing.cool())
        _arwing.boost(0);
}


//affiche une explosion en a la position ou la bullet est morte
void game::bang(const point& p, list<bullet>::iterator& it)
{
     //explosion
    bullet tmpe(_petiteExplosionModel);
    tmpe.setRad(0, 0, 0);
    tmpe.setPos(p);
    tmpe.setSpeed(0);
    tmpe.setExpire(10);
    it->push_back(tmpe);
}

//verifie si on doit verifier l'etat du jeu
bool game::continuer()
{
    return _continu;
}

//verifie si on gagne
bool game::win()
{
    return !_continu && _enemy.empty() && _bulletList.empty() && _arwing.health();
}

