/** \file
 *
 *  Contains the Module class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

/** \defgroup module Module
 *
 *  Tethys modules are collections of Components that can be
 *  dynamically loaded or unloaded.  Modules may be either Lua
 *  script or compiled c++ code
 */

#ifndef MODULE_H_
#define MODULE_H_

#include "utils/Str.h"

#include "component/Component.h"
#include "component/Behavior.h"

class Slate;

/**
 *  Module is the abstract base class for a collection of Component
 *  objects that can be contained in a loadable module.
 *
 *  Typically, an implementation of Module will call:
 *  registerComponent( new MyComponent() ); for each Component in the module,
 *  except MissionComponents, which require a call to
 *  registerBehaviorCreator( MyComponentIF::NAME, &MyComponent::CreateBehavior );
 *  for each Behavior.
 *
 *  Module implementations must implement:
 *  \li extern "C" Module* create_module(), which just returns a "new" instance
 *  of the module
 *  \n --AND--
 *  \li extern "C" void destroy(Module* module), which calls "delete" on the
 *  module object.
 *
 *  \ingroup module
 */
class Module
{
public:
    /// destructor
    virtual ~Module();

    /// returns a vector of components in the module
    virtual FlexArray<Component*>* getComponents();

    /// returns the name of the module
    virtual const Str &getName() const;

    /// returns a description of the module
    virtual const Str &getDescription();

    /// loads the collection of components belonging to this module
    virtual void loadComponents( Logger& logger ) = 0;

    void registerComponent( Component *comp );

    void registerBehaviorCreator( const Str& creatorName, BehaviorCreator behaviorCreator );

    void unregisterComponent( Component *comp );

protected:
    /// Protected constructor for abstract base class
    Module( Str name, Str description );

    Str name_;
    Str description_;

    //std::vector<Component*> components_;
    FlexArray<Component*> components_;

    bool loadAtStartup( const ConfigURI& loadCfg, Logger& logger, bool forceIfMissing = false );

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    Module( const Module& old ); // disallow copy constructor

};

/// Class factories

/// create_module must be implemented, following the
/// class implementation:
/// extern "C" Module* create_module() {
///     return new MyModuleName();
/// }
typedef Module* create_module_t ();

/// destroy_module must be implemented, following the
/// class implementation:
/// extern "C" void destroy(Module* module) {
///    delete module;
/// }
typedef void destroy_module_t ( Module* );

#endif /*MODULE_H_*/
