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


#ifndef MAINTAINER_H_
#define MAINTAINER_H_

#include "component/SyncComponent.h"
#include "data/DataValue.h"
#include "utils/FlexArray.h"

template<typename T> class FlexArray;

/**
 *  Component responsible for handling periodic logging of variable
 *  values to the syslog and the console, etc.
 *
 *  Typically managed by console commands.
 *  Examples:
 *
 *  maintain add HorizontalControl.horizontalMode 2 enum // Sets HorizontalControl.horizontalMode to 2 every cycle
 *  maintain rem HorizontalControl.horizontalMode // stops HorizontalControl.horizontalMode from being maintained
 *  maintain clear // stops all items from being maintained
 *  maintain list // list all the items being maintained
 *
 *  \ingroup logging
 */
class Maintainer
{

public:

    /// Constructor for Maintainer.
    Maintainer();

    void addMaintain( unsigned short int uriCode, DataValue* dataValue,
                      SyncComponent::CycleOrder cycleOrder, bool unavailable, bool invalid );
    void removeMaintain( unsigned short int uriCode );
    void removeAllMaintains();
    void listMaintains();

private:

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

    /// Keeps track of which how we have to maintain each DataElement
    class MaintainItem : public SyncMaintainerComponent
    {
    public:
        /// Constructor
        MaintainItem( unsigned short int uriCode, DataValue* dataValue,
                      SyncComponent::CycleOrder cycleOrder, bool unavailable, bool invalid );

        virtual void run()
        {
            maintain();
        }

        Str makeName( unsigned short int uriCode );
        unsigned short int getUriCode();
        DataValue* getDataValue();

        void setDataValue( DataValue* dataValue );
        bool maintain();
        void maintainStatus();

        void setUnavailable( bool unavailable )
        {
            unavailable_ = unavailable;
        }

        void setInvalid( bool invalid )
        {
            invalid_ = invalid;
        }

        /// Destructor
        ~MaintainItem();

    private:

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

        bool initDataWriter();

        unsigned short int uriCode_;
        DataElement *dataElement_;
        DataValue *dataValue_;
        Component *owner_;
        DataWriter *dataWriter_;
        bool unavailable_;
        bool invalid_;
    };

    FlexArray<MaintainItem*> maintainArray_;
    Mutex mutex_;
};

#endif /* MAINTAINER_H_ */
