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

#ifndef SLATEBRIDGE_H_
#define SLATEBRIDGE_H_

#include <vector>
#include <algorithm>
#include "utils/Str.h"
#include "units/UnitRegistry.h"
#include "component/ComponentRegistry.h"
#include "data/StrValue.h"


typedef std::vector<Str> NameVec;
typedef std::vector<unsigned short> CodeVec;
typedef FastMap<const Str, DataWriter*> DataWriterMap;
// typedef FastMap<const Str, BlobWriter*> BlobWriterMap;

/**
 * SlateBridge provides a flexible interface to Slate data writers.
 *
 *  \ingroup data
 */
class SlateBridge
{
public:

    SlateBridge( Component* owner );

    /// Destructor
    virtual ~SlateBridge();

    virtual bool slateWrite( const Str& name, const Str& unit, const unsigned char data, const Timestamp& timestamp );
    virtual bool slateWrite( const Str& name, const Str& unit, const double data, const Timestamp& timestamp );
    virtual bool slateWrite( const Str& name, const Str& unit, const float data, const Timestamp& timestamp );
    virtual bool slateWrite( const Str& name, const Str& unit, const int data, const Timestamp& timestamp );

    virtual DataWriter* getSlateWriter( const Str& name, const Unit& unit );

    virtual void authorizeComponent( const Str& name );

    virtual void authorizeName( const Str& name );

    virtual void deauthorize( const Str& name );

    bool isAuthorized( const Str& name );


    virtual DataReader* getSlateReader( const Str& name, const Unit& unit );

    virtual unsigned short int requestSlate( const Str& name, const Str& unitName, bool request = true );

    virtual void clearRequested( void );


    virtual void parseVarName( const Str& inputStr, Str& componentName, Str& variableName );

protected:

    Component* owner_;

private:

    template<class T>
    bool slateWriteT( const Str& name, const Str& unitStr, const T data, const Timestamp& timestamp )
    {
        const Unit* unit = UnitRegistry::FindUnit( unitStr );

        if( unit != NULL )
        {
            DataWriter* writer = getSlateWriter( name, *unit );

            if( writer != NULL )
            {
                DataValue& value = *unit->dataValue( data );
                writer->setInvalid( false );
                return writer->write( value, timestamp );
            }
        }
        else
        {
            owner_->getLogger().syslog( "Unit " + unitStr + " is unknown.", Syslog::ERROR );
        }

        return false;
    }

    static const StrValue NO_VALUE;

    DataWriterMap writerMap_;

    CodeVec::iterator findCode( unsigned short code );

    CodeVec requestedCodes_;

    NameVec authorizedNames_;
};


#endif /*SLATEBRIDGE_H_*/
