#include "Test.h"

#include "System_of_Units.h"
#include "AKMA_System_of_Units.h"
#include "SI_System_of_Units.h"

#include "Length_unit.h"
#include "Duration_unit.h"

namespace MM
{

class System_of_Units_test : public Test
{
    System_of_Units *link_1;
    Unit            *link_2;

public:
    System_of_Units_test (const Text & suite_name) : Test(suite_name) { }

    void run ()
    {
        demo();     count_tests();
        IUPAC();    count_tests();
        //Atomic();   count_tests();
        AKMA ();    count_tests();
        E ();       count_tests();
    }

    void demo()
    {
        AKMA_System_of_Units    AKMA;
        Length_unit             length;
        Duration_unit           time;

        length.set_A  (1.);
        time.set_AKMA (1.);

        DOUBLES_EQUAL (AKMA.length (length), 1., 0.000001);
        DOUBLES_EQUAL (AKMA.time   (time),   1., 0.000001);
    }

    void IUPAC()
    {
        Pressure_unit pressure;
        pressure.set_atm (1.);
        DOUBLES_EQUAL (pressure.Pa(), 101325., 1);
        pressure.set_bar (1.);
        DOUBLES_EQUAL (pressure.Pa(), 100000., 1);
        pressure.set_torr (1.);
        DOUBLES_EQUAL (pressure.Pa(), 133.322, 0.001);

        Length_unit length;
        length.set_bohr (1.);
        DOUBLES_EQUAL (length.m(), 5.29177249e-11, 1e-19);

        Charge_unit charge;
        charge.set_C(1);
        DOUBLES_EQUAL (charge.Fr(), 3.33564e-10, 1e-15);

        Mass_unit mass;
        mass.set_amu(1);
        DOUBLES_EQUAL (mass.kg(), 1.6605402e-27, 1e-17);
    }

    /*void Atomic ()
    {
    }//*/

    void AKMA ()
    {
        AKMA_System_of_Units    AKMA;
        SI_System_of_Units      SI;
        Length_unit      length;
        Energy_unit      energy;
        Mass_unit        mass;
        Charge_unit      charge;
        Duration_unit    time;
        Force_unit       force;
        Pressure_unit    pressure;

        AKMA.set_length   (length,   1);
        AKMA.set_energy   (energy,   1);
        AKMA.set_mass     (mass,     1);
        AKMA.set_charge   (charge,   1);
        AKMA.set_time     (time,     1, 1);
        AKMA.set_force    (force,    1);
        AKMA.set_pressure (pressure, 1);
 
        DOUBLES_EQUAL (SI.length   (length),   1.e-10,      1e-10);
        DOUBLES_EQUAL (SI.energy   (energy),   4184,        1);
        DOUBLES_EQUAL (SI.mass     (mass),     1.661e-27,   1e-30);
        DOUBLES_EQUAL (SI.charge   (charge),   1.602e-19,   1e-22);
        DOUBLES_EQUAL (SI.time     (time),     0.04888e-12, 1e-17);
        DOUBLES_EQUAL (SI.force    (force),    6.951e-11,   1e-14);
        DOUBLES_EQUAL (SI.pressure (pressure), 6.951e9,     1e6);
    }

    void E ()
    {
        Energy_unit e;

        e.set_Hartrees (1);
        DOUBLES_EQUAL (e.Hartrees(), 1,                 0.00001);
        DOUBLES_EQUAL (e.eV(),       27.211399,         0.00001);
        DOUBLES_EQUAL (e.kJImol(),   2625.5002,         0.001);
        DOUBLES_EQUAL (e.kcalImol(), 627.509608,        0.0001);
        DOUBLES_EQUAL (e.lIcm(),     219474.63,         0.1);
        DOUBLES_EQUAL (e.K(),        315777.09,         0.1);

        e.set_eV (1);
        DOUBLES_EQUAL (e.Hartrees(), 0.036749305,       0.00000001);
        DOUBLES_EQUAL (e.eV(),       1.,                0.00001);
        DOUBLES_EQUAL (e.kJImol(),   96.4853075,        0.000001);
        DOUBLES_EQUAL (e.kcalImol(), 23.0605419,        0.000001);
        DOUBLES_EQUAL (e.lIcm(),     8065.54011,        0.0001);
        DOUBLES_EQUAL (e.K(),        11604.5886,        0.001);

        e.set_kJImol (1);
        DOUBLES_EQUAL (e.Hartrees(), 0.00038088,        0.0000001);
        DOUBLES_EQUAL (e.eV(),       0.010364272,       0.00000001);
        DOUBLES_EQUAL (e.kJImol(),   1,                 0.000001);
        DOUBLES_EQUAL (e.kcalImol(), 0.239005736,       0.00000001);
        DOUBLES_EQUAL (e.lIcm(),     83.5934539,        0.000001);
        DOUBLES_EQUAL (e.K(),        120.273116,        0.00001);

        e.set_kcalImol (1);
        DOUBLES_EQUAL (e.Hartrees(), 0.001593601,       0.00000001);
        DOUBLES_EQUAL (e.eV(),       0.043364115,       0.00000001);
        DOUBLES_EQUAL (e.kJImol(),   4.184,             0.000001);
        DOUBLES_EQUAL (e.kcalImol(), 1,                 0.000001);
        DOUBLES_EQUAL (e.lIcm(),     349.755011,        0.00001);
        DOUBLES_EQUAL (e.K(),        503.222717,        0.00001);

        e.set_lIcm (1);
        DOUBLES_EQUAL (e.Hartrees(), 0.00000455634,     0.0000000001);
        DOUBLES_EQUAL (e.eV(),       0.000123984,       0.00000001);
        DOUBLES_EQUAL (e.kJImol(),   0.011962659,       0.00000001);
        DOUBLES_EQUAL (e.kcalImol(), 0.002859144,       0.00000001);
        DOUBLES_EQUAL (e.lIcm(),     1,                 0.0001);
        DOUBLES_EQUAL (e.K(),        1.4387863,         0.000001);

        e.set_K (1);
        DOUBLES_EQUAL (e.Hartrees(), 0.00000316679,     0.0000000001);
        DOUBLES_EQUAL (e.eV(),       0.0000861728,      0.000000001);
        DOUBLES_EQUAL (e.kJImol(),   0.00831441,        0.0000001);
        DOUBLES_EQUAL (e.kcalImol(), 0.001987192,       0.00000001);
        DOUBLES_EQUAL (e.lIcm(),     0.695030251,       0.00000001);
        DOUBLES_EQUAL (e.K(),        1,                 0.001);
    }
};

System_of_Units_test test_System_of_Units ("correctness");

}//MM
