#ifndef MLFSCATABSOBODYMANAGER
#define MLFSCATABSOBODYMANAGER

#include "HeaderBase.hh"
#include "ElementContainer.hh"
#include "ElementContainerArray.hh"
#include "ElementContainerMatrix.hh"
#include "StringTools.hh"
#include "BoostXmlParser.hh"
#include "MlfPhysicalConstants.hh"
#include "AdvScatAbsoBodyManagerMLF.hh"

//////////////////////////////////
// MlfScatAbsoBodyManager
/////////////////////////////////

//! Calclates neutron Scattring and absorption on nuclei
/*!
 *  This code gives crosssections for atoms
 *  which are used for the detector efficiency correction.
 *
 *  Override some methods
 *   - import parameters from xml files instead of text files.
 *
 *  @author Yasuhiro Inamura (J-PARC,MLF)
 *
 */

class MlfScatAbsoBodyManager:
    public AdvScatAbsoBodyManagerMLF
{
private:
    std::string _MessageTag;
    BoostXmlParser* _BXP;
    std::string _DetectorStructureInfo;
    void Initialize();
    bool _SetDefaultNistData();
    StringTools* _stools;
    std::string _XML_KEY_NISTDATA;
    std::string _XML_KEY_DETDATA;
    bool isLoadedDefaultNistData;


    Double sigmaDetectorA;
    Double sigmaWallA;
    Double sigmaWallS;
    struct ScatAbsoInfo detectorInfo;
    struct ScatAbsoInfo wallInfo;

public:
    MlfScatAbsoBodyManager();
    MlfScatAbsoBodyManager(std::string _detectInfoPath, std::string _nistDataPath="");
    ~MlfScatAbsoBodyManager();

    //////////////////////////////////////////////////////////////////////////
    // public variables
    //////////////////////////////////////////////////////////////////////////
    /*
     *  _Xtable_** store information of atoms in cell or detector materials
     */
    std::vector<std::string> *_Xtable_name;
    std::vector<double> *_Xtable_velocity;
    std::vector<double> *_Xtable_cohCS;
    std::vector<double> *_Xtable_incCS;
    std::vector<double> *_Xtable_scaCS;
    std::vector<double> *_Xtable_absCS;
    bool Status;
    std::string _XML_NAME_NISTDATA;
    //std::string _SearchXmlPath;
    bool isDebug;
    //////////////////////////////////////////////////////////////////////////
    // public functions
    //////////////////////////////////////////////////////////////////////////
    bool SetXmlInfoFile(std::string detectorInfoPath, std::string _nistDataPath="");
        //!< Set full path to DetectorInfo file and Nist data file
        /*!<
         *
         *    @param detectorInfoPath (std::string)
         *    @param _nistDataPath    (std::string)
         *    @return None
         */
    bool SetNistXmlFile(std::string _nistDataPath);
    bool SetDetectorInfoFile(std::string detectorInfoPath);
    bool SetDetName( std::string det_name="" );
    std::string PutDetectorStructureInfo(){ return _DetectorStructureInfo; }
    //void SetXmlPath( std::string path );
    bool AddSigmaToXtable(std::string atomname);
    void DumpXtable();
    Double GetAtomSigmaWithEnergy( std::string atomname, std::string xstype, Double energy );
    Double GetAtomSigmaWithLambda( std::string atomname, std::string xstype, Double lambda );


    //////////////////////////////////////////
    // override virtual function
    void SetInfoData(std::string det_name, struct ScatAbsoInfo* wallInfo, struct ScatAbsoInfo* bodyInfo);
    void SetSigmaDataNIST(Double velocity, std::string atomname, std::string typeCS);
    Double GetAtomicWeight(std::string); /**< get atomic weight for the specified nuclide or elemnent */


    /////////////////////////////////////////
    // calc Efficiency
    Double GetEfficiency(Double eneNeutron, Double thetaDetector);
    void GetSigmas(Double energy, Double* sigmaDA, Double* sigmaWA, Double* sigmaWS);
    Double CalcEfficiencyDetector(Double thetaDetector, Double sigmaDA, Double sigmaWS, Double sigmaWA);
    Double ReturnAbsorptionByDetector(Double x, Double theta,
                                      Double sigmaDA, Double sigmaWS, Double sigmaWA,
                                      Double radiusDetector, Double radiusInnerDetector, Double radiusWall, Double n3He, Double nwall, Double T);

    /////////////////////////////////////////
    // Calc Xsections from Text form
    Double GetMolecularWeight( std::string form );
    Double GetTotalXsectAve( std::string form );
    Double GetNumberDensity( std::string form, Double dencity );
    // density   : [g/cm^3]
    // molweight : [g/mol]
    // numeric dencity : [1/cm^3] = density*Na/molweight
    bool _Transform( std::string form, std::vector< std::pair<std::string,Double> > &parts );
    bool _GetAtomInfo( std::string atomname, std::vector<Double> &info );

    void SetDebugMode( bool _isDebug = true ){isDebug=_isDebug;}
};

#endif
