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

#ifndef UNIVERSALDATAREADER_H_
#define UNIVERSALDATAREADER_H_

#include "data/BlobReader.h"
#include "data/DataReader.h"
#include "data/UniversalDataElement.h"

/**
 *  A DataAccessor that reads values from the Slate
 *  Contains a default dataValue that must not be NULL,
 *  which is returned if a dataValue request is made and
 *  this Accessor's associated DataElement is unavailable
 *  for some reason (not initialized, orphaned, or failed).
 *
 *  \ingroup data
 */
class UniversalDataReader : public DataReader
{
public:
    UniversalDataReader( Component* owner, UniversalDataElement& universalElement,
                         const DataValue* defaultValue,
                         bool deleteDefaultValue = true );

    UniversalDataReader( Component* owner, UniversalDataElement& universalElement,
                         const Unit& defaultUnit );

    virtual ~UniversalDataReader();

    /**
     *  Returns the DataElement's current accuracy (i.e., for the next write)
     *  \return DataElement's current accuracy
     */
    float getAccuracy( const Unit& unit );

    /**
     *  Returns the DataElement's accuracy at the time of the last write;
     *  \return DataElement's accuracy at the time of the last write.
     */
    float getWrittenAccuracy( const Unit& unit );

    virtual void requestData( bool requestingData )
    {
        requestData( requestingData ? MIN_POWER : NO_STRATEGY );
    }

    void requestData( RequestStrategy requestStrategy );

    UniversalDataElement& getUniversalElement()
    {
        return universalElement_;
    }

protected:

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

    // This is just for convenience -- it's the same thing as element_
    UniversalDataElement& universalElement_;

};

class UniversalBlobReader : public UniversalDataReader, public AbstractBlobReader
{
public:

    virtual ~UniversalBlobReader()
    {}

    // Re-implement abstract method from AbstractBlobReader
    virtual bool read( DataValue& readTo )
    {
        return DataReader::read( readTo );
    }

    // Re-implement abstract method from AbstractBlobReader
    virtual const ElementURI& getUri( void ) const
    {
        return DataReader::getUri();
    }

protected:

    friend class Component;

    UniversalBlobReader( Component* owner, UniversalDataElement& universalElement,
                         const Unit& defaultUnit )
        : UniversalDataReader( owner, universalElement, defaultUnit ),
          AbstractBlobReader( UniversalDataReader::getUri() )
    {}

};

#endif /*UNIVERSALDATAREADER_H_*/
