#ifndef UTSUSEMINEUTRONEVENTDECODERBASE
#define UTSUSEMINEUTRONEVENTDECODERBASE

#include "Header.hh"
#include "StringTools.hh"
#include "UtsusemiHeader.hh"

////////////////////////////////////
// UtsusemiNeutronEventDecoderBase
////////////////////////////////////

//! Base class Decode Event Data
/*! with UtsusemiEventDataConverterTemplate
 *
 */

class UtsusemiNeutronEventDecoderBase
{

private:
    void Initialize();
        //!< Initialize some parameters
        /*!<
         *   @return None
         */
public:
    UtsusemiNeutronEventDecoderBase();
        //!< Constructor
        /*!<
         */
    ~UtsusemiNeutronEventDecoderBase();
        //!< Destructor
        /*!<
         */

    //////////////////////////////////////////////////////////////////////////
    // public instances
    //////////////////////////////////////////////////////////////////////////
    StringTools *stools;

    //////////////////////////////////////////////////////////////////////////
    // public variables and constants
    //////////////////////////////////////////////////////////////////////////
    std::string _MessageTag;        /**< Message Tag  */
    std::string _version;           /**< version of this */
    UInt4 _INVALID_VALUE;      /**< Invalid value  */


    /* common information */
    UChar _HeaderT0Event;       /**< Header Charactor of T0 Event */
    UChar _HeaderClockEvent;    /**< Header Charactor of Instrument Clock Event */
    UChar _HeaderNeutronEvent;  /**< Header Charactor of Neutron Event */

    static const UInt4 _isNeutronEvent;  /**< for check returned value from DecodeEventData() */
    static const UInt4 _isT0Event;       /**< for check returned value from DecodeEventData() */
    static const UInt4 _isClockEvent;    /**< for check returned value from DecodeEventData() */

    Double _MicroSec_Par_Frame; /** < Time [micro-sec] of one frame (default = MLF_TARGET_FRAME_MICROSEC)  */

    std::vector< std::vector< std::pair< std::string,std::string > > > _LabelsOfEC;  /**< Label and unit for X,Y and E of ElementContainer */

    //////////////////////////////////////////////////////////////////////////
    // public functions
    //////////////////////////////////////////////////////////////////////////
    virtual Int4 SetParametersFromFiles( std::string wiring_file, std::string detector_file );
        //!< set parameters from files
        /*!<
         *   @param wiring_file (std::string) Wiring Info xml file
         *   @param detector_file (std::string) DetectorInfo xml file
         *   @retval 0   no error
         *   @retval -1  Troubles happened
         */
    std::vector<Double> decodeEventDataPy( UInt4 daqId, std::string data );
        //!< call decodeEventData from python
        /*!< This call decodeEventData and return pixel_id and tof.
         *
         *   @param daqId (UInt4) daq ID
         *   @param data  (std::string) a event data
         *   @return std::vector<Double> [0]=pixel ID [1]=tof
         */
    void SetFramePeriod( Double _time ) { _MicroSec_Par_Frame=_time; }

    /////////////////////////////////////////////////////////////
    // Values and Functions required by UtsusemiEventDataConverterTemplate
    /////////////////////////////////////////////////////////////
    UInt4 _EventSize;  /**< size of a event (8[bytes] or 4[bytes]) */
    std::string _instCode;

    virtual void ClearPrevT0Event( UInt4 ThNum );
        //!< Clear Previous T0 Event
        /*!<
         *   @param ThNum (UInt4) Thread number
         *   @retval None
         */
    virtual UInt4 DecodeEventData( UInt4 daqId, UInt4 moduleNo, const UChar *data, UInt4 *pixel_id, double *tof, std::vector<Double>* Clock, UInt4 ThNum=1 );
        //!< decode Event data
        /*!< This decodes any one event data and return type of event.
         *   If a given event is neutron, this sets pixel_id and tof and return 1 (_isNeutronEvent)
         *   If T0 event, this event is stored and return 2 (_isT0Event)
         *   If clock event, return 3
         *   If any other event, return 0
         *   @param daqId (UInt4) daq ID
         *   @param moduleNo (UInt4) module number
         *   @param data  (UChar) one event data
         *   @param pixel_id (UInt4) Pixel ID calculated by given event
         *   @param tof (double) TOF calculated by given event
         *   @param Clock (std::vector<Double>)
         *   @param ThNum (UInt4) Thread number
         *   @retval _isNeutronEvent if neutron event
         *   @retval _isT0Event if T0 event
         *   @retval _isClockEvent if clock event
         *   @retval 0 if any other event
         */
    virtual UInt4 ConvertPixelIdToInnerId( UInt4 pixel_id );
        //!< convert outer PixelID to inner( memory allocated ) ID
        /*!< This is used for conversion from outer PixelID to inner id for allocated vectors
         *
         *   @param pixel_id (UInt4) pixel ID
         *   @return inner ID (UInt4)
         */
    virtual std::vector<UInt4> PutPixelIdList( bool isInner );
        //!< return std::vector of existed id from conversion table
        /*!< Conversion table( PixelID <-> inner ID ) is made by WiringFile.
         *   If isInner is true, this puts list of existed inner ID
         *   if false, list of existed pixel ID
         *   @param isInner (bool) parameter to toggle type of return values.
         *   @return list of Id (std::vector<UInt4>)
         */
    virtual std::vector<Double> PutHistBin( UInt4 outerPixelId );
        //!< put binning calculated by Efix
        /*!< For direct convertion from tof to phisical values,
         *   calculated binning(tof) is required to construct histograms.
         *
         *   @param outerPixelId (UInt4) pixel id
         *   @return binning std::vector
         */
    virtual std::vector<Double> PutXaxis();
        //!< put X axis binning calculated from Tof bin type
        /*!< For direct convertion from tof to phisical values,
         *   calculated X-axis is required to construct histograms.
         *
         *   @param outerPixelId (UInt4) pixel id
         *   @return X-axis std::vector
         */
    virtual bool IsNeutronEvent( UInt4 type );
        //!< return true when type is neutron
        /*!< type is return value from _EventDecoder->DecodeEventData
         *   @param data  (UInt) type
         *   @retval bool
         */
    virtual bool IsT0Event( UInt4 type );
        //!< return true when type is t0 event
        /*!< type is return value from _EventDecoder->DecodeEventData
         *   @param data  (UInt) type
         *   @retval bool
         */
    virtual bool IsInstClockEvent( UInt4 type );
        //!< return true when type is inst clock
        /*!< type is return value from _EventDecoder->DecodeEventData
         *   @param data  (UInt) type
         *   @retval bool
         */
    virtual Double CalcIncrementVal( Double *tof, UInt4 *pixelId );
        //!< Calculation increment value (intensity shift)
        /*!< If incremented value (default=1) shifts by case id and tof,
         *   use this function.
         *   This is used in original Increment function.
         *
         *   @param tof (Double*) given tof
         *   @param pixelId (UInt4*) given pixel id
         *   @return value (Double)
         */
    virtual UInt4 PutNumOfInnerPixels(){ return 0; }
        //!< put the number of inner pixels
        /*!<
         *   @return the number of pixels (UInt4)
         */
    virtual std::vector<Double> PutPixelPosition( UInt4 outerPixelId );
        //!< put pixel position from given outerPixelId
        /*!<
         *   @param outerPixelId (UInt4) pixel id
         *   @return std::vector of pixel position
         */
    virtual Int4 PutTofBinType( UInt4 outerPixelId );
        //!< put type of tof binning
        /*!<
         *   @param outerPixelId (UInt4) pixel id
         *   @return binning type
         */
    virtual std::pair<std::string,std::string> PutXLabel( Int4 convtype );
    virtual std::pair<std::string,std::string> PutYLabel( Int4 convtype );
    virtual std::pair<std::string,std::string> PutELabel( Int4 convtype );
    virtual bool isReverseAxis( Int4 convtype );
    virtual bool isValidConvType( Int4 convtype );
    virtual void SetMaskOnError( UInt4 _outerPixelId, std::vector<Double> &_bin, std::vector<Double> &_err );
    virtual std::vector<double>* PutTimeDependBackGroundInfo( UInt4 _outerPixelId ); //[inamura 160809]
    virtual UInt4 PutNumOfPixelForDet(UInt4 _detId=0){ return 0;}
    virtual Double PutL1(){ return 0.0; }
    virtual Double PutTypicalL2(){ return 0.0; }
    virtual Double PutTypicalDS(){ return 0.0; }
    virtual std::vector<Double> PutTypicalPixelSize(UInt4 _detId=0);
};

#endif
