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


#ifndef REPORTER_H_
#define REPORTER_H_

#include "component/SyncComponent.h"
#include "utils/FlexArray.h"
#include "data/StrValue.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:
 *
 *  report add p 2 depth // reports depth every 2 seconds
 *  report add t depth // reports depth every time it is touched
 *  report add c depth // reports depth every time it changes
 *
 *  report rem depth // stops depth from being reported
 *  report clear // stops all items from being reported
 *  report list // list all the items being reported
 *
 *  \ingroup logging
 */
class Reporter : public SyncReporterComponent
{

public:

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

    /// Constructor for Reporter.
    Reporter();

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

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

private:

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

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

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

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

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

        /// Destructor
        ~ReportItem();

    private:

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

        bool initDataReader();

        unsigned short int uriCode_;
        ReportType type_;
        Timespan timespan_;

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

        static const StrValue NO_VALUE;
    };

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

#endif /* REPORTER_H_ */
