/*****************************************************************************
 *
 *  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_Panneau.h"
#include "MOGL_Bibliotheque.h"
#include <GL/glu.h>

#include <MOGL_PoliceTTF.h>

MOGL_Panneau::MOGL_Panneau(MOGL_Fenetre * p_Fenetre, const string & p_Label, unsigned int p_LargeurPanneau, unsigned int p_HauteurPanneau)
  : MOGL_Interface(), _Fenetre(p_Fenetre), _Panneau(NULL), _Police(NULL), _LargeurPanneau(p_LargeurPanneau),
    _HauteurPanneau(p_HauteurPanneau), _IndiceFocus(0), _Activation(false), _ProchaineActivation(false),
    _FilsActif(NULL), _Label(p_Label), _AlignementHorizontal(CENTRE), _AlignementVertical(CENTRE), _UtiliserEscape(true)
{
  _Niveau=60;

  _CouleurFond.r=0;
  _CouleurFond.g=0;
  _CouleurFond.b=0;
  _CouleurFond.a=0.4f;

  _CouleurLabel.r=1;
  _CouleurLabel.g=1;
  _CouleurLabel.b=1;
  _CouleurLabel.a=1;

  _Fenetre->KeyDown.Connecter(this,&MOGL_Panneau::ClavierDown);
  _Fenetre->KeyUp.Connecter(this,&MOGL_Panneau::ClavierUp);
  _Fenetre->MouseMove.Connecter(this,&MOGL_Panneau::DeplacementSouris);

}

MOGL_Panneau::MOGL_Panneau(MOGL_Panneau * p_Panneau, const string & p_Label, unsigned int p_LargeurPanneau, unsigned int p_HauteurPanneau)
  : MOGL_Interface(), _Fenetre(p_Panneau->_Fenetre), _Panneau(p_Panneau), _CouleurFond(p_Panneau->_CouleurFond),
    _CouleurLabel(p_Panneau->_CouleurLabel), _Police(NULL), _LargeurPanneau(p_LargeurPanneau), _HauteurPanneau(p_HauteurPanneau),
    _IndiceFocus(0), _Activation(false), _ProchaineActivation(false), _FilsActif(NULL), _Label(p_Label),
    _AlignementHorizontal(CENTRE), _AlignementVertical(CENTRE), _UtiliserEscape(true)
{
  _Niveau=p_Panneau->_Niveau;
}

void MOGL_Panneau::_AjouterElementPanneau(MOGL_ElementPanneau * p_ElementPanneau)
{
  _VectorPanneau.push_back(p_ElementPanneau);
  if (_VectorPanneau.size()==1)
  {
    p_ElementPanneau->_Focus=true;
    _IndiceFocus=0;
  }
}

void MOGL_Panneau::SetPolice(MOGL_Police * p_Police)
{
  _Police=p_Police;
}

void MOGL_Panneau::Afficher()
{
  if (_Panneau!=NULL)
  {
    SetDimension(_Panneau->_Largeur, _Panneau->_Hauteur);
  }
  _Activation=_ProchaineActivation;
  if (_Activation)
  {
    if (_FilsActif==NULL)
    {
      float xmin=0, xmax=0, ymin=0, ymax=0;
      switch (_AlignementHorizontal)
      {
        case MIN:
        {
          xmin=0;
          xmax=_Largeur;
          break;
        }
        case CENTRE :
        {
          xmin=-static_cast<int>(_Largeur)/2+static_cast<int>(_LargeurPanneau)/2;
          xmax=_Largeur/2+_LargeurPanneau/2;
          break;
        }
        case MAX:
        {
          xmin=static_cast<int>(_LargeurPanneau)-static_cast<int>(_Largeur);
          xmax=_LargeurPanneau;
          break;
        }
      }
      switch (_AlignementVertical)
      {
        case MIN:
        {
          ymin=0;
          ymax=_Hauteur;
          break;
        }
        case CENTRE :
        {
          ymin=-static_cast<int>(_Hauteur)/2+static_cast<int>(_HauteurPanneau)/2;
          ymax=_Hauteur/2+_HauteurPanneau/2;
          break;
        }
        case MAX:
        {
          ymin=static_cast<int>(_HauteurPanneau)-static_cast<int>(_Hauteur);
          ymax=_HauteurPanneau;
          break;
        }
      }

      //Initialize OpenGL
      glColor4f(1.0,1.0,1.0,1.0);
      glEnable(GL_BLEND);
      glDisable(GL_LIGHTING);
      glDisable(GL_TEXTURE_2D);
      glDisable(GL_ALPHA_TEST);
      glDisable(GL_DEPTH_TEST);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluOrtho2D(xmin,xmax,
                 ymax, ymin);

      glMatrixMode(GL_TEXTURE);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);       
      glLoadIdentity();

      // On prend la police par défaut si l'on n'en a pas
      if (!_Police)
      {
        _Police=&(MOGL_Bibliotheque::GetSingleton()->GetPolice());
      }

      // On dessine le cadre
      glColor4f(_CouleurFond.r, _CouleurFond.g, _CouleurFond.b, _CouleurFond.a);
      glBegin(GL_QUADS);
      glVertex2f(0,0);
      glVertex2f(0,_HauteurPanneau);
      glVertex2f(_LargeurPanneau,_HauteurPanneau);
      glVertex2f(_LargeurPanneau,0);
      glEnd();

      int marge=10;

      // On affiche le label
      unsigned int taille=_Police->GetTailleXChaine(_Label);
      _Police->Afficher(_Label, (_LargeurPanneau-taille)/2, marge, _CouleurLabel);

      int val=static_cast<int>(_Police->GetTailleYMax()*1.5);
      for(MOGL_ItVector_ElementPanneau it=_VectorPanneau.begin(); it!=_VectorPanneau.end(); it++)
      {
        if (!(*it)->GetCacher())
        {
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          gluOrtho2D(xmin - marge,
                     xmax - marge,
                     ymax - marge -val,
                     ymin - marge- val);

          glMatrixMode(GL_MODELVIEW);     
          (*it)->Afficher();
          val+=((*it)->GetHauteurElement());
        }
      }

      glEnable(GL_LIGHTING);
    }
    else
    {
      _FilsActif->Afficher();
    }
  }
}

void MOGL_Panneau::ClavierUp(SDL_keysym * key)
{
    memset(&_LastKeyDown, 0, sizeof(_LastKeyDown));
    if (_Activation)
    {

        if (_FilsActif==NULL)
        {
            switch (key->sym)
            {
                case SDLK_ESCAPE:
                {
                    if (_UtiliserEscape)
                    {
                        SetActivation(false);
                    }
                    break;
                }
                default:
                {
                    _VectorPanneau[_IndiceFocus]->ClavierUp(key);
                    break;
                }
            }
        }
        else
        {
            _FilsActif->ClavierUp(key);
        }
    }
}

void MOGL_Panneau::ClavierDown(SDL_keysym * key)
{
    if (memcmp(key, &_LastKeyDown, sizeof(_LastKeyDown)))
    {
        _LastKeyDown = *key;

        if (_Activation)
        {
            if (_FilsActif==NULL)
            {
                switch (key->sym)
                {
                    case SDLK_DOWN :
                    {
                        ProchainFocus();
                        break;
                    }
                    case SDLK_UP :
                    {
                        PrecedentFocus();
                        break;
                    }
                    default:
                    {
                        _VectorPanneau[_IndiceFocus]->ClavierDown(key);
                        break;
                    }
                }
            }
            else
            {
                _FilsActif->ClavierDown(key);
            }
        }
    }
}

void MOGL_Panneau::DeplacementSouris(SDL_MouseMotionEvent * p_Event)
{
  if (_Activation)
  {
    if (_FilsActif==NULL)
    {
    }
    else
    {
      _FilsActif->DeplacementSouris(p_Event);
    }
  }
}

bool MOGL_Panneau::SetFocus(MOGL_ElementPanneau * p_Element)
{
  bool trouve=false;
  for(unsigned int indice=0; indice<_VectorPanneau.size(); indice++)
  {
    if (_VectorPanneau[indice]==p_Element)
    {
      if (indice!=_IndiceFocus && p_Element->_GestionFocus && !p_Element->GetCacher())
      {
        p_Element->_Focus=true;
        _VectorPanneau[_IndiceFocus]->_Focus=false;
        _IndiceFocus=indice;
        trouve=true;
      }
      break;
    }
  }
  return trouve;
}

void MOGL_Panneau::SetActivation(bool p_Activation)
{
  _ProchaineActivation=p_Activation;
  if (_Panneau!=NULL)
  {
    if (p_Activation)
    {
      _Panneau->_FilsActif=this;
    }
    else
    {
      _Panneau->_FilsActif=NULL;
    }
  }
}

bool MOGL_Panneau::GetActivation() const
{
  return _Activation;
}

void MOGL_Panneau::SetLabel(const string & p_Label)
{
  _Label=p_Label;
}

void MOGL_Panneau::ProchainFocus()
{
  unsigned int indDeb=_IndiceFocus;
  _VectorPanneau[_IndiceFocus]->_Focus=false;
  do
  {
    if (++_IndiceFocus==_VectorPanneau.size())
    {
      _IndiceFocus=0;
    }
  } while((!_VectorPanneau[_IndiceFocus]->_GestionFocus || _VectorPanneau[_IndiceFocus]->GetCacher()) && indDeb!=_IndiceFocus);

  _VectorPanneau[_IndiceFocus]->_Focus=true;
}

void MOGL_Panneau::PrecedentFocus()
{
  unsigned int indDeb=_IndiceFocus;

  _VectorPanneau[_IndiceFocus]->_Focus=false;

  do
  {
    if (_IndiceFocus==0)
    {
      _IndiceFocus=_VectorPanneau.size()-1;
    }
    else
    {
      _IndiceFocus--;
    }
  } while((!_VectorPanneau[_IndiceFocus]->_GestionFocus || _VectorPanneau[_IndiceFocus]->GetCacher()) && indDeb!=_IndiceFocus);

  _VectorPanneau[_IndiceFocus]->_Focus=true;
}

void MOGL_Panneau::SetCouleurFond(const MOGL_Struct_Couleur & p_Couleur)
{
  _CouleurFond=p_Couleur;
}

void MOGL_Panneau::SetCouleurLabel(const MOGL_Struct_Couleur & p_Couleur)
{
  _CouleurLabel=p_Couleur;
}

MOGL_Struct_Couleur MOGL_Panneau::GetCouleurFond() const
{
  return _CouleurFond;
}

MOGL_Struct_Couleur MOGL_Panneau::GetCouleurLabel() const
{
  return _CouleurLabel;
}

void MOGL_Panneau::SetUtiliserEscape(bool p_Utilise)
{
  _UtiliserEscape=p_Utilise;
}

bool MOGL_Panneau::GetUtiliserEscape() const
{
  return _UtiliserEscape;
}

