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


#ifndef LCMUNIVERSALREPORTER_H_
#define LCMUNIVERSALREPORTER_H_

#include "component/SyncComponent.h"
#include "utils/FlexArray.h"
#include "data/LcmMsgWriter.h"
#include "data/StrValue.h"

template<typename T> class FlexArray;

/**
 * Component responsible for publishing periodic logging of
 * Univarsal Slate variable values to LCM.
 *
 *  \ingroup logging
 */
class LcmUniversalReporter : public SyncReporterComponent
{

public:

    typedef enum
    {
        REPORT_CHANGE = 0,
        REPORT_PERIODICALLY = 1,
        REPORT_TOUCHED = 2
    } ReportType;

    /// Constructor for LcmUniversalReporter.
    LcmUniversalReporter();

    virtual ~LcmUniversalReporter();

    /// Run the component
    virtual void run( void );

    bool addReport( unsigned short int uriCode, ReportType type = REPORT_TOUCHED, const Timespan *timespan = NULL );
    void changeReport( unsigned short int uriCode, ReportType type = REPORT_TOUCHED, const Timespan *timespan = NULL );
    void removeReport( unsigned short int uriCode );
    void removeAllReports( void );
    void listReports( void );

    /// External interface functions
    static bool AddReport( unsigned short int uriCode );
    static void RemoveReport( unsigned short int uriCode );
    static void RemoveAllReports( void );

private:

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

    /// Pointer to the singleton-like instance of this component
    static LcmUniversalReporter* Instance_;

    /// Overloads the component's activation function.
    void activateMessaging( void );

    /// Overloads the component's deactivation function.
    void deactivateMessaging( void );

    /// Keeps track of which how we have to report each DataElement
    /// and publishes the value of the Universal to LCM
    class LcmReportItem
    {
    public:
        /// Constructor
        LcmReportItem( Component *owner, unsigned short int uriCode, ReportType type = REPORT_CHANGE, const Timespan *timespan = NULL );

        unsigned short int getUriCode( void );
        ReportType getReportType( void );
        const Timespan* getTimespan( void );

        void setReportType( ReportType type );
        void setTimespan( const Timespan *timespan );

        bool needsReporting( void );
        bool report( void );
        void reportStatus( Logger* logger );

        /// Destructor
        ~LcmReportItem();

    private:

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

        bool initDataReader( void );

        unsigned short int uriCode_;
        ReportType type_;
        Timespan timespan_;

        Component *owner_;
        DataReader *dataReader_;
        LcmMsgWriter *lcmMsg_;
        Timestamp lastReported_;
        Str oldValue_;

        static const StrValue NO_VALUE;
    };

    FlexArray<LcmReportItem*> reportArray_;
    Mutex mutex_;
};

#endif /* LCMUNIVERSALREPORTER_H_ */
