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

#include "component/ComponentRegistry.h"
#include "component/BehaviorRegistry.h"
#include "data/Slate.h"
#include "module/Module.h"
#include "units/Units.h"

/// destructor
Module::~Module()
{
    // Destroy all registered components...
    while( !components_.isEmpty() )
    {
        Component* component = components_.pop();
        if( component )
        {
            // Remove from registry
            ComponentRegistry::Remove( component );
            // And delete
            delete component;
        }
    }
}

/// returns a vector of components in the module
//virtual std::vector<Component*>* getComponents() = 0;
/// returns a vector of components in the module
//std::vector<Component*>* Module::getComponents()
FlexArray<Component*>* Module::getComponents()
{
    return &components_;
}

/// returns the name of the module
const Str& Module::getName() const
{
    return name_;
}

/// returns a description of the module
const Str& Module::getDescription()
{
    return description_;
}

void Module::registerComponent( Component *comp )
{
    comp->getLogger().logComponentLoad( comp, true );
    components_.push( comp );
    // And add to the registry
    ComponentRegistry::Insert( comp );
}

void Module::registerBehaviorCreator( const Str& creatorName, BehaviorCreator behaviorCreator )
{
    BehaviorRegistry::Insert( creatorName, behaviorCreator, this );
}

void Module::unregisterComponent( Component *comp )
{
    // Pop the component from components_ and remove from the registry
    for( int i = components_.getMinIndex(); i <= components_.getMaxIndex(); ++i )
    {
        if( components_[i] == comp )
        {
            comp->getLogger().logComponentLoad( comp, false );

            // Remove from the list
            components_.pop( i );

            // And remove from registry
            ComponentRegistry::Remove( comp );

            delete comp;

            break;
        }
    }
}

bool Module::loadAtStartup( const ConfigURI& loadCfg, Logger& logger, bool forceIfMissing )
{
    int isEnabled = false;
    bool present = Slate::ReadOnce( loadCfg, Units::BOOL, isEnabled, logger );
    if( !present && forceIfMissing )
    {
        isEnabled = true;
    }
    return isEnabled;
}

/// Protected constructor for abstract base class
Module::Module( Str name, Str description )
    : name_( name ), description_( description ), components_( false )
{}
