#ifndef UTSUSEMIUNITCONVERTER
#define UTSUSEMIUNITCONVERTER

#include "Header.hh"
#include "UtsusemiHeader.hh"
#include "MlfPhysicalConstants.hh"

/****  Constants ******/

extern const Double PI;
extern const Double Mn;            // Neutron mass [kg]
extern const Double PLANCK;        // Planck constant [Js]
extern const Double HBAR;          // Planck/2*PI [Js]
extern const Double kB;            // Boltzmann constant [J/K]
extern const Double MLF_EV2J;      // 1 [eV] = 1.6 [J]
extern const Double MLF_J2EV;      // 1 [J] = 1/1.6 [eV]
extern const Double MLF_MEV2J;     // 1meV=1.e-03eV
extern const Double MLF_J2MEV;

//////////////////////////////////
// Unit Conversion on Utsusemi
/////////////////////////////////

//! Function for offering some constant values and converting units.
/*!
 * Unit Conversion
 * e=1.602187653e-19 [J]->1meV=1.602187653e-22[J]
 * [J]=[kg(m/2)^2]
 * mn=1.67495e-27 [kg]
 * -----
 * Basical Units
 * length [meter]
 * time   [micro-second]
 * Energy [milli-electron-volt]
 * verocity [meter/micro-second]
 * Wave length [Ang]
 * Wave std::vector [1/Ang]
 */
class UtsusemiUnitConverter
{
private:

protected:
    double cMn;      /**< mass of a neutron [kg] */
    double cPlanck;  /**< Planck's constant [Js] */
    double chver;    /**< Planck's constant/2Pi [Js] */
    double cnvJtoE;  /**< conversion from [J] to [meV]*/

    double cLEtoT;   /**< [micro sec]/[m]*[meV] */
    double cVtoE;    /**< [meV]/[(m/s)**2] */
    double cEtoV;    /**< [m/s]/[sqrt(meV)] */
    double cK2toE;   /**< [(1/Ang)**2]/[meV] */
    double cVtoLambda; /**< conversion parameter from v to lambda */

public:
    UtsusemiUnitConverter();
        //!< Constructor
        /*!<
         */
    ~UtsusemiUnitConverter();
        //!< Destructor
        /*!<
         */
    double LEtoT(){ return cLEtoT; }
        //!< Puts conversion parameter from L[m], E[meV] to TOF[micro-sec]
        /*!<
         *   @return cLEtoT
         */
    double LEtoT( double L, double E );
        //!< Puts Tof[micro-sec] converted from given L[m] and E[meV]
        /*!<
         *   @param L     flight path length [meter]
         *   @param E     energy [meV]
         *   @return TOF [micro-sec]
         */
    double VtoE(){ return cVtoE; }
        //!< Puts conversion parameter from V[meter/micro-sec] to E[meV]
        /*!<
         *   @return cVtoE
         */
    double VtoE( double V );
        //!< Puts Energy[meV] converted from given verocity[meter/micro-sec]
        /*!<
         *   @param V    verocity of neutron [meter/micro-sec]
         *   @return energy [meV]
         */
    double VtoK( double V );
        //!< Puts wave std::vector converted from given verocity
        /*!<
         *   @param V    verocity of neutron [m/s]
         *   @return wave std::vector [(1/Ang)]
         */
    double Vmm_msToK();
        //!< Puts wave std::vector converted from given verocity
        /*!<
         *   @param V    verocity of neutron [mm/micro-sec]
         *   @return constant to convert from V[mm/micro-sec] to K [(1/Ang)]
         */
    double Vmm_msToK( double V );
        //!< Puts wave std::vector converted from given verocity
        /*!<
         *   @param V    verocity of neutron [mm/micro-sec]
         *   @return wave std::vector [(1/Ang)]
         */
    double EtoV(){ return cEtoV; }
        //!< Puts conversion parameter from E[meV] to V[meter/micro-sec]
        /*!<
         *   @return cEtoV
         */
    double EtoV( double E );
        //!< Puts verocity[meter/micro-sec] converted from given energy of neutron [meV]
        /*!<
         *   @param E     energy of neutron [meV]
         *   @return verocity [meter/micro-sec]
         */
    double Mn(){ return cMn; }
        //!< Puts constant value about mass of a neutron [kg]
        /*!<
         *   @return mass of neutron [kg]
         */
    double KtoE( double K );
        //!< Puts Energy[meV] converted from given wave std::vector [1/Ang]
        /*!<
         *   @param K     wave std::vector length [1/Ang]
         *   @return energy [meV]
         */
    double K2toE(){ return cK2toE; }
        //!< Puts conversion parameter from sqare( K[1/Ang] ) to Energy [meV]
        /*!<
         *   @return cK2toE
         */
    double EtoK2( double E );
        //!< Puts square of wave std::vector[1/Ang] converted from given energy[meV]
        /*!<
         *   @param E     energy of neutron [meV]
         *   @return square of wave std::vector [1/Ang]
         */
    double J2meV(){ return cnvJtoE; }
        //!< Puts unit conversion parameter from Joule to meV
        /*!<
         *   @return cnvJ2E
         */
    double TLtoLambda( double _tof, double _L );
        //!< Puts lambda [Angs.] from TOF[micro-sec] and L1+L2[m]
        /*!<
         *   @param _tof time of flight [micro-sec]
         *   @param _L   length between modelator and detector [m]
         *   @return lambda (double)
         */
    double VtoLambda(){ return cVtoLambda; }
        //!< Puts conversion parameter from 1/v[meter/micro-sec] to lambda [Angs.]
        /*!<
         *   @return ccVtoLambda
         */
    double VtoLambda( double V );
        //!< Puts lambda [Ang] from v[meter/micro-sec]
        /*!<
         *   @param V (double) verosity [meter/micro-sec]
         *   @return lambda (double)
         */
    double EtoLambda( double E );
        //!< Puts lambda [Ang]  from E[meV]
        /*!<
         *   @param E (double) energy [meV]
         *   @return lambda (double)
         */
    double KtoLambda( double K );
        //!< Puts lambda [Ang]  from K[1/Ang]
        /*!<
         *   @param K (double) wave number [1/Ang]
         *   @return lambda (double)
         */
    double LambdatoE( double Lam );
        //!< Puts E [meV] from lambda [Ang]
        /*!<
         *   @param Lam (double) wavelength [Ang]
         *   @return energy (double)
         */
};
#endif
