#ifndef UTSUSEMIREADOUTEVENTDECODERTEMPLATE_CC
#define UTSUSEMIREADOUTEVENTDECODERTEMPLATE_CC

#include "UtsusemiReadoutEventDecoderTemplate.hh"
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UtsusemiReadoutEventDecoderTemplate<T1,T2>::
UtsusemiReadoutEventDecoderTemplate():
UtsusemiNeutronEventDecoderBase()
{
    Initialize();
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UtsusemiReadoutEventDecoderTemplate<T1,T2>::
~UtsusemiReadoutEventDecoderTemplate(){
    Clear();
    delete [] _prevT0Event;
    if (_detInfo!=NULL) delete _detInfo;
    if (_wirInfo!=NULL) delete _wirInfo;
    if (_wirDict!=NULL) delete _wirDict;
    delete _st;
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
void UtsusemiReadoutEventDecoderTemplate<T1,T2>::
Initialize(){
    _detInfo = NULL;
    _wirInfo = NULL;
    _wirDict = NULL;

    _EventSize = (UInt4)8;
    _HeaderT0Event      = (UChar)0x00;
    _HeaderClockEvent   = (UChar)0x00;
    _HeaderNeutronEvent = (UChar)0x00;

    _NumOfMulTh = UtsusemiGetNumOfMulTh();
#ifdef MULTH
    _prevT0Event = new UChar[ _EventSize*_NumOfMulTh ];
    for (UInt4 i=0;i<_EventSize*_NumOfMulTh;i++) *(_prevT0Event+i)=0x00;
#else
    _prevT0Event = new UChar[ _EventSize*2 ];
    for (UInt4 i=0;i<_EventSize*2;i++) *(_prevT0Event+i)=0x00;
#endif

    _MessageTag="UtsusemiReadoutEventDecoderTemplate >> ";

    _pixelPositionVect.clear();
    _pixelSolidAngleVect.clear();
    _isRequiredPosiInfo=true;

    _st = new StringTools();
    _isSetFrameBoundary = false;
}
/////////////////////////////////////////////////////////
template <typename T1, typename T2>
void UtsusemiReadoutEventDecoderTemplate<T1,T2>::
Clear(){
    if (!(_pixelPositionVect.empty())){
        for (UInt4 i=0;i<_pixelPositionVect.size();i++)
            if (_pixelPositionVect[i]!=NULL) delete _pixelPositionVect[i];

        _pixelPositionVect.clear();
    }
    _pixelSolidAngleVect.clear();
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
Int4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
SetParametersFromFiles( std::string wiring_file, std::string detector_file ){
    if (_detInfo!=NULL) {
        delete _detInfo;
        _detInfo=NULL;
    }
    if (_wirInfo!=NULL) {
        delete _wirInfo;
        _wirInfo=NULL;
    }

    _wirInfo = new T1(wiring_file);
    _detInfo = new T2(detector_file);
    _wirDict = new WiringInfoConversionDictionary();

    if ((_detInfo->_Status)&&(_wirInfo->_Status)){
        UtsusemiMessage(_MessageTag+"SetParametersFromFilesBase finished successfully. ");
    }else{
        UtsusemiError(_MessageTag+"SetParametersFromFilesBase fails. ");
        delete _wirInfo;
        delete _detInfo;
        delete _wirDict;
        _wirInfo = NULL;
        _detInfo = NULL;
        _wirDict = NULL;
        return -1;
    }

    if (_isRequiredPosiInfo){
        CalcPixelPosition();
        _wirDict->SetPixelPosition( _pixelPositionVect );
    }else{
      _pixelPositionVect.clear();
      _pixelPositionVect.resize(_wirInfo->MaxPixelId +1,NULL );
      _wirDict->SetPixelPosition( _pixelPositionVect );
    }
    _wirDict->SetTimeFocusingParam( _detInfo->PutTfp() );
    _wirDict->SetL1( _detInfo->PutInstL1() );
    std::vector<Double> p = _detInfo->PutInstSamplePosition();
    _wirDict->SetSamplePosition( p[0],p[1],p[2] );
    _instCode = _wirInfo->InstCode;

    // Set FrameBoundary for each pixel
    if (_wirInfo->FrameBoundaryInfo.frameNo!=0){
        if ( _wirDict->SetFrameBoundaryInfoList(
                 _wirInfo->FrameBoundaryInfo.frameNo,
                 _wirInfo->FrameBoundaryInfo.boundaryValue,
                 _wirInfo->FrameBoundaryInfo.boundaryType
                 ) ){
            _isSetFrameBoundary=true;
        }else{
            UtsusemiError(_MessageTag+"SetParameterFromFilesBase >> SetFrameBounadryInfoList failed" );
            _isSetFrameBoundary=false;
            delete _wirInfo;
            delete _detInfo;
            delete _wirDict;
            _wirInfo = NULL;
            _detInfo = NULL;
            _wirDict = NULL;
            return -1;
        }
    }

    return 0;

}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
void UtsusemiReadoutEventDecoderTemplate<T1,T2>::
ClearPrevT0Event(UInt4 ThNum){
    for (UInt4 i=0;i<_EventSize;i++) _prevT0Event[(_EventSize*ThNum)+i]=0x00;
}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UInt4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
ConvertPixelIdToInnerId( UInt4 pixel_id ){
    return _wirInfo->PixelIdToInnerId[pixel_id];
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UInt4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
ConvertPixelIdToDetId( UInt4 pixel_id ){
    return _wirInfo->PixelConvTable->at(pixel_id)->at(2);
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UInt4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutNumOfInnerPixels(){
    return _wirInfo->NumOfInnerPixel;
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UInt4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutMaxOfPixelId(){
    return _wirInfo->MaxPixelId;
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<UInt4> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutPixelIdList( bool isInner ){
    std::vector<UInt4> ret;
    UInt4 ind = 0;
    if (isInner) ind = 1;

    for (UInt4 i=0; i<(_wirInfo->PixelConvTable->size()); i++){
        if ( _wirInfo->PixelConvTable->at(i)!=NULL ){
            if (_wirInfo->PixelConvTable->at(i)->at(ind)!=-1) ret.push_back(i);
        }
    }
    return ret;
}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
Int4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutTofBinType( UInt4 outerPixelId ){

    if (_wirInfo->TofBinInfoList[outerPixelId]==NULL){
        UtsusemiError(_MessageTag+"PutTofBinType > TofBInInfoList is NULL pixid="+_st->UInt4ToString(outerPixelId));
        return -1;
    }
    std::vector<Double>* tofBinInfo = _wirInfo->TofBinInfoList[outerPixelId];

    UInt4 tof_pat_id = (UInt4)(tofBinInfo->at(0));
    if (_wirInfo->TofBinPtnInfo[ tof_pat_id ]==NULL){
        UtsusemiError(_MessageTag+"PutTofBinType > TofBInInfo is NULL tof_pat_id="+_st->UInt4ToString(tof_pat_id));
        return -1;
    }

    return  _wirInfo->TofBinPtnInfo[ tof_pat_id ]->type;

}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<Double> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutPixelPosition( UInt4 outerPixelId ){
    std::vector<Double>* p_vec = _pixelPositionVect[ outerPixelId ];
    std::vector<Double> ret;
    ret.push_back( p_vec->at(0) );
    ret.push_back( p_vec->at(1) );
    ret.push_back( p_vec->at(2) );
    return ret;

}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<Double> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutXaxis(){
    if (_wirDict!=NULL)
        return _wirDict->PutXaxis();
    else{
        UtsusemiError(_MessageTag+"PutXaxis > have not executed SetParametersFromFiles() yet.");
        std::vector<Double> tmp;
        return tmp;
    }

}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
bool UtsusemiReadoutEventDecoderTemplate<T1,T2>::
isReverseAxis( Int4 convtype ){
    if (_wirDict!=NULL)
        return _wirDict->isReverseXaxis( convtype );
    else{
        UtsusemiError(_MessageTag+"isReverseAxis > have not executed SetParametersFromFiles() yet.");
        return false;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
bool UtsusemiReadoutEventDecoderTemplate<T1,T2>::
isValidConvType( Int4 convtype ){
    if (_wirDict!=NULL)
        return _wirDict->isValidConvType( convtype );
    else{
        UtsusemiError(_MessageTag+"isValidConvType > have not executed SetParametersFromFiles() yet.");
        return false;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<Double> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutHistBin( UInt4 outerPixelId ){
    std::vector<Double> ret;
    ret.clear();

    if (_wirInfo->TofBinInfoList[outerPixelId]==NULL) {
        UtsusemiError(_MessageTag+"PutHistBin > TofBinInfo[pixelId]=NULL : pixel_id="+_st->UInt4ToString(outerPixelId));
        return ret;
    }
    std::vector<Double>* tofBinInfo = _wirInfo->TofBinInfoList[outerPixelId];

    UInt4 tof_pat_id = (UInt4)(tofBinInfo->at(0));
    if (_wirInfo->TofBinPtnInfo[ tof_pat_id ]==NULL){
        UtsusemiError(_MessageTag+"PutHistBin > TofBinPtnVec[ tof_pat_id ]=NULL : pat_id="+_st->UInt4ToString(tof_pat_id));
        return ret;
    }

    Int4 tofBinType = _wirInfo->TofBinPtnInfo[ tof_pat_id ]->type;
    std::vector<Double>* pattern = _wirInfo->TofBinPtnInfo[ tof_pat_id ]->PatternVect;

    return _wirDict->PutTofBin( outerPixelId, tofBinType, pattern );

}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::pair<std::string,std::string> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutXLabel( Int4 convtype ){
    if (_wirDict!=NULL)
        return _wirDict->PutXLabel( convtype );
    else{
        UtsusemiError(_MessageTag+"PutXLabel > have not executed SetParametersFromFiles() yet.");
        std::pair<std::string,std::string> tmp;
        tmp.first="None";
        tmp.second="None";
        return tmp;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::pair<std::string,std::string> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutYLabel( Int4 convtype ){
    if (_wirDict!=NULL)
        return _wirDict->PutYLabel( convtype );
    else{
        UtsusemiError(_MessageTag+"PutYLabel > have not executed SetParametersFromFiles() yet.");
        std::pair<std::string,std::string> tmp;
        tmp.first="None";
        tmp.second="None";
        return tmp;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::pair<std::string,std::string> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutELabel( Int4 convtype ){
    if (_wirDict!=NULL)
        return _wirDict->PutELabel( convtype );
    else{
        UtsusemiError(_MessageTag+"PutELabel > have not executed SetParametersFromFiles() yet.");
        std::pair<std::string,std::string> tmp;
        tmp.first="None";
        tmp.second="None";
        return tmp;
    }
}

//////////////////////////////////////////////////////////
template <typename T1, typename T2>
bool UtsusemiReadoutEventDecoderTemplate<T1,T2>::
SetTofOriginShift( UInt4 cType ){
    if (_wirDict!=NULL)
        return _wirDict->SetTofShift( cType );
    else{
        UtsusemiError(_MessageTag+"SetTofOriginShift > have not executed SetParametersFromFiles() yet.");
        return false;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
bool UtsusemiReadoutEventDecoderTemplate<T1,T2>::
SetTofOriginShift( UInt4 cType, std::vector<Double> params ){
    if (_wirDict!=NULL)
        return _wirDict->SetTofShift( cType, params );
    else{
        UtsusemiError(_MessageTag+"PutTofOriginShift > have not executed SetParametersFromFiles() yet.");
        return false;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<Double> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutLambda( UInt4 pixel_id ){
    if (_wirDict!=NULL)
        return _wirDict->PutLambda( pixel_id );
    else{
        UtsusemiError(_MessageTag+"PutLambda > have not executed SetParametersFromFiles() yet.");
        std::vector<Double> ret;
        return ret;
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
void UtsusemiReadoutEventDecoderTemplate<T1,T2>::
SetMaskOnError( UInt4 _outerPixelId, std::vector<Double> &_bin, std::vector<Double> &_err ){
    if (_wirInfo->TofMaskPtnInfo.empty()){
    }else{
        if ((_wirInfo->TofBinInfoList.size()<=_outerPixelId)||(_wirInfo->TofBinInfoList[_outerPixelId]==NULL)) {
            UtsusemiError(_MessageTag+"SetMaskOnError > TofBinInfoList[pixelId]=NULL : pixel_id="+_st->UInt4ToString(_outerPixelId));
            return;
        }
        std::vector<Double>* tofBinInfo = _wirInfo->TofBinInfoList[_outerPixelId];
        if (tofBinInfo->size()>=3){
            Int4 tof_mask_ptnId = (Int4)(tofBinInfo->at(2));
            if (tof_mask_ptnId<0){
            }else if (_wirInfo->TofMaskPtnInfo[(UInt4)(tof_mask_ptnId)]!=NULL){
                UtsusemiTofMaskPattern *tmp = _wirInfo->TofMaskPtnInfo[(UInt4)(tof_mask_ptnId)];
                if (tmp!=NULL){
                    for (UInt4 i=0; i<(_err.size()); i++){
                        Double bin1 = _bin[i];
                        Double bin2 = _bin[i+1];
                        bool isMask = false;
                        for (UInt4 j=0; j<(tmp->PatternVect.size()); j++){
                            if ( ( ( bin1>=(tmp->PatternVect[j].first) )&&( bin2<=(tmp->PatternVect[j].second) ) )
                                 ||( ( bin1<=(tmp->PatternVect[j].first) )&&( (tmp->PatternVect[j].first)<=bin2 ) )
                                 ||( ( bin1<=(tmp->PatternVect[j].second) )&&( (tmp->PatternVect[j].second)<=bin2 ) ) ){
                                isMask = true;
                                break;
                            }
                        }
                        if (isMask) {
                            if (_err[i]==0.0) _err[i] = 1e-30;
                            _err[i] = -1.0*_err[i];
                        }
                    }
                }
            }
        }
    }
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
UInt4 UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutNumOfPixelForDet(UInt4 _detId){
    return _wirInfo->PutNumOfPixelForDet(_detId);
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
Double UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutL1(){
    return _detInfo->PutInstL1();
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
Double UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutTypicalL2(){
    return _detInfo->PutInstTypicalL2();
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
Double UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutTypicalDS(){
    return _detInfo->PutInstTypicalDS();
}
//////////////////////////////////////////////////////////
template <typename T1, typename T2>
std::vector<Double> UtsusemiReadoutEventDecoderTemplate<T1,T2>::
PutTypicalPixelSize(UInt4 _detId){
    std::vector<Double> ret;
    std::vector<Double> pv = _detInfo->PutPositionInfoParams(_detId);
    if ((pv.empty())&&(_detId==0)){
        for (UInt4 i=0; i<_detInfo->PosiInfo->position_list.size(); i++){
            pv = _detInfo->PutPositionInfoParams(i);
            if (!(pv.empty())) break;
        }
    }
    if (pv.empty()) return ret;

    UInt4 numOfPixel = PutNumOfPixelForDet();
    ret.clear();
    ret.resize(3,0.0);
    ret[0] = sqrt( pv[3]*pv[3] + pv[4]*pv[4] + pv[5]*pv[5] )/(Double)numOfPixel;
    ret[1] = pv[7];
    ret[2] = pv[7];
    return ret;
}

#endif
