/** \file
 *  Game Develop
 *  2008-2011 Florian Rival (Florian.Rival@gmail.com)
 */

#ifndef AUTOMATISM_H
#define AUTOMATISM_H

#include <boost/shared_ptr.hpp>
#include <string>
class Object;
class RuntimeScene;
class Scene;
typedef boost::shared_ptr<Object> ObjSPtr;
class TiXmlElement;
#if defined(GD_IDE_ONLY)
class wxWindow;
class Game;
class MainEditorCommand;
#endif

/**
 * \brief Automatism are linked to objects and provided automatic behaviours to these latters.
 */
class GD_API Automatism
{
    public:
        Automatism(std::string automatismTypeName);
        virtual ~Automatism() {};
        virtual boost::shared_ptr<Automatism> Clone() { return boost::shared_ptr<Automatism>(new Automatism(*this));}

        /**
         * Change the name identifying the automatism. Change also AutomatismId.
         */
        void SetName(std::string name_);

        /**
         * Return the name identifying the automatism
         */
        std::string GetName() { return name; }

        /**
         * Return the identifier identifying the automatism
         */
        unsigned int GetAutomatismId() { return automatismId; }

        /**
         * Return the name identifying the type of the automatism
         */
        std::string GetTypeName() { return type; }

        /**
         * Return the identifier identifying the type of the automatism
         */
        unsigned int GetTypeId() { return typeId; }

        /**
         * Set the object owning this automatism
         */
        void SetOwner(Object* owner_) { object = owner_; OnOwnerChanged(); };

        /**
         * Called at each frame before events. Call DoStepPreEvents.
         */
        inline void StepPreEvents(RuntimeScene & scene) { if (activated) DoStepPreEvents(scene); };

        /**
         * Called at each frame after events. Call DoStepPostEvents.
         */
        inline void StepPostEvents(RuntimeScene & scene) { if (activated) DoStepPostEvents(scene); };

        /**
         * De/Activate the automatism
         */
        inline void Activate(bool enable = true) { if ( !activated && enable ) { activated = true; OnActivate(); } else if ( activated && !enable ) { activated = false; OnDeActivate(); } };

        /**
         * Return true if the automatism is activated
         */
        inline bool Activated() const { return activated; };

        /**
         * Reimplement this method to do extra work when the automatism is activated
         */
        virtual void OnActivate() {};
        /**
         * Reimplement this method to do extra work when the automatism is deactivated
         */
        virtual void OnDeActivate() {};

        #if defined(GD_IDE_ONLY)
        /**
         * Save Automatism to XML
         */
        virtual void SaveToXml(TiXmlElement * eventElem) const {}
        #endif

        /**
         * Load Automatism from XML
         */
        virtual void LoadFromXml(const TiXmlElement * eventElem) {}

        #if defined(GD_IDE_ONLY)
        /**
         * Called when user wants to edit the automatism.
         */
        virtual void EditAutomatism( wxWindow* parent, Game & game_, Scene * scene, MainEditorCommand & mainEditorCommand_ ) {};
        #endif

    protected:

        /**
         * Called at each frame before events
         */
        virtual void DoStepPreEvents(RuntimeScene & scene) {};

        /**
         * Called at each frame after events
         */
        virtual void DoStepPostEvents(RuntimeScene & scene) {};

        /**
         * Redefine this method so as to do special works when owner is setted.
         */
        virtual void OnOwnerChanged() {};

        Object* object; ///< Object owning the automatism
        bool activated; ///< True if automatism is running

        std::string name; ///< Name of the automatism
        unsigned int automatismId; ///< The automatismId is the "unsigned-int-equivalent" of the name.

        std::string type; ///< The type indicate of which type is the automatism. ( To test if we can do something, like actions, reserved to specific automatism with it )
        unsigned int typeId; /// The typeId is the "unsigned-int-equivalent" of the type.
};

#endif // AUTOMATISM_H
