#ifndef UTSUSEMIREADOUTEVENTDECODERTEMPLATE_HH
#define UTSUSEMIREADOUTEVENTDECODERTEMPLATE_HH

#include "UtsusemiHeader.hh"
#include "UtsusemiNeutronEventDecoderBase.hh"
#include "WiringInfoConversionDictionary.hh"

#ifdef MULTH
    #include <omp.h>
#endif

//////////////////////////////////
// UtsusemiReadoutEventDecoderTemplate
/////////////////////////////////

//! Decode Event Data of Readout (2D) for Utsusemi
/*!
 *
 */


template <typename T1, typename T2>
class UtsusemiReadoutEventDecoderTemplate:
    public UtsusemiNeutronEventDecoderBase
{
private:
    std::string _MessageTag;  /**<  Message Tag */
    StringTools* _st;

protected:
    UInt4 _NumOfMulTh;
    UChar* _prevT0Event;  /**< for use to keep previous T0 Event */
    void Initialize();
        //!< Initialize some parameters
        /*!<
         *   @return None
         */
    void Clear();
        //!< Clear some parameters
        /*!<
         *   @return None
         */

public:
    UtsusemiReadoutEventDecoderTemplate();
        //!< Constructor
        /*!<
         */
    virtual ~UtsusemiReadoutEventDecoderTemplate();
        //!< Destructor
        /*!<
         */


    //////////////////////////////////////////////////////////////////////////
    // public instances
    //////////////////////////////////////////////////////////////////////////
    T1 *_wirInfo;
    T2 *_detInfo;
    WiringInfoConversionDictionary *_wirDict;
    //////////////////////////////////////////////////////////////////////////
    // public variables
    //////////////////////////////////////////////////////////////////////////
    std::vector< std::vector<Double>* > _pixelPositionVect;   /**< pixel positions ( index : outer pixel id ) */
    std::vector< Double > _pixelSolidAngleVect;          /**< pixel solid angle ( index : outer pixel id ) */
    bool _isRequiredPosiInfo;
    bool _isSetFrameBoundary;
    //////////////////////////////////////////////////////////////////////////
    // virtual functions from UtsusemiNeutronEventDecorderBase
    //////////////////////////////////////////////////////////////////////////
    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
         */

    //////////////////////////////////////////////////////////////////////////
    // virtual functions required by UtsusemiEventDataConverterTemplate
    //////////////////////////////////////////////////////////////////////////
    virtual void ClearPrevT0Event( UInt4 ThNum );
        //!< Clear Previous T0 Event
        /*!<
         *   @param ThNum (UInt4) Thread number
         *   @retval None
         */
    virtual UInt4 DecodeEventData( UInt4 daqId, UInt4 modNo, const UChar *data, UInt4 *pixel_id, double *tof, std::vector<Double>* Clock, UInt4 ThNum )=0;
        //!< 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 modNo (UInt4) module No
         *   @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 UInt4 ConvertPixelIdToDetId( UInt4 pixel_id );
        //!< convert outer PixelID to outer DetID
        /*!< This is used to get det Id from outer PixelID to
         *
         *   @param pixel_id (UInt4) pixel ID
         *   @return detID (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
         */
    UInt4 PutNumOfInnerPixels();
        //!< put the number of inner pixels
        /*!<
         *   @return the number of pixels (UInt4)
         */
    std::vector<Double> PutPixelPosition( UInt4 outerPixelId );
        //!< put pixel position from given outerPixelId
        /*!<
         *   @param  outerPixelId (UInt4) pixel id
         *   @return std::vector of pixel position
         */
    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 void SetMaskOnError( UInt4 _outerPixelId, std::vector<Double> &_bin, std::vector<Double> &_err );
    //////////////////////////////////////////////////////////////////////////
    // public functions
    //////////////////////////////////////////////////////////////////////////
    virtual void CalcPixelPosition(){}
        //!< calculate the position of each pixel
        /*!< This calculates the position of pixel from stored information.
         *   Potisions are stored to _pixelPositionVect.
         *   @return None
         */
    UInt4 PutMaxOfPixelId();
        //!< put maximum number of pixel id
        /*!<
         *   @return maximum number (UInt4)
         */
    Int4 PutTofBinType( UInt4 outerPixelId );
        //!< put Tof Bin Type of given outerPixelId
        /*!< Tof Bin Type comes from Wiring File
         *
         *   @param  outerPixelId (UInt4) pixel id
         *   @return tof bin type
         */
    virtual std::vector<Double> PutXaxis();
        //!< put x axis values
        /*!< When TofBinType is for direct conversion from event data to energy,
         *   this returns calculated x-axis values.
         *
         *   @param  None
         *   @return std::vector for values on calculated x-axis
         */
    bool isReverseAxis( Int4 convtype );
    bool isValidConvType( Int4 convtype );
    bool SetTofOriginShift( UInt4 cType );
    bool SetTofOriginShift( UInt4 cType, std::vector<Double> params );
    std::vector<Double> PutLambda( UInt4 pixel_id );
    UInt4 PutNumOfPixelForDet(UInt4 _detId=0);
    Double PutL1();
    Double PutTypicalL2();
    Double PutTypicalDS();
    std::vector<Double> PutTypicalPixelSize(UInt4 _detId=0);
};
#include "UtsusemiReadoutEventDecoderTemplate.cc"
#endif
