/***************************************************************************
 *   Copyright (C) 2004 by Raphael Langerhorst                             *
 *   raphael-langerhorst@gmx.at                                            *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

#ifndef GBEGMOVEAGENTH
#define GBEGMOVEAGENTH

#include <GAgent.h>
#include <GVector3.h>

#include <qtimer.h>
#include <qdatetime.h>

namespace GBE
{

/**
  \class GMoveAgent GMoveAgent.h
  \brief Handles movements for forms.

  This agent periodically updates the forms position according
  to the current speed.
  
  Adds the following xml data to the element data:
  <dynamics>
    <slowdownfactor>double value</slowdownfactor>
    <translationspeed>double value</translationspeed>
    <rotationspeed>double value</rotationspeed>
    <updateinterval>unsigned long integer value</updateinterval>
  </dynamics>
  
  @see GCS::GForm
  
  @todo add another value: last update time and use it on execution resuming
*/
class GMoveAgent : public GCS::GAgent
{
  Q_OBJECT

  protected:
  
    /**
     * Used to measure time intervals between updates.
     */
    QTime Time;

  public:
    /**
     * Constructor.
     */
    GMoveAgent();

    /**
     * Destructor.
     */
    virtual ~GMoveAgent();
    
  protected:
    
    /**
     * Constantly updates the forms position and also slows down according to SlowDownFactor.
     * @see Interval, SlowDownFactor, updateForm()
     */
    virtual void run();
    
  protected slots:
    
    /**
     * Here the actual updating is performed.
     * 
     * Subtracts CurrentSpeed * SlowDownFraction*elapsed_time from CurrentSpeed
     * for translation and rotation speed.
     * 
     * @see run()
     */
    virtual void updateForm();

  public slots:
  
    /**
     * Adds given speed impulse to the form's speed.
     */
    virtual void addTranslationSpeedImpulse(const GCS::GVector3& add_speed);
    
    /**
     * Adds given rotation impulse around given axis to the form's
     * rotation speed.
     */
    virtual void addRotationImpulse(const GCS::GVector3& rotation_impulse);
    
    /**
     * Sets both translation speed and rotation speed to zero.
     */
    virtual void fullStop();
    
    /**
     * Initializes translation speed in the element data
     */
    virtual void initTranslationSpeed(const GCS::GVector3& speed);
    
    /**
     * Initializes rotation speed in the element data.
     */
    virtual void initRotationSpeed(const GCS::GVector3& speed);
    
    /**
     * Initializes slow down fractor in the element data.
     * This value should be between 0 and 1 to get some slowdown.
     * If you set it higher than 1 it will actually accelerate.
     */
    virtual void initSlowDownFactor(double factor);
    
    /**
     * Initializes update interval in the element data.
     */
    virtual void initUpdateInterval(unsigned long interval);
};

};

#endif
