#include "UtsusemiReadoutWLSF32EventDecoder.hh"
//////////////////////////////////////////////////////////
UtsusemiReadoutWLSF32EventDecoder::
UtsusemiReadoutWLSF32EventDecoder():
UtsusemiReadoutEventDecoderTemplate<WiringInfoEditorReadout,DetectorInfoEditorReadout2d>()
{
    Initialize();
}
//////////////////////////////////////////////////////////
UtsusemiReadoutWLSF32EventDecoder::
~UtsusemiReadoutWLSF32EventDecoder(){
    Clear();
}
//////////////////////////////////////////////////////////
void UtsusemiReadoutWLSF32EventDecoder::
Initialize(){
    //UtsusemiReadoutEventDecoderTemplate<WiringInfoEditorReadout,UtsusemiDetectorInfoReaderReadout2d>::Initialize();

    _EventSize = (UInt4)4;

    _AnaModeReadout32 = -1;

    _MessageTag="UtsusemiReadoutWLSF32EventDecoder >> ";

}

//////////////////////////////////////////////////////////
UInt4 UtsusemiReadoutWLSF32EventDecoder::
DecodeEventData( UInt4 daqId, UInt4 modNo, const UChar *data, UInt4 *pixel_id, double *tof, std::vector<Double>* Clock, UInt4 ThNum ){

    UInt4 ret = 0;

    // if given event is neutron event;
    UInt4 header = (*(data+0))&0x3;
    if ((header==2)||(header==3)){
        for (UInt4 i=0;i<_EventSize;i++) (*(_prevT0Event+(_EventSize*ThNum)+i))=(*(data+i));
        ret = _isT0Event;
    }else if (header==0){
        // Analysis decode
        if (_AnaModeReadout32>=0){
            UInt4 ana = (UInt4)( ((*(data+0))&0xc)>>2 );
            if (ana!=abs(_AnaModeReadout32)) return ret;
        }

        // TOF decode
        UInt4 tof_up = (UInt4)((*(_prevT0Event+(_EventSize*ThNum)+3))&0xf0)<<8;
        *tof = tof_up + (UInt4)(*(data+1)<<4) + (UInt4)((*(data+0)&0xf0)>>4);
        // frame treatment : minus clock means this frame must be ignored.
        /*
        if ( (_wirInfo->FrameBoundaryInfo.first)>1 ){
            if ( *tof < (_wirInfo->FrameBoundaryInfo.second) ){
                if (Clock->at( _wirInfo->FrameBoundaryInfo.first -1 )<0) return ret;
                *tof += Clock->at( _wirInfo->FrameBoundaryInfo.first -1 );
            }else{
                if (Clock->at( _wirInfo->FrameBoundaryInfo.first -2 )<0) return ret;
                *tof += Clock->at( _wirInfo->FrameBoundaryInfo.first -2 );
            }
        }
        */

        // position decode
        UInt4 xpos = (UInt4)(*(data+2));
        UInt4 ypos = (UInt4)(*(data+3));

        // Pixel ID
        std::vector< std::vector<Int4>* > *pixel_info = NULL;
        try{
            pixel_info = _wirInfo->PixelInfoStore->at(daqId)->at(modNo);
        }catch(...){
            return ret;
        }
        if (pixel_info!=NULL){
            for (UInt4 i=0; i<(pixel_info->size()); i++){

                UInt4 xpos_start = pixel_info->at(i)->at(4);
                UInt4 x_size = pixel_info->at(i)->at(5);
                UInt4 ypos_start = pixel_info->at(i)->at(6);
                UInt4 y_size = pixel_info->at(i)->at(7);

                if ( (xpos>=xpos_start) && (xpos<(xpos_start+x_size))
                     && (ypos>=ypos_start) && (ypos<(ypos_start+y_size)) ){
                    UInt4 head_pixelId = pixel_info->at(i)->at(2);
                    *pixel_id = head_pixelId + (xpos-xpos_start)*y_size + (ypos-ypos_start);
                    ret = _isNeutronEvent;

                    if(_wirInfo->TofBinInfoList[(*pixel_id)]!=NULL)
                        *tof += _wirInfo->TofBinInfoList[(*pixel_id)]->at(1);
                    if (_isSetFrameBoundary){
                        UInt4 fno = _wirDict->FrameBoundaryInfoList[(*pixel_id)]->first;
                        Double boundary = _wirDict->FrameBoundaryInfoList[(*pixel_id)]->second;
                        if ( *tof < boundary){
                            if (Clock->at( fno -1 )<0) return ret;
                            *tof += Clock->at( fno -1 );
                        }else if ( *tof < (boundary+_MicroSec_Par_Frame) ){
                            if (Clock->at( fno -2 )<0) return ret;
                            *tof += Clock->at( fno -2 );
                        }
                    }
                    break;
                }
            }
        }
    }else{
        std::cout << _MessageTag+"DecodeEventData >>> VETO signal " << std::endl;
    }

    return ret;

}
//////////////////////////////////////////////////////////
void UtsusemiReadoutWLSF32EventDecoder::
CalcPixelPosition(){
    Clear();
    if (_wirInfo->PixelInfoStore->empty()) {
        UtsusemiError(_MessageTag+" not ready wiring info.");
        return;
    }

    for (UInt4 daq=0; daq<_wirInfo->PixelInfoStore->size();daq++){

        if (_wirInfo->PixelInfoStore->at(daq)==NULL) continue;

        for (UInt4 mod=0; mod<_wirInfo->PixelInfoStore->at(daq)->size(); mod++){

            if (_wirInfo->PixelInfoStore->at(daq)->at(mod)==NULL) continue;

            for (UInt4 det=0; det<_wirInfo->PixelInfoStore->at(daq)->at(mod)->size(); det++){
                if (_wirInfo->PixelInfoStore->at(daq)->at(mod)->at(det)!=NULL){
                    std::vector<Int4>* pic = _wirInfo->PixelInfoStore->at(daq)->at(mod)->at(det);
                    UInt4 det_id = pic->at(1);
                    UInt4 head_px = pic->at(2);
                    UInt4 xpos_st = pic->at(4);
                    UInt4 xpos_size = pic->at(5);
                    UInt4 ypos_st = pic->at(6);
                    UInt4 ypos_size = pic->at(7);

                    if (_pixelPositionVect.size()<(head_px + (xpos_size*ypos_size) ) ){
                        _pixelPositionVect.resize( (head_px + (xpos_size*ypos_size) ), NULL );
                        _pixelSolidAngleVect.resize( (head_px + (xpos_size*ypos_size) ), 0.0 );
                    }

                    std::vector< std::vector<Double>* > pos_vec;
                    pos_vec.resize( (xpos_size*ypos_size), NULL );
                    for (UInt4 i=0; i<(xpos_size*ypos_size); i++)
                        pos_vec[i] = new std::vector<Double> (3,0.0);

                    if ( _detInfo->CalcReadout2dPixelPosition( det_id, xpos_size, ypos_size, &pos_vec ) ){
                        std::vector<Double> tmp_solid_angles = _detInfo->CalcReadout2dPixelSolidAngle( det_id, xpos_size, ypos_size, &pos_vec );
                        for (UInt4 i=0; i<(xpos_size*ypos_size); i++){
                            _pixelPositionVect[head_px+i] = pos_vec[i];
                            _pixelSolidAngleVect[head_px+i] = tmp_solid_angles[i];
                        }
                    }else{
                        for (UInt4 i=0; i<(xpos_size*ypos_size); i++)
                            delete pos_vec[i];
                    }
                }
            }
        }
    }

}

//////////////////////////////////////////////////////////
bool UtsusemiReadoutWLSF32EventDecoder::
SetAnaModeReadout32( Int4 anamode ){
    if (anamode<0) _AnaModeReadout32=-1;
    else if (anamode<4) _AnaModeReadout32=anamode;
    else return false;
    return true;
}
