#ifndef CORRECTIONABSORPTION
#define CORRECTIONABSORPTION

#include <iostream>
#include <vector>

#include "Header.hh"
#include "CppToPython.hh"
//#include "AdvScatAbsoBodyManagerDNA.hh"
#include "AdvScatAbsoBodyManagerMLF.hh"
#include "AdvEquipmentManagerDNA.hh"


//#include "../system/ElementContainer.hh"
//#include "../system/ElementContainerArray.hh"
//#include "../system/ElementContainerMatrix.hh"
//#include "../system/HeaderBase.hh"

/**
 * AdvCorrectionAbsorptionDNA Class calculates absorption factor and desired value of the scattering
 * from the sample corrected for absorption, based on the following paper.
 *  H.H. Paalman and C.J. Pings :: J. Appl. Phys. 33, 2635 (1962).
 *
 * @@author skoike@@advancesoft
 * @@vertion 1.0
*/
//class AdvCorrectionAbsorptionDNA : public AdvScatAbsoBodyManagerDNA {
class AdvCorrectionAbsorptionDNA : public AdvScatAbsoBodyManagerMLF {
  private:

    UInt4 m;             /**< m-th order Legendre polynomial */
    UInt4 m_2;
    std::vector <Double>  xk; /**< k-th zero point of Pm(x) */
    std::vector <Double>  Hk; /**< weighted factor in Gauss-Legendre fomula */

    UInt4 maxCylinderNum; /**< max number of cylinders treated */

    UInt4 diffLevelCell;
    UInt4 diffLevelSample;
    UInt4 diffLevel;

    std::string filename;                /**< filename of data for cell and sample */
    std::string filepath;                /**< filename of data for cell and sample */

    struct ScatAbsoInfo sampleInfo; /**< data for sample */
    struct ScatAbsoInfo wallInfo;   /**< data for cell */
    struct coordinate scaPos;       /** neutron scattering position */

    Double sigmaCEi; /** total cross section of cell for incident neutron */
    Double sigmaCEo; /** total cross section of cell for reflected neutron */
    Double sigmaSEi; /** total cross section of sample for incident neutron */
    Double sigmaSEo; /** total cross section of sample for reflected neutron */

    Double theta; /** reflected angle */
    Double phi; /** reflected angle */

    Double sinTheta;  //20150123 ++
    Double cosTheta;  //20150123 ++
    Double sinPhi;    //20150123 ++
    Double cosPhi;    //20150123 ++

    Double sinTheta2; //20150123 ++
    Double cosTheta2; //20150123 ++
    Double sinPhi2;   //20150123 ++
    Double cosPhi2;   //20150123 ++

    Double incEnergy; /** incident neutron energy */
    Double outEnergy; /** reflected neutron energy */

    Double incLamdba0;
    Double sigmaAbsorpCEi0;
    Double sigmaAbsorpSEi0;

    Double radiusSmall; /** smaller radius of cylinder */
    Double radiusLarge; /** larger radius of cylinder */
    Double volume; /** volume of cylinder */
    UInt4 species; /** species of each absorption factor */

    /**
     * return length of neutron flight between invasion point and scattering point.
     *
     * @@return value of "S1C" or "S1S".
     */
    Double GetS1(Double, Double, Double);


    /**
     * return length of neutron flight between scattering point and exit point.
     *
     * @@return value of "S2C" or "S2S".
     */
    Double GetS2(Double, Double, Double);

//    Double epsilon; /** threshold value used for judgement of convergence of numerical integral */
//    Double epsilonRatio; /** threshold value used for judgement of convergence of numerical integral */
//    Double threZero; /** supplementary threshold value used for judgement of convergence of numerical integral */

    /**
     * return 3D integrated value
     *
     * @@return value of 3D numerical integral
     */
    Double CalcInteg(void);

    /**
     * return 2D integrated value
     *
     * @@return value of 2D numerical integral
     */
    Double IntegRTheta(Double);

    /**
     * return 1D integrated value
     *
     * @@return value of 1D numerical integral
     */
    Double IntegTheta(UInt4, Double, Double);

    /**
     * return value of function tobe integrated in the calculation of ACC.
     *
     * @@return value of  function tobe integrated in the calculation of ACC.
     */
    Double ReturnIntegFunctionValueA_C_C(void);

    /**
     * return value of function tobe integrated in the calculation of ACSC.
     *
     * @@return value of  function tobe integrated in the calculation of ACSC.
     */
    Double ReturnIntegFunctionValueA_CS_C(void); /** value of function to be integrated */

    /**
     * return value of function tobe integrated in the calculation of ACSS.
     *
     * @@return value of  function tobe integrated in the calculation of ACSS.
     */
    Double ReturnIntegFunctionValueA_CS_S(void); /** value of */

    /**
     * return value of function tobe integrated in the calculation of ASS.
     *
     * @@return value of  function tobe integrated in the calculation of ASS.
     */
    Double ReturnIntegFunctionValueA_S_S(void); /** value of */


    /**
     * main function of calculation of coefficient factor
     *
     * @@return value of coefficient factor
     */
    Double GetAMain(void);

    /**
     * calculate coefficient factor A_C_C1.
     * A_C_C1 is coefficent factor of sell scattered at outer cylinder.
     *
     * @@return A_C_C1
     */
    Double GetA_C_C1(void);

    /**
     * calculate coefficient factor A_C_C2
     * A_C_C2 is coefficent factor of sell scattered at inner cylinder.
     *
     * @@return A_C_C2
     */
    Double GetA_C_C2(void);

    /**
     * calculate coefficient factor A_CS_C1
     * A_CS_C1 is coefficent factor of sell+sample scattered at outer cell.
     *
     * @@return A_CS_C1
     */
    Double GetA_CS_C1(void);

    /**
     * calculate coefficient factor A_CS_C2
     * A_CS_C2 is coefficent factor of sell+sample scattered at inner cell.
     *
     * @@return A_CS_C2
     */
    Double GetA_CS_C2(void);

    /**
     * calculate coefficient factor A_CS_S
     * A_CS_S is coefficent factor of sell+sample scattered at sample.
     *
     * @@return A_CS_S
     */
    Double GetA_CS_S(void);

    /**
     * calculate coefficient factor A_S_S
     * A_S_S is coefficent factor of sample scattered at sample.
     *
     * @@return A_S_S
     */
    Double GetA_S_S(void);

    /**
     * calculate coefficient factor A_C_C
     * A_C_C is coefficent factor of sell scattered at cell.
     *
     * @@return ACC
     */
    Double GetACCd(Double, Double, Double, Double);

    /**
     * calculate coefficient factor A_CS_S
     * A_CS_S is coefficent factor of sell+sample scattered at sample.
     *
     * @@return ACSS
     */
    Double GetACSSd(Double, Double, Double, Double);

    /**
     * calculate coefficient factor A_CS_C
     * A_CS_C is coefficent factor of sell+sample scattered at sample.
     *
     * @@return ACSS
     */
    Double GetACSCd(Double, Double, Double, Double);

    Double GetQVal(Double, Double, Double); // [20140410 AS]

  public:
    /** constructor */
    AdvCorrectionAbsorptionDNA(void);
    AdvCorrectionAbsorptionDNA(std::string);
    AdvCorrectionAbsorptionDNA(std::string,std::string);  //[20140410 AS]

    /** destructor */
    ~AdvCorrectionAbsorptionDNA(void);

    /**
     * return threshold value used for judgement of convergence in numerial integral
     *
     * @@return epsilon
     */
//    Double GetIntegThresholdValue(void) {return epsilon;};

    /**
     * return threshold value of ratio used for judgement of convergence in numerial integral
     *
     * @@return epsilonRatio
     */
//    Double GetIntegThresholdRatio(void) {return epsilonRatio;};

    /**
     * set threshold value used for judgement of convergence in numerial integral
     *
     * @@set epsilon
     */
//    void SetIntegThresholdValue(Double a) {epsilon=a;};

    /**
     * set threshold value Ratio used for judgement of convergence in numerial integral
     *
     * @@set epsilonRatio
     */
//    void SetIntegThresholdRatio(Double a) {epsilonRatio=a;};

    /**
     * calculate coefficient factor A_C_C
     * A_C_C is coefficent factor of sell scattered at cell.
     *
     * @@return ACC
     */
    Double GetACC(Double, Double, Double, Double);

    /**
     * calculate coefficient factor A_CS_S
     * A_CS_S is coefficent factor of sell+sample scattered at sample.
     *
     * @@return ACSS
     */
    Double GetACSS(Double, Double, Double, Double);

    /**
     * calculate coefficient factor A_CS_C
     * A_CS_C is coefficent factor of sell+sample scattered at sample.
     *
     * @@return ACSS
     */
    Double GetACSC(Double, Double, Double, Double);

    /**
     * calculate coefficient factor A_S_S
     * A_S_S is coefficent factor of sample scattered at sample.
     * only use in the case of column shape
     *
     * @@return ASS
     */
    Double GetASS(Double, Double, Double, Double);

    /**
     * calculate intensity correctrion
     */
    void GetModifiedIntensity(Double, char*, char*);

//    void GetAbsorptionCoeffs(ElementContainer *ec1, ElementContainer *ec2);
    std::vector<Double> GetThetaPhi(PyObject*);

    Double GetCorrectIntensity(Double, Double, Double, Double, Double);
};

#endif
