#ifndef SCENE_H
#define SCENE_H
#include "storage.h"
#include <string>
#include <vector>
#include "me_signal.h"
#include "slot.h"

class SceneObject;
class Config_Interface;
/**
Хранилище сцен

	@author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
*/
class Scene
{
    public:
        Scene( );
        virtual ~Scene();
        /**
         * Загружает описание сцены и все объекы сцены
         * @return true при успехе
         * @author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
         * @date 01.06.2007
         */
        virtual bool load_scene( );
        /**
	 * Добавляет объект на сцену
	 * @param object_name имя объекта
	 * @param object указатель на объект
	 * @param z_level z_level объекта на котором его требуется разместить
	 * @return true при успехе
	 * @author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
	 * @date 01.06.2007
	 */
	virtual bool add_object( const std::string &object_name, SceneObject *obj, int z_level );
        /**
	 * Добавляет объект на сцену
	 * @param object_name имя объекта
	 * @return true при успехе
	 * @author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
	 * @date 01.06.2007
	 */
	virtual bool remove_object( const std::string &object_name );
        /**
         * Отрисовывает сцену
         * @return false если требуется завершить выполнение всех сцен
         * @author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
         * @date 01.06.2007
         */
        virtual bool draw();
	/**
	 * Производит реинициализацию сцены. По умолчанию запускает сигнал scene_name->reinit
	 * @author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
	 * @date 06.07.2009
	 */
	virtual void reinit();

        /**
         * Вызывается при нажатии кнопки мыши. Производит активирование объекта и установку сигналов.
         * @author Denis A. Birukov aka Messenger of death
         * @date 11.01.2008
         */
        DECLARE_SLOT(Scene, _on_mouse_press);

        /**
         * Вызывается при активации сцены.
         * @author Denis A. Birukov aka Messenger of death
         * @date 11.01.2008
         */
        DECLARE_SLOT(Scene, _on_activate);
        
        /**
         * Вызывается при деактивации сцены.
         * @author Denis A. Birukov aka Messenger of death
         * @date 11.01.2008
         */
        DECLARE_SLOT(Scene, _on_deactivate);

        bool scene_loaded() {return _loaded_;}
        void set_video_name( std::string video_name ) {_video_name_ = video_name;}
        void set_storage_file( std::string file ) {_storage_file_ = file;}
    protected:
        virtual void init_signals();
        virtual void init_slots();
        virtual void deinit_slots();

        std::string _name_;
        std::string _video_name_;
        std::string _storage_file_;
        Storage<std::string, SceneObject*> _objects_by_name;
        Storage<std::string, int> _objects_z;
        std::vector<std::string> _object_list;
        std::multimap<int, std::string> _view_queue;
        bool _loaded_;
        SceneObject *_active_object_;
        //Сигналы
        Signal _new_cycle_;
        Signal _activate_signal_;
	Signal _reinit_signal_;
        bool _show_mouse_cursor_;

};

/**
Фабрика сцен

	@author Messenger of death aka Denis A. Birukov <messengerofdeath@gmail.com>
 */
class SceneFabric
{

    public:
        SceneFabric();
        virtual ~SceneFabric();

        Scene* operator[]( std::string name );
        static void add_fabric( std::string name, SceneFabric* fabric );
        virtual Scene* operator()() {return 0;};
    protected:
        static Storage<std::string, SceneFabric*> _fabrics_;
};

template<class T> class SceneFabrics : public SceneFabric
{
    public:
        Scene* operator()()
        {
            return new T;
        }
};
extern SceneFabrics<Scene> GenericSceneFabric;

#endif
