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

#ifndef MULTIHANDLER_H_
#define MULTIHANDLER_H_

#include "component/SyncComponent.h"
#include "logger/Logger.h"
#include "process/Handler.h"
#include "utils/FastMap.h"

/**
 *  A pure virtual Handler for a group (list) of Components.
 *
 *  \ingroup process
 *
 *  MultiHandler is a base class for Handlers which might need to
 *  store and keep track of more than one Component.  For example, the
 *  SyncHandler must keep track of all of the Components running
 *  in the ControlThread.
 *
 *  Handles the bookkeeping for keeping a ListOfComponents where each Entry
 *  is a Component.
 *  Also includes basic functions for adding and removing Components.
 *
 *  MultiHandler is a pure virtual.  Derived classes need to define run()
 *
 *  \ingroup process
 */
class MultiHandler : public Handler
{
public:

    typedef FastMap<SyncComponent::CycleOrder, SyncComponent*> OrderedComponents;

    /// Destructor
    virtual ~MultiHandler();

    /// Run the component itself
    /// Should monitor the state of runnable_
    virtual void run() = 0;

    /// Run all items in the list of components
    virtual void runAll();

    /// Run next item in the list of components
    virtual void runNext();

    /// Indicates whether the component is running
    virtual bool isRunning()
    {
        return running_;
    }

    /// Allow runs
    virtual void allowRuns()
    {
        runnable_ = true;
    }

    /// Stop the runs, if they are in progress, and disallow future runs
    virtual void stopRuns()
    {
        runnable_ = false;
    }

    /// is the handler (and contained thread) runnable_?
    const bool isRunnable()
    {
        return runnable_;
    }

    /// Stop the handler (and uninit the component)
    virtual void shutdown( void );

    //== Functions for dealing with the list of components ==
    /// Put a component in the control thread's control.
    /// Does not insert duplicates.
    ///
    /// \param component The SyncComponent to be added
    bool addComponent( SyncComponent* component );

    /// Remove a component from the control thread's control.
    /// (technically only removes the first instance but
    /// list should not allow duplicates.
    ///
    /// \param component SyncComponent to remove (uses == to compare pointers)
    bool removeComponent( SyncComponent* component );

    /// Empty the lists (doesn't actually delete the components)
    void clearComponentList( void );

    /// Dumps information about the components in the list
    /// to the given Logger.
    ///
    /// \param logger The Logger to dump the syslog to.
    void syslogComponentOrder( Logger &logger );

    /// Returns the component that is currently running.
    /// Useful for fault handling.
    Component* getRunningComponent( void )
    {
        return runningComponent_;
    }

protected:

    /// Protected Constructor
    MultiHandler( Component& owner, const Str& name );

    OrderedComponents components_;
    unsigned int runNextIndex_;
    bool runnable_;
    bool running_;
    SyncComponent* runningComponent_;

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

    /// Mutex for thread-safing an instance.
    Mutex mutex_;
};


#endif /*MULTIHANDLER_H_*/
