#include "AdvQECalculation.hh"
// AS 120229 start

//////////////////////////////////////////////////////////
AdvQECalculation::
AdvQECalculation()
{
    Initialize();
}
//////////////////////////////////////////////////////////
AdvQECalculation::
AdvQECalculation(ElementContainerMatrix *ecm)
{
    Initialize();
    SetTarget(ecm);
}
//////////////////////////////////////////////////////////
AdvQECalculation::
~AdvQECalculation()
{
}
//////////////////////////////////////////////////////////
void AdvQECalculation::
Initialize(){
    commentHead = "AdvQECalculation >> ";
    stools = new StringTools();
}
//////////////////////////////////////////////////////////

ElementContainerArray AdvQECalculation::
CalcQE(double startQ, double endQ, double deltaQ){
    ElementContainerArray ECA;
    CalcQE(&ECA, startQ, endQ, deltaQ);
    return ECA;
}
void AdvQECalculation::
CalcQE(ElementContainerArray* ECA, double startQ, double endQ, double deltaQ){
//////////////////////////////////////////////////
//initialize

    ElementContainerMatrix *ecm = Put();
    ElementContainerArray *eca;
    ElementContainer *ec;

    std::vector<double> HistValX = ecm->PutPointer(0)->PutPointer(0)->PutX();
    std::vector<double> HistValY,HistValE;

    std::vector< std::vector < double > > HWQY_CALIB;
    std::vector< std::vector < double > > HWQE_CALIB;
    std::vector< std::vector < double > > HWQY;
    std::vector< std::vector < double > > HWQE;
    std::vector< std::vector < double > > HWQN;

    UInt4 NumOfQbin   = (int)((endQ - startQ)/deltaQ);
    UInt4 NumOfHWBin = HistValX.size()-1;

        //ElementContainerArray ECA;
    ECA->AddToHeader( std::string("MASKED"), 0 );
    ECA->AddToHeader( std::string("TYPE"), std::string("PSD") );
    ECA->AddToHeader( std::string("PSDID"), Int4(0) );


    HWQY.resize(NumOfQbin);
    HWQE.resize(NumOfQbin);
    HWQN.resize(NumOfQbin);
    for (UInt4 i = 0; i < NumOfQbin; i++)
        {
        HWQY[i].resize(NumOfHWBin);
        HWQE[i].resize(NumOfHWBin);
        HWQN[i].resize(NumOfHWBin);
        fill(HWQY[i].begin(),HWQY[i].end(),0.0);
        fill(HWQE[i].begin(),HWQE[i].end(),0.0);
        fill(HWQN[i].begin(),HWQN[i].end(),0.0);
        }

    HWQY_CALIB.resize(NumOfQbin);
    HWQE_CALIB.resize(NumOfQbin);
    for (UInt4 i = 0; i < NumOfQbin; i++)
        {
        HWQY_CALIB[i].resize(NumOfHWBin);
        HWQE_CALIB[i].resize(NumOfHWBin);
        }

    std::cout <<std::endl;
    std::cout << "QE-Calc-start"<<std::endl;

    //////////////////////////////////////////////////
    // psd loop
    UInt4 NumOfPsd = ecm->PutTableSize();
    for (UInt4 psd=0;psd<NumOfPsd;psd++)
        {
        if(psd%22==0){std::cout << "  "<<psd/22*10<<" %"<<std::endl;}

        eca = ecm->PutPointer(psd);

        //////////////////////////////////////////////////////
        // pixel loop
        UInt4 NumOfPixel = eca->PutTableSize();
        for (UInt4 pixel=0; pixel<NumOfPixel; pixel++)
            {
            ec       = eca->PutPointer(pixel);
            HistValX = ec->PutX();
            HistValY = ec->PutY();
            HistValE = ec->PutE();

            int MaskedValue = 0;
            int mask = ec->PutHeaderPointer()->PutInt4("MASKED");
            if (mask==0)
                MaskedValue=1;
            else if (mask==1)
                MaskedValue=0;

            double ef         = ec->PutHeaderPointer()->PutDouble("Ef");
            double PolarAngle = ec->PutHeaderPointer()->PutDouble("PolarAngle");

            std::vector<double> Qvalue;
            // variable definition::HW = Ef-Ei
            //    for(UInt4 HWbin=0; HWbin<NumOfHWBin; HWbin++)
            //        {
            //        Qvalue.push_back ( sqrt(1/2.072 *( 2*ef - HistValX.at(HWbin) -2*sqrt( ef * ( ef - HistValX.at(HWbin) ) )* cosPA) ) );
            //        }
            // variable definition::HW = Ei-Ef
            double cosPA=cos(PolarAngle);
            for(UInt4 HWbin=0; HWbin<NumOfHWBin; HWbin++)
                {
                Qvalue.push_back ( sqrt(1/2.072 *( 2*ef + HistValX.at(HWbin) -2*sqrt( ef * ( ef + HistValX.at(HWbin) ) )* cosPA ) ) );
                }

            for(UInt4 HWbin=0; HWbin<NumOfHWBin; HWbin++)
                {
                for(UInt4 Qbin=0; Qbin<NumOfQbin; Qbin++)
                    {
                    if ( (deltaQ*Qbin+startQ <= Qvalue.at(HWbin)) && (Qvalue.at(HWbin) < deltaQ*(Qbin+1)+startQ) )
                        {
                        if(HistValE.at(HWbin)>=0.0) //T.Yamada Add[20150216]
                            {
                                /*
                                if((psd==20)&&(pixel==50)){
                                std::cout<< HistValY.at(HWbin) << ", " << HistValE.at(HWbin) <<","<<HWbin <<std::endl;
                                }
                                */
                                /*if((Qbin ==14)&&(HWbin==70)){
                                std::cout<< HistValY.at(HWbin) <<", "<< HistValE.at(HWbin)<<", " << MaskedValue << std::endl;
                                }*/
                            HWQY[Qbin][HWbin] += HistValY.at(HWbin)*MaskedValue;
                            HWQE[Qbin][HWbin] += HistValE.at(HWbin)*HistValE.at(HWbin)*MaskedValue;
                            HWQN[Qbin][HWbin] += MaskedValue;
                            /*if(Qbin==10 && HWbin==60){
                                std::cout << "HistValY" << HistValY.at(HWbin) <<", " << HistValE.at(HWbin) << ", " << MaskedValue << std::endl;
                                }*/
                            }//T.Yamada End[20150216]
                        }
                    else if (deltaQ*Qbin+startQ>Qvalue.at(HWbin))
                        break;
                    }
                }
            }
        }

    //////////////////////////////////////////////////////
    // Add to Element Container and sum up
    /*std::cout << "HWQY[10][60]" << HWQY[10][60] << std::endl;
    std::cout << "HWQE[10][60]" << HWQE[10][60] << std::endl;
    std::cout << "HWQN[10][60]" << HWQN[10][60] << std::endl;*/

    for(UInt4 Qbin=0; Qbin<NumOfQbin; Qbin++)
        {
        for(UInt4 HWbin=0; HWbin<NumOfHWBin; HWbin++)
            {
            if(int(HWQN[Qbin][HWbin])!=0)
                {
                HWQY_CALIB[Qbin][HWbin] =      HWQY[Qbin][HWbin] / HWQN[Qbin][HWbin];
                HWQE_CALIB[Qbin][HWbin] = sqrt(HWQE[Qbin][HWbin])/ HWQN[Qbin][HWbin];
                }
            else
                {
                //HWQY_CALIB[Qbin][HWbin] = 0;
                //HWQE_CALIB[Qbin][HWbin] = 0;
                HWQY_CALIB[Qbin][HWbin] = MLF_MASKVALUE;
                HWQE_CALIB[Qbin][HWbin] = -1.0;
                }
            }
        }

    for(UInt4 Qbin=0; Qbin<NumOfQbin; Qbin++)
        {
        ElementContainer EC;
        EC.AddToHeader(std::string("PSDID"), Int4(NumOfPsd-2) );
        EC.AddToHeader(std::string("MASKED"), 0 );
        EC.AddToHeader(std::string("PIXELID"), Int4((int)(Qbin *deltaQ + startQ)) );
        std::vector<double> xrange;
        xrange.push_back(Qbin *deltaQ + startQ);
        xrange.push_back((Qbin+1) *deltaQ + startQ);
        EC.AddToHeader(std::string("XRANGE"), xrange );

        double Total = 0;
        for (UInt4 l=0;l<(HWQY_CALIB.at(Qbin)).size();l++)
            {
            Total += (HWQY_CALIB.at(Qbin))[l];
            }

        EC.AddToHeader(std::string("TotalCounts"), Total );
        EC.AddToHeader(std::string("Label"), stools -> Int4ToString( (int)(Qbin *deltaQ + startQ) ));
        EC.Add("Energy", HistValX);
        EC.Add("Intensity", HWQY_CALIB.at(Qbin));
        EC.Add("Error", HWQE_CALIB.at(Qbin));
        EC.Add("N",HWQN.at(Qbin));
        EC.SetKeys( "Energy", "Intensity", "Error" );
        ECA->Add( EC );
        }

    HeaderBase hh = ecm->PutHeader();
    ECA->InputHeader(hh);
    std::string runnum = ecm->PutHeaderPointer()->PutString("RUNNUMBER");
    std::cout <<"runnum = " <<runnum <<std::endl;

    std::cout << "QE-Calc-end"<<std::endl;
    //return ECA;

    }// function CalcQE(){ end
//////////////////////////////////////////////////////////
