/*****************************************************************************
 *
 *  Copyright (C) 2003 Cédric Brégardis <cedric.bregardis@free.fr>
 *
 *  This file is part of BRIQUOLO
 *
 *  BRIQUOLO is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  BRIQUOLO is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BRIQUOLO; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *****************************************************************************/
#include <MOGL_Temps.h>
#include <MOGL_GestionnaireObjet.h>
#include <MOGL_Noeud.h>

#include "BibliothequeSon.h"
#include "Constante.h"
#include "Plateau.h"

#ifndef M_PI
#define M_PI 3.14159265359
#endif

#define PLAT_DIV_FACT 2000


MOGL_Objet * Plateau::_ObjetSourceMilieu=NULL;
MOGL_Objet * Plateau::_ObjetSourceDroite=NULL;
MOGL_Objet * Plateau::_ObjetSourceGauche=NULL;

Plateau::Plateau(): ElementCollision(), _TailleInitX(8), _TailleInitY(2),
                    _TailleX(_TailleInitX), _TailleY(_TailleInitY),
                    _FacteurTaille(1), _Vitesse(0)
{
    if (_ObjetSourceMilieu==NULL)
    {
        PreCharger();
    }
    _ElementArbre=new MOGL_Noeud;

    _ObjetMilieu=new MOGL_Objet(*_ObjetSourceMilieu);
    _ObjetDroite=new MOGL_Objet(*_ObjetSourceDroite);
    _ObjetDroite->ReinitialiserPosition();
    _ObjetDroite->AjouterTranslation(_TailleX/2,0,0);
    _ObjetGauche=new MOGL_Objet(*_ObjetSourceGauche);
    _ObjetGauche->ReinitialiserPosition();
    _ObjetGauche->AjouterTranslation(-_TailleX/2,0,0);

    ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetMilieu);
    ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetDroite);
    ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetGauche);
}

Plateau::~Plateau()
{
  delete _ElementArbre;
  delete _ObjetMilieu;
  delete _ObjetGauche;
  delete _ObjetDroite;
}

Plateau::Plateau(const Plateau & p_Plateau): ElementCollision(p_Plateau),
                                             _TailleInitX(p_Plateau._TailleInitX), _TailleInitY(p_Plateau._TailleInitY),
                                             _TailleX(p_Plateau._TailleX), _TailleY(p_Plateau._TailleY),
                                             _FacteurTaille(p_Plateau._FacteurTaille), _Vitesse(p_Plateau._Vitesse)  
{
  if (_ObjetSourceMilieu==NULL)
  {
    PreCharger();
  }
  MOGL_Noeud * no=dynamic_cast<MOGL_Noeud *>(p_Plateau._ElementArbre);
  _ElementArbre=new MOGL_Noeud(*no);

  _ObjetMilieu=new MOGL_Objet(*p_Plateau._ObjetMilieu);
  _ObjetDroite=new MOGL_Objet(*p_Plateau._ObjetDroite);
  _ObjetGauche=new MOGL_Objet(*p_Plateau._ObjetGauche);

  ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetMilieu);
  ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetDroite);
  ((MOGL_Noeud *)_ElementArbre)->AjouterElement(_ObjetGauche);

  _MinX=p_Plateau._MinX;
  _MaxX=p_Plateau._MaxX;
}

void Plateau::PreCharger()
{
  _ObjetSourceMilieu=new MOGL_Objet;
  MOGL_GestionnaireObjet::ChargerObjetASCTriangle((Constante::GetGlobalDir()+Constante::GetDataDir()+"/plateau_milieu.tri").c_str(), 
                                                  *Texture::GetGestionnaireTexture(), *_ObjetSourceMilieu);

  _ObjetSourceDroite=new MOGL_Objet;
  MOGL_GestionnaireObjet::ChargerObjetASCTriangle((Constante::GetGlobalDir()+Constante::GetDataDir()+"/plateau_droite.tri").c_str(), 
                                                  *Texture::GetGestionnaireTexture(), *_ObjetSourceDroite);

  _ObjetSourceGauche=new MOGL_Objet;
  MOGL_GestionnaireObjet::ChargerObjetASCTriangle((Constante::GetGlobalDir()+Constante::GetDataDir()+"/plateau_gauche.tri").c_str(), 
                                                  *Texture::GetGestionnaireTexture(), *_ObjetSourceGauche);
}

Struct_Collision Plateau::TesterCollision(Balle * p_Balle)
{
  Struct_Collision collision;
  collision.TempsCollision=p_Balle->GetTempsMax();
  collision.VitesseX=p_Balle->GetVitesseTotaleX();
  collision.VitesseY=p_Balle->GetVitesseTotaleY();

  Struct_Collision t1, t2, t3, t4;

  t1 = _SegmentCollision(p_Balle->GetPositionX(), p_Balle->GetPositionY(),p_Balle->GetRayon(),
                         p_Balle->GetVitesseTotaleX(), p_Balle->GetVitesseTotaleY(),
                         _X, _Y, 0,
                         -_TailleX/2, -_TailleY/2, _TailleX/2, -_TailleY/2,
                         _Vitesse, 0, 0, 0, p_Balle->GetTempsMax());

  t2 = _SegmentCollision(p_Balle->GetPositionX(), p_Balle->GetPositionY(),p_Balle->GetRayon(),
                         p_Balle->GetVitesseTotaleX(), p_Balle->GetVitesseTotaleY(),
                         _X, _Y, 0,
                         -_TailleX/2, _TailleY/2, _TailleX/2, _TailleY/2,
                         _Vitesse, 0, 0, 0, p_Balle->GetTempsMax());

  t3 = _CircleCollision(p_Balle->GetPositionX(), p_Balle->GetPositionY(),p_Balle->GetRayon(),
                        p_Balle->GetVitesseTotaleX(), p_Balle->GetVitesseTotaleY(),
                        _X, _Y, 0, 
                        -_TailleX/2, 0, _TailleY/2, _Vitesse, 0, 0, p_Balle->GetTempsMax());

  t4 = _CircleCollision(p_Balle->GetPositionX(), p_Balle->GetPositionY(),p_Balle->GetRayon(),
                         p_Balle->GetVitesseTotaleX(), p_Balle->GetVitesseTotaleY(),
                        _X, _Y, 0, 
                        _TailleX/2, 0, _TailleY/2, _Vitesse, 0, 0, p_Balle->GetTempsMax());

  if (t1.TempsCollision < collision.TempsCollision)
  {
    collision = t1;
  }
  if (t2.TempsCollision < collision.TempsCollision)
  {
    collision = t2;
  }
  if (t3.TempsCollision < collision.TempsCollision)
  {
    collision = t3;
  }
  if (t4.TempsCollision < collision.TempsCollision)
  {
    collision = t4;
  }

  if (collision.VitesseY < 0)
  {
    collision.VitesseY *= -1;
  }
/*
  if (collision.TempsCollision < p_Balle->GetTempsMax())
  {
    collision.AddFacteurCollision = 1+fabs(_Vitesse / PLAT_DIV_FACT);
  }
*/
  return collision;
}

void Plateau::SetVitesse(double p_Vitesse)
{
  _Vitesse = p_Vitesse;
}

void Plateau::SetMinX(double p_Valeur)
{
  _MinX=p_Valeur;
}

void Plateau::SetMaxX(double p_Valeur)
{
  _MaxX=p_Valeur;
}

double Plateau::GetTailleX() const
{
  return _TailleX;
}

double Plateau::GetTailleY() const
{
  return _TailleY;
}

void Plateau::SetTaille(double p_TailleX)
{
  double facteur=p_TailleX/_TailleX;
  SetTailleFacteur(facteur);
}

void Plateau::SetTailleFacteur(double p_Facteur)
{
  _FacteurTaille*=p_Facteur;
  _TailleX*=p_Facteur;
  
  if (_X+_TailleX/2+_TailleY/2 > _MaxX)
  {
    _X=_MaxX-_TailleX/2-_TailleY/2;
  }
  else if (_X-_TailleX/2-_TailleY/2 < _MinX)
  {
    _X=_MinX+_TailleX/2+_TailleY/2;
  }

  MOGL_MatriceTransformation mat=MOGL_MatriceTransformation::FabriqueEchelle(_FacteurTaille, 1, 1);

  _ObjetMilieu->ReinitialiserPosition();
  _ObjetMilieu->AjouteTransformation(mat);

  _ObjetDroite->ReinitialiserPosition();
  _ObjetDroite->AjouterTranslation(_TailleX/2,0,0);

  _ObjetGauche->ReinitialiserPosition();
  _ObjetGauche->AjouterTranslation(-_TailleX/2,0,0);
  SetPosition(_X,_Y);
}

void Plateau::Deplacer(double p_Temps)
{
    _X += _Vitesse*p_Temps;
    if (_X < _TailleX/2+_TailleY/2)
    {
        _X = _TailleX/2+_TailleY/2;
    }

    if (_X > 40-(_TailleX/2+_TailleY/2))
    {
        _X = 40-(_TailleX/2+_TailleY/2);
    }

    SetPosition(_X, _Y);
    _Vitesse = 0;
}
