/*
 *  Copyright (c) 2007-2008 Cyrille Berger <cberger@cberger.net>
 *
 * 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, or (at your option) any later version of the License.
 *
 * 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; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef _OPENCTL_MODULES_MANAGER_H_
#define _OPENCTL_MODULES_MANAGER_H_

#include <GTLCore/String.h>
#include <OpenCTL/Export.h>

namespace {
  class StaticPointerModulesManager;
}

namespace OpenCTL {
  class Module;
  /**
   * ModulesManager is a class that registers modules that got loaded, and whose functions
   * can be shared with other modules using the "import" keyword of CTL.
   * 
   * Newly created modules aren't automatically added to the Manager. Once a Module is added to
   * the manager it shouldn't get destroyed.
   * To add a Module to the manager, you can call \ref registerModule .
   * 
   * @ingroup OpenCTL
   */
  class OPENCTL_EXPORT ModulesManager {
      friend class ::StaticPointerModulesManager;
    private:
      GTL_NO_COPY(ModulesManager);
      ModulesManager();
      ~ModulesManager();
    public:
      /**
       * @param name of the module
       * @return the module with the given name. Or 0 if there is no module with that name.
       */
      Module* module(const GTLCore::String& name);
      /**
       * Load the module. This function will look for a module in the list of directories,
       * the module is expected to be called "name.ctl" where 'name' is the parameter.
       * In the following example, the ModulesManager will look for a file called "myModule.ctl" :
       * @code
       *  ModulesManager::instance()->loadModule("myModule");
       * @endcode
       * 
       * Modules that get loaded by this function are then registered.
       * 
       * If the module is already registered in the ModulesManager, this function
       * will return the already existing module.
       * 
       * @param name of the module
       * @return a pointer to the module
       */
      Module* loadModule(const GTLCore::String& name);
      /**
       * This function will register a module for later use.
       */
      void registerModule(const GTLCore::String& name, Module* );
      /**
       * Add a directory to the list of directory that get searched for modules.
       * This function is not thread-safe.
       */
      void addDirectory(const GTLCore::String& directory);
    public:
      /**
       * @return the instance to the singleton ModulesManager
       */
      static ModulesManager* instance();
    private:
      struct Private;
      Private* const d;
  };
}

#endif
