#ifndef SASINCOHCALCFOR3HESPINFILTER
#define SASINCOHCALCFOR3HESPINFILTER

#include "Header.hh"
#include "CppToPython.hh"
#include "ElementContainerMatrix.hh"
#include "UtsusemiHeader.hh"

//////////////////////////////////
// IncohCalcFor3HeSpinFilter
/////////////////////////////////

//! Function to calculate coherent data and incoherent data from both measured data with spin flipper on/off
/*!
 * [Single scattering]
 * tt=IncohCalcFor3HeSpinFilter( DAT1, DAT2 ) # DAT1 : Spin Flipper on, DAT2 : Spin Flipper off
 * if tt.SetPolarizationTable( "/path/to/data.dat" ):
 *     tt.SetAval( 0.505 )
 *     tt.SetHePressure( 0.617 )
 *     DAT_c = ElementContainerMatrix() # Coherent scattering data
 *     DAT_ic= ElementContaienrMatrix() # Incoherent scattering data
 *     if tt.Execute(DAT_c, DAT_ic):
 *         # Steps for succeeded
 *
 * [Multi scattering]
 * tt=IncohCalcFor3HeSpinFilter( DAT1, DAT2 ) # DAT1 : Spin Flipper on, DAT2 : Spin Flipper off
 * if tt.SetPolarizationTable( "/path/to/data.dat" ):
 *     tt.SetAval( 0.505 )
 *     tt.SetHePressure( 0.617 )
 *     if tt.SetMultiScatPval( 0.5 ):
 *         DAT_c = ElementContainerMatrix() # Coherent scattering data
 *         DAT_ic= ElementContaienrMatrix() # Incoherent scattering data
 *         DAT_nsf = ElementContainerMatrix() # non-spin-flip data on multi-scattering
 *         DAT_sf  = ElementContainerMatrix() # spin-flip data on multi-scattering
 *     if tt.Execute(DAT_c, DAT_ic, DAT_nsf, DAT_sf):
 *         # Steps for succeeded

 */

class IncohCalcFor3HeSpinFilter
{
private:

    UInt4 _NumOfMulth;
    void Initialize();
    std::string _MessageTag;
    Double _A;
    Double _P_He_p;
    Double _P_He_m;
    Double _P_Multi;
    bool _isAbsCorr;
    ElementContainerMatrix* _DAT1;
    ElementContainerMatrix* _DAT2;
    std::vector<Double> _pol_lam;
    std::vector<Double> _pol_val;
    StringTools* _st;

public:
    IncohCalcFor3HeSpinFilter();
        //!< Constructor
        /*!<
         *
         */
    IncohCalcFor3HeSpinFilter( ElementContainerMatrix* dat1, ElementContainerMatrix* dat2, Double A=0.0, Double P_He_p=0.0, Double P_He_m=0.0, bool isAbsCorr=true );
        //!< Constructor
        /*!<
         *  @param dat1 (ElementContainerMatrix) Data for spin flipper on
         *  @param dat2 (ElementContainerMatrix) Data for spin flipper off
         *  @param A    (Double) A(lambda) value
         *  @param P_He_p (Double) the pressure of He
         *  @param P_He_m (Double) the pressure of He
         *  @param isAbsCorr (bool) correction of absorption on changing flight path by two theta
         */
    ~IncohCalcFor3HeSpinFilter();
        //!< Destructor
        /*!<
         *
         */
    void SetData( ElementContainerMatrix* dat1, ElementContainerMatrix* dat2 );
        //!< Set Data
        /*!<
         *  @param dat1 (ElementContainerMatrix) Data for spin flipper on
         *  @param dat2 (ElementContainerMatrix) Data for spin flipper off
         *  @param A    (Double) A(lambda) value
         *  @param P_He (Double) the pressure of He
         *  @return None
         */
    bool SetPolarizationTable( std::string _pathToData );
        //!< Set text file path for Polarization table
        /*!<  text format  <lambda>,<polarization>
         *    If the beginning of line is #, ignored
         *  @param _pathToData (std::string) path to text file
         *  @retval true  : succeeded.
         *  @retval false : failed.
         */
    void SetHePlusPressure( Double P_He ){ _P_He_p = P_He; }
        //!< Set He pressure value
        /*!<
         *  @param P_He (Double) the pressure of He
         *  @return None
         */
    void SetHeMinusPressure( Double P_He ){ _P_He_m = P_He; }
        //!< Set He pressure value
        /*!<
         *  @param P_He (Double) the pressure of He
         *  @return None
         */
    void SetAval( Double A ){ _A = A; }
        //!< Set A(lambda) value
        /*!<
         *  @param A    (Double) A(lambda) value
         *  @return None
         */
    void SetAbsCorrectionByTwoTheta( bool isAbsCorr = true ){ _isAbsCorr = isAbsCorr; }
        //!<  Use A/cos(2theta)*lambda insteed of A*lambda
        /*!<
         *  @param isAbsCorr (bool)
         *  @return None
         */
    bool SetMultiScatPval( Double Pval );
        //!<  Set P value to be used for calculation on Multi Scattering
        /*!<
         *  @param Pval (Double) P values (0.5 < Pval < 2/3
         *  @return None
         */
    bool Execute( ElementContainerMatrix* _coh, ElementContainerMatrix* _inc, ElementContainerMatrix* _NSF=NULL, ElementContainerMatrix* _SF=NULL );
        //!< Calcurate coherent scattering and incoherent scattering data from both with given data set of spin flipper on/off
        /*!<
         *
         *  @param _coh (ElementContainerMatrix) given empty data to be stored the coherent data
         *  @param _inc (ElementContainerMatrix) given empty data to be stored the incoherent data
         *  @param _NSF (ElementContainerMatrix) given empty data to be stored the NSF(non-spin-flip) data
         *  @param _SF (ElementContainerMatrix) given empty data to be stored the SF(spin-flip) data
         *  @retval true  : succeeded.
         *  @retval false : failed.
         */

};
#endif
