/** @file
 * $Source: /home/cvsmanager/yoda/techmodel/physics/CalorimeterReader.cpp,v $
 * $Id: CalorimeterReader.cpp,v 3.1 2005/03/06 04:29:24 kusanagi Exp $
 * $Author: kusanagi $
 * 
 * Implementation of the CalorimeterReader class.
 */


#include <iostream>
#include <string>
#include <log4cxx/logger.h>
#include "CalorimeterReader.h"

extern "C" {
  

 extern struct {
        int     iev;
        int     stwerr[4];
        float   perror[4];
        float   dexy[2][22][96];
        float   dexyc[2][22][96];
        float   base[2][22][6];
        float   calselftrig[4][7];
        float   calIItrig[4];
        float   calstriphit[4];
        float   calDSPtaberr[4];
        float   calevnum[4];
    } evento_; 

    void calunpack_(unsigned char[], long int*, int*);
    //Struct per il passaggio di dati da e verso la chiamata fortran
}

using namespace pamela;
using namespace pamela::calorimeter;

static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("pamela.techmodel.calorimeter.CalorimeterReader"));

/**
 * Constructor.     
 */
CalorimeterReader::CalorimeterReader(void): 
  TechmodelAlgorithm(PacketType::Physics, "TechmodelCalorimeterReader") { 
  logger->debug(_T("Construnctor"));
  calorimeter = new CalorimeterEvent();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string CalorimeterReader::GetVersionInfo(void) const {
  return 
    "$Header: /home/cvsmanager/yoda/techmodel/physics/CalorimeterReader.cpp,v 3.1 2005/03/06 04:29:24 kusanagi Exp $";
}

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

/**
 * Unpack the calorimeter event from an input file.
 */
void CalorimeterReader::RunEvent(int EventNumber) {
  
}

/**
 * Unpack the Calorimeter data event from the physical packet.
 */
void CalorimeterReader::RunEvent(int EventNumber, const char subData[], long int length) {
    std::stringstream oss;       
    char *data = new char[length];
    memcpy(data, subData, length);
    int  ERROR = 0;
    
    /*unsigned short convdata[length];
    for (int i = 0; i<length; i++){
        convdata[i] = (unsigned short)((unsigned char)subData[i]&0xFF);
    }*/
    
    //Call to the routine that unpack calorimeter events
    calunpack_((unsigned char*)data, &length, &ERROR);

    calorimeter->unpackError = ERROR;
    if (ERROR != 0) {
        char *errmsg;
        switch (ERROR){
            case 1: errmsg = "CALORIMETER NOT FOUND";
            break;
            default: errmsg = "CALORIMETER ERRROR CODE UNIDENTIFIED";
        }
        oss.str("");
        oss << "Fortran77 function calunpack: " <<  errmsg;
        logger->warn(oss.str().c_str());
    }
    //  In case of "ERROR != 0" the calunpack will take care to set all 
    //  parameters to zero
    //} else {
        calorimeter->iev   = evento_.iev;
        memcpy(calorimeter->stwerr, evento_.stwerr, sizeof(calorimeter->stwerr));
        memcpy(calorimeter->perror, evento_.perror, sizeof(calorimeter->perror));
    //--------have to invert array because of FORTRAN <-> C different management of the indexes
        float tempDexy[96][22][2];
        float tempDexyc[96][22][2];
        float tempBase[6][22][2];
        float tempCalselftrig[7][4];
        memcpy(tempDexy,           evento_.dexy,           sizeof(tempDexy));
        memcpy(tempDexyc,          evento_.dexyc,          sizeof(tempDexyc));
        memcpy(tempBase,           evento_.base,           sizeof(tempBase));
        memcpy(tempCalselftrig,    evento_.calselftrig,    sizeof(tempCalselftrig));

        for (int i = 0; i < 4; i++){
            for (int j = 0; j < 7; j++){
                calorimeter->calselftrig[i][j] = tempCalselftrig[j][i];
            }
        }

        for (int i = 0; i < 2; i++){
            for (int j = 0; j < 22; j++){
                for (int z = 0; z < 96; z++){
                    calorimeter->dexy[i][j][z] = tempDexy[z][j][i];
                    calorimeter->dexyc[i][j][z] = tempDexyc[z][j][i];
                }
                for (int z = 0; z < 6; z++){
                    calorimeter->base[i][j][z] = tempBase[z][j][i];
                }
            }
        }
    //-----------------------------------------------------------------------------------------
        memcpy(calorimeter->calIItrig,      evento_.calIItrig,      sizeof(calorimeter->calIItrig));
        memcpy(calorimeter->calstriphit,    evento_.calstriphit,    sizeof(calorimeter->calstriphit));
        memcpy(calorimeter->calDSPtaberr,   evento_.calDSPtaberr,   sizeof(calorimeter->calDSPtaberr));
        memcpy(calorimeter->calevnum,       evento_.calevnum,       sizeof(calorimeter->calevnum));
    //}
    delete [] data;
}
