#ifndef UTSUSEMIFILTERTRIGNET
#define UTSUSEMIFILTERTRIGNET

#include "Header.hh"
#include "UtsusemiHeader.hh"
#include "UtsusemiFilterBase.hh"
#include "UtsusemiCaseInfoReaderTrignet.hh"
#include "UtsusemiTrignetDictionary.hh"
#include "UtsusemiTrignetEventDecoderBase.hh"
#include "T0TreatToolsNeunet.hh"
#include "StringTools.hh"
#include "UtsusemiOneTrignetStorage.hh"
#include <boost/filesystem.hpp>
#ifdef MULTH
    #include <omp.h>
#endif

//////////////////////////////////
// UtsusemiFilterTrignet
/////////////////////////////////

//! Filter used by UtsusemiEventCaseTemplate
/*!
 *
 */


class UtsusemiFilterTrignet:
    public UtsusemiFilterBase
{
private:
    std::string MessageTag;
    UInt4 _eventSize;
    UInt4 _NumOfMulTh;

protected:
    std::vector< std::vector< std::vector<UInt4>* >* >* _filterCaseTables; /**< Case Table <index><frame><values> */
    std::vector< std::vector<UInt8>* >* _filterPulseIdLists;          /**< List of PulseId <index><frame> */
    std::vector< std::vector<Double>* >* _filterInstClockLists;       /**< List of InstrumentClock <index><frame> [clock]  */
    void ClearCaseTables( UInt4 index, bool makeNew=false );
    void ClearPIDLists( UInt4 index, bool makeNew=false );
    void ClearICLists( UInt4 index, bool makeNew=false );
    Double _firstT0InstClock;
    StringTools* _stools;

public:
    UtsusemiFilterTrignet();
        //!< Constructor
        /*!<
         */
    ~UtsusemiFilterTrignet();
        //!< Destructor
        /*!<
         */
    //////////////////////////////////////////////////////////////////////////
    // public instances
    //////////////////////////////////////////////////////////////////////////
    UtsusemiCaseInfoReaderTrignet* _UCR;
    UtsusemiOneTrignetStorage* _UTS;
    UtsusemiTrignetEventDecoderBase* _UTD;

    //////////////////////////////////////////////////////////////////////////
    // public variables
    //////////////////////////////////////////////////////////////////////////
    bool isTrigTableReady;
    bool isCaseInfoReady;

    //////////////////////////////////////////////////////////////////////////
    // virtual functions from UtsusemiFilterBase
    //////////////////////////////////////////////////////////////////////////
    std::vector<UInt4> PutListOfCases();
        //!< Puts list of cases
        /*!<
         *  @param None
         *  @return list of cases
         */
    Int4 ReadCaseEvent( UInt4 index, std::vector<std::string> evt_files, std::vector<std::string> t0b_files );
        //!< Reads Case Event file(s).
        /*!< This method is called from UtsusemiEventCasesDecoderTemplate class
         *   and has a role of the interface to this->ReadTrigEvent method.
         *
         *  @param index     (UInt4) index of TrigNET event file
         *  @param evt_files (std::vector<std::string>) path to TrigNET event file(s). Given files are must be belong to same runnumber.
         *  @param t0b_files (std::vector<std::string>) T0 index table for the TrigNET event file
         *  @retval  0 : Succeeded to make filters
         *  @retval -1 : Failed to make filters
         */
    void MakeFilterTables();
        //!< Makes filterCaseTable and filterPulseIdList
        /*!<
         *  @param None
         *  @return None
         */
    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.
         */

    //////////////////////////////////////////////////////////////////////////
    // public functions
    //////////////////////////////////////////////////////////////////////////
    void Initialize();
    void ClearAllTables( UInt4 index, bool makeNew=false );

    void CaseSorting( const UChar* data, UInt8 size, UInt4 index, UInt4 ThNum );
        //!< Sorts TrigNET evetns into each case
        /*!<
         *  @param data  (UChar*)  events
         *  @param size  (UInt8)   size of events (bytes)
         *  @param index (UInt4)   index of TrigNET event file
         *  @param ThNum (UInt4)   Thread number
         *  @return None
         */
    void PreCaseSorting( const UChar* data, std::vector<UInt8> T0Table, UInt4 index );
        //!< Preprocess to CaseSorting
        /*!<
         *  @param data    (UChar*)  events
         *  @param T0Table (UInt8)   T0 index table
         *  @param index   (UInt4)   index of TrigNET event file
         *  @return None
         */
    void ReadTrigEvent( std::string trig_event_file, std::string trig_t0_file, UInt4 index=0 );
    void ReadTrigEvent( std::vector<std::string> trig_event_files, std::vector<std::string> trig_t0_files, UInt4 index=0 );
        //!< Reads TrigNET Event file as Case Event data file
        /*!<
         *  @param trig_event_file (std::string) path to TrigNET event file
         *  @param T0Table         (std::vector<UInt4>) T0 index table for the TrigNET event file
         *  @param index (UInt4) index of TrigNET event file
         *  @return None
         */
    Int4 ReadCaseInfoFile( std::string caseInfo_file );
        //!< Reads Case Info file
        /*!<
         *  @param caseInfo_file (std::string) path to Case Info file
         *  @retval 0 : Succeeded.
         */

    void MakeCaseTable( bool isAppend=false);
        //!< Makes filterCaseTable by analysis TrigNET event data file(s)
        /*!<
         *  @param isAppend (bool) if you need not clear previous CaseTables.
         *  @return None
         */
    std::vector< std::pair<Double,Double> > PutListOfCounterConditions();
        //!< Puts list of Counter-cases Conditions
        /*!<
         *  @param None
         *  @return list of conditions : index is CaseId
         */
    bool DumpTrigEventFile( std::string trig_file, std::string out_file, bool isDecorated=true, bool withT0=false );
        //!< Reads TrigNET event file and writes dump as text file
        /*!<
         *  @param trig_file (std::string) Path to Event File of TrigNET
         *  @param out_file  (std::string) Path to output file
         *  @param isDecorated (bool) Output text decorated for easy-to-understand
         *  @param withT0 (bool) Add T0 events
         *  @retval  true : Succeeded
         *  @retval  false : Failed
         */
    void DumpCaseTable(std::string file="");
    void MakeTimeSlicingCases( std::vector<UInt8> _pulseId, std::vector<double> _seconds );
    void SetTimeSlicing( std::vector<Double> tmp );
    /*-----------  Obsoleted Methods -----------------------------------------*/
    void ReadTrigEventFile( std::string trig_event_file, UInt4 index=0 );
    void ReadTrigEventFile( std::string trig_event_file, std::vector<UInt8> T0Table, UInt4 index=0 );
        //!< Reads TrigNET Event file as Case Event data file (obsoleted)
        /*!<
         *  @param trig_event_file (std::string) path to TrigNET event file
         *  @param T0Table         (std::vector<UInt4>) T0 index table for the TrigNET event file
         *  @param index (UInt4) index of TrigNET event file
         *  @return None
         */
    Int4 ReadCaseEventFiles( UInt4 index, std::vector<std::string> evt_files, std::vector< std::vector<UInt8> > t0b_index_list );
        //!< Reads TrigNET Event file as Case Event data files (obsoleted)
        /*!<
         *  @param evt_files (vecto<std::string>) pathes to TrigNET event files
         *  @param t0b_files (vecto<std::string>) pathes to t0b event for TrigNET event files
         *  @return None
         */
    bool isTimeSlicing();
};
#endif
