#ifndef MARS_Nova
#define MARS_Nova

#include <libnova/solar.h>
#include <libnova/lunar.h>
#include <libnova/rise_set.h>
#include <libnova/transform.h>

namespace Nova
{
    typedef ln_lnlat_posn LnLatPosn;
    //typedef ln_hrz_posn   HrzPosn;
    typedef ln_equ_posn   EquPosn;
    typedef ln_rst_time   RstTime;

    struct ZdAzPosn;

    // Warning: 0deg=South, 90deg=W
    struct HrzPosn : public ln_hrz_posn
    {
        HrzPosn() { }
        HrzPosn(const ZdAzPosn &);
    };

    struct ZdAzPosn
    {
        double zd;
        double az;

        ZdAzPosn() : zd(0), az(0) { }
        ZdAzPosn(const HrzPosn &hrz) : zd(90-hrz.alt), az(hrz.az-180) { }

        // This crahsed cint, but it could save up the dedicate structure HrzPosn :(
        //operator HrzPosn() const { const HrzPosn p = { az-180, 90-zd}; return p; }
    };

    HrzPosn::HrzPosn(const ZdAzPosn &za) { alt = 90-za.zd; az = za.az-180; }



    const LnLatPosn &ORM()
    {
        //static LnLatPosn obs;
        //obs.lng = -(17.+53./60+26.525/3600);
        //obs.lat =   28.+45./60+42.462/3600;
        const static LnLatPosn obs = { -(17.+53./60+26.525/3600), 28.+45./60+42.462/3600 };
        return obs;
    }

    HrzPosn GetHrzFromEqu(const EquPosn &equ, const LnLatPosn &obs, double jd)
    {
        HrzPosn hrz;
        ln_get_hrz_from_equ(const_cast<EquPosn*>(&equ), const_cast<LnLatPosn*>(&obs), jd, &hrz);
        return hrz;
    }
    HrzPosn GetHrzFromEqu(const EquPosn &equ, double jd)
    {
        return GetHrzFromEqu(equ, ORM(), jd);
    }

    EquPosn GetEquFromHrz(const HrzPosn &hrz, const LnLatPosn &obs, double jd)
    {
        EquPosn equ;
        ln_get_equ_from_hrz(const_cast<HrzPosn*>(&hrz), const_cast<LnLatPosn*>(&obs), jd, &equ);
        return equ;
    }
    EquPosn GetEquFromHrz(const HrzPosn &hrz, double jd)
    {
        return GetEquFromHrz(hrz, ORM(), jd);
    }

    RstTime GetSolarRst(double jd, const LnLatPosn &obs, double hrz=LN_SOLAR_STANDART_HORIZON)
    {
        RstTime rst;
        ln_get_solar_rst_horizon(jd, const_cast<LnLatPosn*>(&obs), hrz, &rst);
        return rst;
    }
    RstTime GetSolarRst(double jd, double hrz=LN_SOLAR_STANDART_HORIZON)
    {
        return GetSolarRst(jd, ORM(), hrz);
    }

    RstTime GetLunarRst(double jd, const LnLatPosn &obs=ORM())
    {
        RstTime rst;
        ln_get_lunar_rst(jd, const_cast<LnLatPosn*>(&obs), &rst);
        return rst;
    }
    EquPosn GetSolarEquCoords(double jd)
    {
        EquPosn equ;
        ln_get_solar_equ_coords(jd, &equ);
        return equ;
    }

    double GetLunarDisk(double jd)
    {
        return ln_get_lunar_disk(jd);
    }

    double GetLunarSdiam(double jd)
    {
        return ln_get_lunar_sdiam(jd);
    }

    double GetLunarPhase(double jd)
    {
        return ln_get_lunar_phase(jd);
    }

    EquPosn GetLunarEquCoords(double jd, double precision=0)
    {
        EquPosn equ;
        ln_get_lunar_equ_coords_prec(jd, &equ, precision);
        return equ;
    }

    double GetLunarEarthDist(double jd)
    {
        return ln_get_lunar_earth_dist(jd);
    }
}

#endif
