#ifndef UTSUSEMIREDISPUBSUBEVENTREADER_HH
#define UTSUSEMIREDISPUBSUBEVENTREADER_HH

/* Header.hh should be included on the top to avoid environments
 * specific issues (see Header.hh for the detail).
 */
#include "Header.hh"

#include "UtsusemiHeader.hh"
#include "RedisPubSub.hh"
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <unistd.h>
#include <time.h>
///////////////////////////////////////////
//  UtsusemiRedisPubSubEventReader
///////////////////////////////////////////

//! Queue PubSub access for Event Data
/*!
 *
 *   tt=QM.UtsusemiRedisPubSubEventReader()
 *   tt.Subscribe( "SIK", runNo, daqId, modNo, "localhost", 2223 )
 *   tt.Read()
 *   tt.Unsubscribe()
 *
 *   ret=tt.Test( "SIK", runNo, daqId, modNo, "Test.bin","localhost", 2223)
 */
class UtsusemiRedisPubSubEventReader
{
public:
    std::vector<UInt8> LeftPulseIdTable;
    std::vector<UInt4> LeftT0IndexTable;
    std::vector<UInt4> LeftDiffClockTable;
    std::vector<Char>  LeftEdbEvents;

    std::string _MessageTag;
    UInt4 _ByteOfEvent;

    UtsusemiRedisPubSubEventReader();
    UtsusemiRedisPubSubEventReader( const UtsusemiRedisPubSubEventReader& obj );
    ~UtsusemiRedisPubSubEventReader();

    bool Subscribe( std::string inst_code, std::string keyRoot, std::string host="localhost", UInt4 port=6379 );
    bool Subscribe( std::string instCode, UInt4 runNo, UInt4 daqId, UInt4 modNo, std::string host="localhost", UInt4 port=6379, std::string date="" );
    bool Unsubscribe();
    bool Read( UChar *data, UInt4 *num_of_data, std::vector<UInt8> *t0PulseId, std::vector<Double> *t0DiffClock, std::vector<UInt8> *t0Index );

    bool Test( std::string inst_code, UInt4 runNo, UInt4 daqId, UInt4 modNo, std::string saveFile, std::string host, UInt4 port, UInt4 loop );
    bool simpleTest( std::string inst_code, std::string keyRoot, std::string saveFile, std::string host, UInt4 port );

    Double PutFirstClock(){ return _firstClock; }
    Double PutLastClock(){ return _preClock; }
    static const UInt4 REDIS_PUBSUB_BUF_SIZE;
    static const UInt4 REDIS_PUBSUB_TIMEOUT;
  bool isDebug;

protected:
    bool _getOfT0b( std::vector<UInt8> &t0Index, std::vector<UInt8> &t0Pid, std::vector<Double> &t0Clk );
    bool _getOfEdb( Char *buf, UInt4 &size_buf, UInt4 &ind, std::vector<UInt8> &t0Index );
    std::string _makeKeyRoot( std::string instCode, UInt4 runNo, UInt4 daqId, UInt4 modNo, std::string date="" );
    /////////////////////////////////////////////////////////
    void decodeT0InfoEvent(UChar event[], UInt8 *num, Double *clock);
    void decodeT0InfoEvent(UChar event[], UInt8 *num );
    void decodeClockIncEvent(UChar event[], Double *clock);
    void decodePidEvent(UChar eventPid[], UInt8 *pid );
    void decodeT0ClockEvent(UChar eventClock[], Double *clock);
    /////////////////////////////////////////////////////////

    std::string _KeyOfEdb;  /**< Key to subscribe edb data */
    std::string _KeyOfT0b;  /**< Key to subscribe t0b data */

    RedisSyncSubscriber* _RedisPubSubEdb;
    RedisSyncSubscriber* _RedisPubSubT0b;

    UInt8 _prePid;
    Double _preClock;
    Double _firstClock;

private:
    void Initialize();

};

#endif
