/*
 * This source file is part of KEOS (Free 3D Engine)
 * For the latest info, see http://www.keosengine.org/
 * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
 * 
 * This program 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 of the License, or (at your option) any later
 * version.
 *
 * This program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 * http://www.gnu.org/copyleft/lesser.txt.
 *
 */

#ifndef KEOS_ROOT_H
#define KEOS_ROOT_H

#include "KeosPrerequisites.h"
#include "KeosSingleton.h"
#include "KeosConfigOption.h"

#if KEOS_COMPILER == KEOS_COMPILER_MSVC
#   define SET_TERM_HANDLER { set_terminate( &Keos::CRoot::_TermHandler ); }
#else
#   define SET_TERM_HANDLER { std::set_terminate( &Keos::CRoot::_TermHandler ); }
#endif

namespace Keos
{
    typedef void (*DLL_START_PLUGIN)(void);
    typedef void (*DLL_STOP_PLUGIN)(void);

	typedef std::vector<IRenderSystem*> RenderSystemList;

    //-----------------------------------------------------------------------
    /** The root class of the Keos system.
     *  The Keos::CRoot class represents a starting point for the client
     *  application. From here, the application can gain access to the
     *  fundamentals of the system, namely the rendering systems
     *  available, management of saved configurations, logging, and
     *  access to other classes in the system. Acts as a hub from which
     *  all other objects may be reached. An instance of Root must be
     *  created before any other Keos operations are called. Once an
     *  instance has been created, the same instance is accessible
     *  throughout the life of that object by using CRoot::Instance.
     */
    class KEOS_EXPORT CRoot : public CSingleton<CRoot>
    {
    friend CSingleton<CRoot>;

    public :

        static void _TermHandler(void);
        
        /** Initialises the renderer.
         *  @param
         *      bAutoCreateWindow If true, a rendering window will
         *        automatically be created (saving a call to
         *        RenderSystem::createRenderWindow).
         *  @param strWindowTitle Window's title.
         *  @returns
         *      A pointer to the automatically created window, if
         *      requested, otherwise <b>NULL</b>.
         */
        IRenderWindow* Initialise(bool bAutoCreateWindow, const String& strWindowTitle = "KEOS Render Window");

        /** Sets the rendering subsystem to be used.
         *  This method indicates to Keos which rendering system is to be
         *  used (e.g. Direct3D, OpenGL etc). 
         *  @param pRenderSystem Pointer to the render system to use.
         */
        void SetRenderSystem(IRenderSystem* pRenderSystem);
        
		/** Adds a new rendering subsystem to the list of available renderers.
		 *  @param pNewRend Pointer to the new render system.
         */
		void AddRenderSystem(IRenderSystem *pNewRend);

        /** Retrieve a pointer to the currently render system.
         */
        IRenderSystem* GetRenderSystem()
        {
            return m_pActiveRenderSystem;
        }

		/** Retrieve a list of the available render systems.
         */
        RenderSystemList* GetAvailableRenderers(void)
		{
			return &m_Renderers;
		}

        /** Manually load a plugin.
		 *  @param strPluginName Name of the plugin library to load.
		 */
		void LoadPlugin(const String& strPluginName);

        /** Unloads all loaded plugins.
         */
        void UnloadPlugins(void);

        /** If the StartRendering() has been called, the rendering loop will stop.
         */
        void StopRendering(void);

        /** Starts / restarts the automatic rendering cycle.
         *  This method begins the automatic rendering of the scene. It
         *  will <b>NOT</b> return until the rendering cycle is halted.
         */
        void StartRendering(void);

        /** Render one frame. 
         *  Updates all the render targets automatically and then returns.
         */
        bool RenderOneFrame(void);

        /** Shuts down the system.
         */
        void Shutdown(void);

        /** Gets a pointer to the central timer used for all KEOS timings. 
         */
        CTimer* GetTimer(void);

        /** Checks for saved video/sound/etc settings.
         *  @returns If a valid configuration was found, <b>true</b> is returned.
         */
        bool RestoreConfig(void);

        /** Save video/sound/etc settings.
         */
        void SaveConfig(void);

        /** Displays a dialog asking the user to choose system settings.
         *  @returns If the user clicked 'Ok', <b>true</b> is returned.  
         */
        bool ShowConfigDialog(void);

		/** Return version of Keos.
		 */
		const String& GetVersion()
		{ return m_strVersion; }
  
    private :

        /** Default constructor.
         */
        CRoot();

        /** Destructor.
         */
        ~CRoot();

        //! The active rendering system
        IRenderSystem* m_pActiveRenderSystem;

        //! Timer used for all KEOS timings
        CTimer * m_pTimer;

        //! List of loaded plugins
        std::vector<CDynLib*> m_PluginLibs;

        //! Used to stop the loop rendering
        bool m_bStopRendering;

		//! List of availaible RenderSystem
		RenderSystemList m_Renderers;

		//! Keos version
		String m_strVersion;
        
    };

} // namespace Keos

#endif // KEOS_ROOT_H
