#ifndef SASCONVERTTOQSPACE
#define SASCONVERTTOQSPACE

#include <math.h>
#include "Header.hh"
#include "OperatorBase.hh"
#include "ElementContainer.hh"
#include "ElementContainerArray.hh"
#include "ElementContainerMatrix.hh"
#include "HeaderBase.hh"
#include "StringTools.hh"
#include "UtsusemiHeader.hh"
#include "UtsusemiUnitConverter.hh"
#include "UtsusemiCheckDataProcess.hh"
#include "UtsusemiAnaEnvironReader.hh"
#include "SASDetectorInfoEditorRPMT.hh"

//////////////////////////////////
// Calclate Qx, Qy, Qx on SAS
/////////////////////////////////

//! Function to make Q std::vector and add to ElementContainer
/*!
 *
 *
 *
 *
 */
class ConvertToQspace :
  public ManipulatorBase< ElementContainerMatrix >
{
private:
    void Initialize();
    std::vector<Double> IncidentVect;  /**< std::vector of the incident beam orientetion */
    std::string _MessageTag;
    UtsusemiUnitConverter* UU;
    UtsusemiCheckDataProcess* UCP;
    std::string _ProcessTag;
    Double _grav_param_a;
    Double _grav_param_b;

public:
    ConvertToQspace();
        //!< Constructor
        /*!<
         */
    ConvertToQspace(ElementContainerMatrix *ecm, Double vx=0.0, Double vy=0.0, Double vz=1.0 );
        //!< Constructor
        /*!<
         *  @param ecm ElementContainerMatrix for the target
         */
    ~ConvertToQspace();
        //!< Destructor
        /*!<
         */
    void SetIncidentBeamVector( Double vx=0.0, Double vy=0.0, Double vz=1.0 );
        //!< Sets Incident Beam orientation std::vector
        /*!< This orientation is used to calculate Q values.
         *   void SetIncidentBeamVector( Double vx=0.0, Double vy=0.0, Double vz=1.0 )
         *
         *   @param vx (Double) x-axis of orientation vector
         *   @param vy (Double) y-axis of orientation vector
         *   @param vz (Double) z-axis of orientation vector
         *   @return None
         */
    bool SetIncidentBeamRPMT(Int4 DET, Int4 PIX);
        //!< Sets Incident Beam calculated from the beam center at DET and PIX pixel
        /*!<
         *   @param DET   Detector ID for the beam center pixel
         *   @param PIX   Pixel No for the beam center pixel
         *   @retval true   done successfully
         *   @retval false  failed
         */
    bool SetIncidentBeamWithGravityRPMT( Double alpha, Double beta, Double px );
    bool SetIncidentBeamWithGravityRPMT( Double beta, Double lambda, Double px, Double py );
        //!< Sets Incident Beam with lambda dependency by gravity effect
        /*!<
         *   @param beta    lambda dependency parameter a-b*(lambada)^2
         *   @param lambda  lambda where beam center is (px,py)
         *   @param px      beam center position for x axis
         *   @param py      beam center position for y axis
         *   @retval true   done successfully
         *   @retval false  failed
         */
    bool SetIncidentBeamWithGravityRPMTDetectInfo( UInt4 runNo, UInt4 modeNo, std::string dfile="", Double beta=0.0, Double l2=0.0 );
        //!< Sets Incident Beam with lambda dependency by gravity effect using parameters in detector info.
        /*!<
         *   @param dfile   DetectorInfo file path. If empty, default file is used.
         *   @param beta    lambda dependency parameter b in a-b*(lambada)^2 [mm/Angst]
         *   @param l2      L2 shortest distance between sample and RPMT
         *   @retval true   done successfully
         *   @retval false  failed
         */
    bool SetIncidentBeamWithGravity( Double alpha, Double beta, Double px );
    bool Execute();
        //!< Convert To Q space
        /*!<
         *   @param None
         *   @retval true   done successfully
         *   @retval false  failed
         */
};
#endif
