#include "TofToEnergyChoppers.hh"
//////////////////////////////////////////////////////////
TofToEnergyChoppers::
TofToEnergyChoppers()
{
}

//////////////////////////////////////////////////////////
TofToEnergyChoppers::
~TofToEnergyChoppers()
{
}

//////////////////////////////////////////////////////////
void TofToEnergyChoppers::
TofToEnergyBase( double L1, double Tof_offset, std::vector<double> new_bin )
{
    ElementContainerMatrix *ecm = Put();
    std::vector<double> tof,posivect,int_org,err_org,int_new,err_new,tof_new;
    std::string xkey,ykey,ekey;
    Double L2p;
    UInt4 num_of_eca, num_of_ec;

    HeaderBase *h;
    /* check the existence of key Ei in header  */
    h = ecm->PutHeaderPointer();

    Double mn = 1.6749e-27;
    Double J2meV = 6.24151e21;
    std::vector<Double> et;

    /* need or not for TOF Rebinning    */
    UInt4 rebin_flag = 0;
    if (new_bin.size()!=0){
        rebin_flag = 1;
    }

    num_of_eca = ecm->PutTableSize();
    //std::cout << "TofToEnergyChoppers >> PSD = ";
    for (UInt4 psd=0;psd<num_of_eca;psd++){
        ElementContainerArray *eca = ecm->PutPointer(psd);
        //std::cout << psd << ",";
        std::string type_s = eca->PutHeaderPointer()->PutString(UTSUSEMI_KEY_HEAD_DETTYPE);
        std::string::size_type index = type_s.find( UTSUSEMI_KEY_HEAD_DETTYPE_MONITOR );
        if (index ==std::string::npos){
            num_of_ec = eca->PutTableSize();
            for (UInt4 pixel=0;pixel<num_of_ec;pixel++){
                ElementContainer *ec = eca->PutPointer(pixel);
                et.clear();
                tof.clear();
                posivect.clear();
                int_org.clear();
                err_org.clear();
                int_new.clear();
                err_new.clear();
                tof_new.clear();

                xkey = ec->PutXKey();
                ykey = ec->PutYKey();
                ekey = ec->PutEKey();

                tof = ec->PutX();
                int_org = ec->PutY();
                err_org = ec->PutE();
                tof_new.push_back(tof[tof.size()-1]);
                for (UInt4 i=0;i<int_org.size();i++){
                    tof_new.push_back( tof[int_org.size()-i] );
                    int_new.push_back( int_org[int_org.size()-i] );
                    err_new.push_back( err_org[int_org.size()-i] );
                }

                posivect = ec->PutHeaderPointer()->PutDoubleVector(UTSUSEMI_KEY_HEAD_PIXELPOSITION);
                L2p = sqrt( posivect[0]*posivect[0]+posivect[1]*posivect[1]+posivect[2]*posivect[2] );
                for (UInt4 i=0;i<(tof.size());i++){
                    et.push_back(0.5*mn*( pow( ((L1+L2p)/1000.0),2.0 )/pow( ((tof_new[i]-Tof_offset)*(1.0e-6)),2.0))*J2meV);
                }

                ec->Add(UTSUSEMI_KEY_ENERGY,et,UTSUSEMI_KEY_ENERGY_UNIT);
                ec->Replace(ykey,int_new);
                ec->Replace(ekey,err_new);
                ec->SetKeys(UTSUSEMI_KEY_ENERGY,ykey,ekey);
                ec->Remove(xkey);
                if (rebin_flag==1){
                    //(2009.12.18) Rebin -> Bining
                    //ElementContainer new_ec = ec->ReBin(new_bin);
                    ElementContainer new_ec = ec->Binning(new_bin);
                    ec->Replace(UTSUSEMI_KEY_ENERGY,new_ec.PutX());
                    ec->Replace(ykey,new_ec.PutY());
                    ec->Replace(ekey,new_ec.PutE());
                    ec->SetKeys(UTSUSEMI_KEY_ENERGY,ykey,ekey);
                }
            }
        }
    }
    //std::cout << std::endl;
    std::vector<std::string> st_vect = h->PutStringVector(UTSUSEMI_KEY_HEAD_DATAPROCESSED);
    st_vect.push_back("TOF TO ENERGY CONVERSION");
    h->OverWrite(UTSUSEMI_KEY_HEAD_DATAPROCESSED,st_vect);

}

//////////////////////////////////////////////////////////
void TofToEnergyChoppers::
TofToEnergy( double Tof_offset)
{
    ElementContainerMatrix *ecm = Put();
    double L1;
    if ( (ecm->PutHeaderPointer()->CheckKey(UTSUSEMI_KEY_HEAD_L1))==0 ){
        UtsusemiError("TofToEnergyChoppersTransfer >> L1 is not set in ElementContainerMatrix.");
        return;
    }
    L1 = ecm->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_L1);

    std::vector<Double> no_bin;
    no_bin.clear();

    TofToEnergyBase( L1, Tof_offset, no_bin );
}

//////////////////////////////////////////////////////////
void TofToEnergyChoppers::
TofToEnergy( double Tof_offset, std::vector<Double> new_bin )
{
    ElementContainerMatrix *ecm = Put();
    double L1;
    if ( (ecm->PutHeaderPointer()->CheckKey(UTSUSEMI_KEY_HEAD_L1))==0 ){
        UtsusemiError("TofToEnergyChoppersTransfer >> L1 is not set in ElementContainerMatrix.");
        return;
    }
    L1 = ecm->PutHeaderPointer()->PutDouble(UTSUSEMI_KEY_HEAD_L1);

    TofToEnergyBase( L1, Tof_offset, new_bin );
}

//////////////////////////////////////////////////////////
void TofToEnergyChoppers::
TofToEnergy( double L1, double Tof_offset)
{
    std::vector<Double> no_bin;
    no_bin.clear();
    TofToEnergyBase( L1, Tof_offset, no_bin );
}

//////////////////////////////////////////////////////////
void TofToEnergyChoppers::
TofToEnergy( double L1, double Tof_offset, std::vector<Double> new_bin )
{
    TofToEnergyBase( L1, Tof_offset, new_bin );
}
