#ifndef UTSUSEMIEVENTCASESDECODERTEMPLATE_HH
#define UTSUSEMIEVENTCASESDECODERTEMPLATE_HH

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

//////////////////////////////////
// UtsusemiEventCasesDecoderTemplate
/////////////////////////////////

//! Decode Cases by Event Data
/*!
 *
 */

template <typename T1, typename T2>
class UtsusemiEventCasesDecoderTemplate
{
private:
    void Initialize();
    void Clear( UInt4 flag );

    //std::vector<Double> _rangeSingleTimeSlice;
    StringTools* stools;

    std::string _MessageTag;
    std::vector<Double> _L2OfPixels;
    std::vector<Double> _L1Vect;
    std::vector<Double> _T0ShiftVect;

    std::vector< std::vector<UInt4>* >* _CaseTable;

protected:
    T1* _TT; // T0TreatToolsXXX
    T2* _FF; // Filter function

public:
    UtsusemiEventCasesDecoderTemplate();
        //!< Constructor
        /*!<
         */
    ~UtsusemiEventCasesDecoderTemplate();
        //!< Destructor
        /*!<
         */
    //////////////////////////////////////////////////////////////////////////
    // public instances

    //////////////////////////////////////////////////////////////////////////
    std::vector< std::vector<Double>* >* _pixelPositionVect;      /**< pixel positions ( index : outer pixel id ) */

    //////////////////////////////////////////////////////////////////////////
    // functions required by UtsusemiEventCaseDecoderBase
    //////////////////////////////////////////////////////////////////////////
    // Functions required by UtsusemiEventCaseDecoderTermplate
    UInt4 _NumOfCases;
    bool isCheckedPulseId;
    Double CalcIncrementPosi( Double* tof, UInt4* pixelId, UInt4* caseId );
        //!< Calculation increment position (tof shift)
        /*!< If bin position(tof) shifts by case id and pixelId,
         *   use this function.
         *   This is used in original Increment function.
         *
         *   @param tof (Double*) tof
         *   @param pixelId (UInt4*) given pixel id
         *   @param caseNo (UInt4*) given case number
         *   @return tof (Double) shifted tof
         */
    UInt4 GetCaseFromTof( const UInt4 pixelId, Double* tof, std::vector<UInt4>* caseVec );
        //!< Returns CaseId from given pixel id and tof.
        /*!<
         *   This is used in original Increment function.
         *
         *   @param pixelId (UInt4*) given pixel id
         *   @param tof (Double*) tof
         *   @param caseVec (vecotr<UInt4>*) given std::vector of cases
         *   @return caseId (UInt4)  if 0, this tof will not be incremented to histogram.
         */
    std::vector<UInt8> PutT0Index();
        //!< Puts T0Index.
        /*!<
         *   @param None
         *   @return T0Index std::vector
         */
    std::vector<UInt8> PutPulseId();
        //!< Puts PulseId list.
        /*!<
         *   @param None
         *   @return PulseId std::vector
         */
    std::vector<Double> PutT0ClockDiff();
        //!< Puts differencies clocks between frames
        /*!<
         *   @param None
         *   @return diffencies clocks std::vector
         */
    std::vector< std::vector<UInt4>* >* PutCaseTable();
        //!< Puts CaseTable
        /*!<
         *   @param None
         *   @return CaseTable
         */

    //////////////////////////////////////////////////////////////////////////
    // public functions
    //////////////////////////////////////////////////////////////////////////
    T1* PutT0TreatTools(){ return _TT; }
        //!< Puts T0TreatToolsXXX pointer
        /*!<
         *   @param _tt (T1*) instance of T0TreatToolsXXX
         *   @return None
         */
    T2* PutFilter(){ return _FF; }
        //!< Puts Filger function pointer
        /*!<
         *   @param _ff (T2*) instance of Filter function
         *   @return None
         */
    void ReadCaseInfoFile( std::string filepath );
        //!< Imports Case Info file
        /*!<
         *   @param filepath (std::string) path to CaseInfo file
         *   @return None
         */
    //void ReadCaseEventFiles( std::vector<std::string> files );
    void ReadCaseEvent( UInt4 index, std::vector<std::string> evt_files, std::vector<std::string> t0b_files );
        //!< Reads event data files for cases
        /*!<
         *   @param index (UInt4) The index of TrigNET
         *   @param evt_files (std::vector<std::string>) pathes to event data file
         *   @param t0b_files (std::vector<std::string>) pathes to t0b event data file
         *   @return None
         */
    void ReadCaseEventFiles( UInt4 index, std::vector<std::string> evt_files, std::vector<std::string> t0b_files );
        //!< Reads event data files for cases (obsolete)
        /*!<
         *   @param index (UInt4) The index of TrigNET
         *   @param evt_files (std::vector<std::string>) pathes to event data file
         *   @param t0b_files (std::vector<std::string>) pathes to t0b event data file
         *   @return None
         */
    std::vector<UInt4> PutListOfCases(){ return _FF->PutListOfCases(); }
        //!< Puts list of cases
        /*!<
         *  @param None
         *  @return list of cases
         */
    void CheckCaseTableWithT0Index();
        //!< Checks and rewrite Case table using T0Index
        /*!<
         *   @return None
         */
    std::vector<UInt4> PutNumOfT0ListInCases( Double tof=1.0 );
        //!< Returns the number of T0 for each case
        /*!< retVal[caseId] = T0 counts at caseId
         *
         *   @param tof (Double) Time-of-flight point in each frame to be determined caseId
         *   @return std::vector of the number of T0 : index is caseId : ret[caseId] included caseId=0 <- ret.size() = num_of_cases + 1
         */
    void _CopyCaseTable( std::vector<UInt4>* target, std::vector<UInt4>* orig );
        //!< Copies function between std::vector pointers
        /*!<
         *   @param target (std::vector<UInt4>*) copy to
         *   @param orig   (std::vector<UInt4>*) copy from
         *   @return None
         */
    void SetParamsForShiftTof( std::vector< std::vector<Double>* > *pixelPositionVect, std::vector<Double> *L1Vect, std::vector<Double> *T0ShiftVect );
        //!< Sets some parameters for TOF shift
        /*!< TOF detected at detectors may be shifted that at the sample position.
         *   @param pixelPositionVect    pixel position <pixelId><axis>
         *   @param LiVect               L2 for each pixel <pixelId>
         *   @param T0ShiftVect          T0 shift for each pixel <pixelId>
         *   @return None
         */
    Double ShiftTofAtSample( Double tof, UInt4 pixelId );
        //!< Calculates tof at the sample position
        /*!<
         *   @param tof   (Double) TOF at a detector
         *   @param pixelId  (UInt4) pixelID
         *   @return shifted tof
         */

    // Functions for T0TreatToolsXXX
    Int4 ReadT0IndexEventFile( std::string t0Data, UInt4 num_of_clocks=0 );
        //!< Reads T0Index Event data file
        /*!< This calls _TT->reatT0IndexEvent()
         *
         *   @param t0Data (std::string) path to T0 event data file
         *   @param num_clocks (UInt4) number of clocks before first T0
         *   @retval 0 successful
         */
    Int4 ReadT0IndexEventFile( std::vector<std::string> t0DataSet, UInt4 num_of_clocks=0 );
        //!< Reads T0Index Event data file
        /*!< This calls _TT->reatT0IndexEvent()
         *
         *   @param t0DataSet (std::vector<std::string>) list of path to T0 event data files
         *   @param num_clocks (UInt4) number of clocks before first T0
         *   @retval 0 successful
         */
    std::vector<Double> PutMeasPeriodFromT0();
        //!< Puts the period to be measured
        /*!<
         *   @param None
         *   @return date and time of the period
         */
    bool SetRangeOfSingleTimeSlicing( double startSec, double endSec );
        //!< Sets time range for time slice of event data
        /*!< Values for time are indicated the passed time [sec] from head of event data
         *   @param  startSec     start time [sec]
         *   @param  endSec       end time [sec]
         *   @retval true         succeeded
         *   @retval false        failed
         */
    bool SetRangeOfSingleTimeSlicing( std::string startDate, std::string endDate );
        //!< Sets time range for time slice of event data
        /*!< Values for time are indicated the passed time [sec] from head of event data
         *   std::string format : "YYYY,MM,DD,hh,mm,ss,s.ss", "2011,1,22,13,54,22,0.54"
         *   @param  startDate     start date std::string
         *   @param  endDate       end date std::string
         *   @retval true         succeeded
         *   @retval false        failed
         */
    void MakeTimeSlicingCases( std::vector<std::string> _t0b_files );
        //!< Makes the case list for the time slicing
        /*!< This calls  UtsusemiFilterBase::MakeTimeSlicingCases
         *
         *   @param  _t0b_files (std::vector<std::string>) T0b files
         *   @retval None
         */
    void SetTimeSlicing( std::vector<Double> tmp );
        //!< Sets the list for the time slicing
        /*!< This calls  UtsusemiFilterBase::SetTimeSlicing
         *
         *   @param  tmp (std::vector<Double>) Time range [t0_start,t0_end, t1_start, t1_end, ..., tn_end]
         *   @retval None
         */
};
#include "UtsusemiEventCasesDecoderTemplate.cc"
#endif
