/*
 *  Open BEAGLE
 *  Copyright (C) 2001-2004 by Christian Gagne and Marc Parizeau
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Contact:
 *  Laboratoire de Vision et Systemes Numeriques
 *  Departement de genie electrique et de genie informatique
 *  Universite Laval, Quebec, Canada, G1V 4J7
 *  http://vision.gel.ulaval.ca
 *
 */

/*!
 *  \file   beagle/GP/Context.hpp
 *  \brief  Definition of the type GP::Context.
 *  \author Christian Gagne
 *  \author Marc Parizeau
 *  $Revision: 1.2 $
 *  $Date: 2004/01/15 21:08:56 $
 */

#ifndef Beagle_GP_Context_hpp
#define Beagle_GP_Context_hpp

#include "beagle/config.hpp"
#include "beagle/macros.hpp"
#include "beagle/Object.hpp"
#include "beagle/AllocatorT.hpp"
#include "beagle/PointerT.hpp"
#include "beagle/ContainerT.hpp"
#include "beagle/AssertException.hpp"
#include "beagle/Context.hpp"
#include "beagle/GP/Vivarium.hpp"
#include "beagle/GP/Deme.hpp"
#include "beagle/GP/Individual.hpp"
#include "beagle/GP/Tree.hpp"
#include "beagle/GP/System.hpp"

namespace Beagle {
namespace GP {


/*!
 *  \class Context beagle/GP/Context.hpp "beagle/GP/Context.hpp"
 *  \brief The GP context class.
 *  \ingroup GPF
 *  \ingroup GPSys
 */
class Context : public Beagle::Context {

public:

  //! GP::Context allocator type.
  typedef AllocatorT<Context,Beagle::Context::Alloc>
          Alloc;
  //! GP::Context handle type.
  typedef PointerT<Context,Beagle::Context::Handle>
          Handle;
  //! GP::Context bag type.
  typedef ContainerT<Context,Beagle::Context::Bag>
          Bag;

           Context() { }
  virtual ~Context() { }

  /*!
   *  \brief Return the nth element of the call stack.
   *  \param inN Index of the element to return.
   *  \return Value of the nth element.
   *  \throw Beagle::AssertException If the index is out of bound.
   */
  inline unsigned int operator[](unsigned int inN) const
  {
    Beagle_BoundCheckAssertM(inN,0,mCallStack.size()-1);
    return mCallStack[inN];
  }

  /*!
   *  \brief Empty the call stack.
   */
  inline void emptyCallStack()
  {
    mCallStack.clear();
  }

  /*!
   *  \brief Return the call stack.
   *  \return Cosntant reference to the call stack.
   */
  inline const std::vector<unsigned int>& getCallStack() const
  {
    return mCallStack;
  }

  /*!
   *  \brief Return the call stack.
   *  \return Reference to the call stack.
   */
  inline std::vector<unsigned int>& getCallStack()
  {
    return mCallStack;
  }

  /*!
   *  \brief Return the nth element of the call stack.
   *  \param inN Index of the element to return.
   *  \return Value of the nth element.
   *  \throw Beagle::AssertException If the index is out of bound.
   */
  inline unsigned int getCallStackElement(unsigned int inN) const
  {
    Beagle_BoundCheckAssertM(inN,0,mCallStack.size()-1);
    return mCallStack[inN];
  }

  /*!
   *  \brief Return the call stack size.
   *  \return Call stack size.
   */
  inline unsigned int getCallStackSize() const
  {
    return mCallStack.size();
  }

  /*!
   *  \brief Get the top element of the call stack.
   *  \return Top element of the call stack.
   *  \throw Beagle::AssertException If the call stack is empty.
   */
  inline unsigned int getCallStackTop() const
  {
    Beagle_AssertM(mCallStack.empty() == false);
    return mCallStack.back();
  }

  /*!
   *  \brief Return a constant reference to the actual GP tree.
   *  \return Actual GP tree constant reference.
   */
  inline const GP::Tree& getGenotype() const
  {
    return castObjectT<const GP::Tree&>(*mGenotypeHandle);
  }

  /*!
   *  \brief Return a reference to the actual GP tree.
   *  \return Actual GP tree reference.
   */
  inline GP::Tree& getGenotype()
  {
    return castObjectT<GP::Tree&>(*mGenotypeHandle);
  }

  /*!
   *  \brief Return a handle to the actual GP tree.
   *  \return Actual GP tree handle.
   */
  GP::Tree::Handle getGenotypeHandle()
  {
    return castHandleT<GP::Tree>(mGenotypeHandle);
  }

  /*!
   *  \brief Return a constant reference to the actual individual.
   *  \return Actual individual constant reference.
   */
  inline const GP::Individual& getIndividual() const
  {
    return castObjectT<const GP::Individual&>(*mIndividualHandle);
  }

  /*!
   *  \brief Return a reference to the actual GP individual.
   *  \return Actual GP individual reference.
   */
  inline GP::Individual& getIndividual()
  {
    return castObjectT<GP::Individual&>(*mIndividualHandle);
  }

  /*!
   *  \brief Return a handle to the actual GP individual.
   *  \return Actual GP individual handle.
   */
  inline GP::Individual::Handle getIndividualHandle()
  {
    return castHandleT<GP::Individual>(mIndividualHandle);
  }

  /*!
   *  \brief Return a constant reference to the actual deme.
   *  \return Actual deme constant reference.
   */
  inline const GP::Deme& getDeme() const
  {
    return castObjectT<const GP::Deme&>(*mDemeHandle);
  }

  /*!
   *  \brief Return a reference to the actual GP deme.
   *  \return Actual GP deme reference.
   */
  inline GP::Deme& getDeme()
  {
    return castObjectT<GP::Deme&>(*mDemeHandle);
  }

  /*!
   *  \brief Return a handle to the actual GP deme.
   *  \return Actual GP deme handle.
   */
  inline GP::Deme::Handle getDemeHandle()
  {
    return castHandleT<GP::Deme>(mDemeHandle);
  }

  /*!
   *  \brief Return a constant reference to the actual vivarium.
   *  \return Actual vivarium constant reference.
   */
  inline const GP::Vivarium& getVivarium() const
  {
    return castObjectT<const GP::Vivarium&>(*mVivariumHandle);
  }

  /*!
   *  \brief Return a reference to the actual GP vivarium.
   *  \return Actual GP vivarium reference.
   */
  inline GP::Vivarium& getVivarium()
  {
    return castObjectT<GP::Vivarium&>(*mVivariumHandle);
  }

  /*!
   *  \brief Return a handle to the actual GP vivarium.
   *  \return Actual GP vivarium handle.
   */
  inline GP::Vivarium::Handle getVivariumHandle()
  {
    return castHandleT<GP::Vivarium>(mVivariumHandle);
  }

  /*!
   *  \brief Return a constant reference to the GP system.
   *  \return Evolution GP system constant reference.
   */
  inline const GP::System& getSystem() const
  {
    return castObjectT<const GP::System&>(*mSystemHandle);
  }

  /*!
   *  \brief Return a reference to the GP system.
   *  \return Evolution GP system reference.
   */
  inline GP::System& getSystem()
  {
    return castObjectT<GP::System&>(*mSystemHandle);
  }

  /*!
   *  \brief Return a handle to the GP system.
   *  \return Evolution GP system handle.
   */
  inline GP::System::Handle getSystemHandle()
  {
    return castHandleT<GP::System>(mSystemHandle);
  }

  /*!
   *  \brief Pop the call stack.
   *  \throw Beagle::AssertException If the call stack is empty.
   */
  inline void popCallStack()
  {
    Beagle_AssertM(mCallStack.empty() == false);
    mCallStack.pop_back();
  }

  /*!
   *  \brief Push a node index on the call stack.
   *  \param inNodeIndex Node index to push.
   */
  inline void pushCallStack(unsigned int inNodeIndex)
  {
    mCallStack.push_back(inNodeIndex);
  }

  /*!
   *  \brief Set an handle to the actual GP tree.
   *  \param inTreeHandle Actual GP tree handle.
   */
  inline void setGenotypeHandle(GP::Tree::Handle inTreeHandle)
  {
    mGenotypeHandle = inTreeHandle;
  }

  /*!
   *  \brief Set an handle to the actual GP individual.
   *  \param inIndividualHandle Actual GP individual handle.
   */
  inline void setIndividualHandle(GP::Individual::Handle inIndividualHandle)
  {
    mIndividualHandle = inIndividualHandle;
  }

  /*!
   *  \brief Set an handle to the actual GP deme.
   *  \param inDemeHandle Actual GP deme handle.
   */
  inline void setDemeHandle(GP::Deme::Handle inDemeHandle)
  {
    mDemeHandle = inDemeHandle;
  }

  /*!
   *  \brief Set an handle to the actual GP vivarium.
   *  \param inVivariumHandle Actual GP vivarium handle.
   */
  inline void setVivariumHandle(GP::Vivarium::Handle inVivariumHandle)
  {
    mVivariumHandle = inVivariumHandle;
  }

  /*!
   *  \brief Set the GP system handle.
   *  \param inSystemHandle GP handle to the system.
   */
  inline void setSystemHandle(GP::System::Handle inSystemHandle)
  {
    mSystemHandle = inSystemHandle;
  }

protected:
  std::vector<unsigned int> mCallStack;   //!< The GP execution call stack.

};

}
}

#endif // Beagle_GP_Context_hpp



