
extern "C" {

    //Struct per il passaggio di dati da e verso la chiamata fortran
    extern struct {
        int   iev;
        int   cstwerr[4];
        float cperror[4];
        float calped[4][11][96];
        float calgood[4][11][96];
        float calthr[4][11][6];
        float calrms[4][11][96];
        float calbase[4][11][6];
        float calvar[4][11][6];
        //float calpuls[4][11][96];
    } calib_; 
    //external declaration of the Fortran function 
    void calpedestal_(char*, long int*, int*);
}

#include "ReaderAlgorithms.h"
using namespace pamela::techmodel;


/**
 * Constructor. 
 */
CalibCalPedReader::CalibCalPedReader(void): 
  TechmodelAlgorithm(PacketType::Log, "TechmodelCalibCalPedReader") { 
  calibCalPed = new CalibCalPedEvent();
}



/**
 * Initialize the algorithm with a special run. This will initialize the
 * event reader routines for all packet types.
 */
void CalibCalPedReader::Init(PamelaRun *run) {
  run->WriteSubPacket(this, &calibCalPed, calibCalPed->Class());
}

/**
 * Unpack the CalibCalPed event from an input file.
 */
void CalibCalPedReader::PKT_RunEvent(char* packetData, long int dataLength) throw (CalibException){
    stringstream oss;
	string msg;
    int         ERROR;  
    calpedestal_((char*)packetData, &dataLength, &ERROR);
    calibCalPed->unpackError = ERROR;
    if (ERROR != 0) {
        char *errmsg;
        switch (ERROR){
            case 1: errmsg = "CALORIMETER NOT FOUND";
        }
        oss.str("");
        oss << "CalibCalPed: Fortran77 function calpedestal error code = " << ERROR
            <<  " " << errmsg;
    	msg=oss.str();
    	PamOffLineSW::mainLogUtil->logWarning(msg);	
     } //else {
      //Store the unpacked data
        calibCalPed->iev = calib_.iev;
        memcpy(calibCalPed->cstwerr, calib_.cstwerr, sizeof(calibCalPed->cstwerr));
        memcpy(calibCalPed->cperror, calib_.cperror, sizeof(calibCalPed->cperror));
    //--------have to invert array because of FORTRAN <-> C different management of the indexes
        float tempCalped[96][11][4];
        float tempCalgood[96][11][4];
        float tempCalthr[6][11][4];
        float tempCalrms[96][11][4];
        float tempCalbase[6][11][4];
        float tempCalvar[6][11][4];
        //float tempCalpuls[96][11][4];

        memcpy(tempCalped,  calib_.calped,  sizeof(tempCalped));
        memcpy(tempCalgood, calib_.calgood, sizeof(tempCalgood));
        memcpy(tempCalthr,  calib_.calthr,  sizeof(tempCalthr));
        memcpy(tempCalrms,  calib_.calrms,  sizeof(tempCalrms));
        memcpy(tempCalbase, calib_.calbase, sizeof(tempCalbase));
        memcpy(tempCalvar,  calib_.calvar,  sizeof(tempCalvar));
        //memcpy(tempCalpuls, calib_.calpuls, sizeof(tempCalpuls));

        for (int i = 0; i < 4; i++){
            for (int j = 0; j <11; j++){
                for (int z = 0; z < 96; z++){
                    calibCalPed->calped[i][j][z]    = tempCalped[z][j][i];
                    calibCalPed->calgood[i][j][z]   = tempCalgood[z][j][i];
                    calibCalPed->calrms[i][j][z]    = tempCalrms[z][j][i];
                    //calibCalPed->calpuls[i][j][z]   = tempCalpuls[z][j][i];
                }
            }
        }

        for (int i = 0; i < 4; i++){
            for (int j = 0; j <11; j++){
                for (int z = 0; z < 6; z++){
                    calibCalPed->calthr[i][j][z]    = tempCalthr[z][j][i];
                    calibCalPed->calbase[i][j][z]   = tempCalbase[z][j][i];
                    calibCalPed->calvar[i][j][z]    = tempCalvar[z][j][i];
                }
            }
        }
    //-----------------------------------------------------------------------------------------
    //}
        
        //TODO: check here ....
        if((calibCalPed->cperror[0])||(calibCalPed->cperror[1])||(calibCalPed->cperror[2])||(calibCalPed->cperror[3]))
        {
        	oss.str("");
        	oss <<  "CalibCalPed Problem: cperror[0] = " <<calibCalPed->cperror[0]<<" cperror[1] = " <<calibCalPed->cperror[1]<<" cperror[2] = " <<calibCalPed->cperror[2]<<" cperror[3] = " <<calibCalPed->cperror[3];
        	msg=oss.str();
        	PamOffLineSW::mainLogUtil->logError(msg);
        	throw CalibException("Wrong Global CRC for CalibCalPed Packet ");
        }

}

/**
 * Get a string with the version info of the algorithm.
 */
std::string CalibCalPedReader::GetVersionInfo(void) const {
  return 
    "$Header: /repository/PamOffLineSW/techmodel/CalibCalPedReader.cpp,v 1.7 2008-03-21 16:18:46 messineo Exp $\n";
}
