/** \file
 *
 *  Contains the ReadDataComponent class declaration.
 *
 *  ReadDataComponent.h should only be included by ReadDataComponent.cpp
 *  Other classes should include ReadDataIF.h
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef READDATACOMPONENT_H_
#define READDATACOMPONENT_H_

#include "component/Behavior.h"
#include "data/DataAccessor.h"
#include "data/StrValue.h"

class MissionItem;
class MissionNode;
class Module;
class ValueClause;

/**
 *  Contains the ReadDataComponent Behavior/Command. Causes
 *  the indicated measurement to be made by setting
 *  the requestData flag on the reader to true.
 *  Command is satisfied if data is returned by the
 *  reader's writers.
 *
 *  \todo add timing options, etc. to meet requirements:
 *  \ref req_timing_dataAsync and \ref req_timing_dataLoop
 *
 *  ReadDataComponent.h should only be included by ReadDataComponent.cpp
 *  Other classes should include ReadDataIF.h
 *
 *  \ingroup modules_guidance
 */
class ReadDataComponent : public Behavior
{
public:

    static ReadDataComponent* Instance( MissionNode* node, const Str& itemName,
                                        MissionItem* parent, const Module* module, Logger& logger );

    ReadDataComponent( const Str& prefix );

    virtual ~ReadDataComponent();

    /// Initialize function
    void initialize( void );

    /// Initialize function for DataReaders
    void initializeReaders( void );

    /// Just do the run: ignore the results of the satisfied
    void run();

    /// Just do the satisfied: return true if envelope "satisfied"
    bool isSatisfied();

    /// Do the run, and return true if envelope "satisfied"
    bool runIfUnsatisfied();

    /// Called when the mission component becomes preempted.
    void preempted();

    /// Uninit function
    void uninitialize( void );

    /// Mission Component factory interface
    static Behavior* CreateBehavior( const Str& prefix, const Module* module );

protected:

    // Specific sensors which are read
    FlexArray<Component*> sensors_;

    // Names of Variables that are read - converted to readers by initializeReaders
    FlexArray<Str*> readerNames_;

    // Variables that are read - not using readers_ because of readers below
    FlexArray<DataReader*> varReaders_;

    // Reads in the value to test the interval against - null if time used
    DataReader *intervalValueReader_;

    // Last value the interval was tested against.
    double lastIntervalValue_;

    // Reads in the interval
    ValueClause *intervalSettingClause_;

    bool intervalTriggered_;

    bool initializedReaders_;

    DataAccessor::RequestStrategy requestStrategy_;

    static const StrValue NO_VALUE;

    void requestData( bool requestingData );

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

};

#endif /*READDATACOMPONENT_H_*/
