// SPDX-License-Identifier: LGPL-2.1-or-later
//
// SPDX-FileCopyrightText: 2012 Gerhard HOLTKAMP
//

#if !defined(__eclsolar_h)
#define __eclsolar_h

#include "astrolib_export.h"
#include "attlib.h"

const int GBL_ECLBUF = 12; // maximum number of eclipses allowed
const int MAXLUN = 15;

typedef double PMJD[MAXLUN]; // array of MJD's of the respective phase

class ASTROLIB_EXPORT EclSolar // Calculate Solar Eclipses
{
public:
    EclSolar();
    ~EclSolar();

    int getYear() const; // the year currently used by EclSolar
    void putYear(int yr); // set the year to be used by EclSolar
    int getNumberEclYear(); // get the number of eclipses of the currently selected year
    void setLunarEcl(bool lecl); // include lunar eclipses
    void setStepWidth(double s); // set the step width (minutes)
    void setTimezone(double d); // set timezone for I/O
    void setDeltaTAI_UTC(double d); // set IERS Parameter TAI - UTC
    void setAutoTAI_UTC(); // IERS Parameter TAI - UTC to auto
    void setLocalPos(double lat, double lng, double hgt); // set local geographic coordinates
    void getLocalDetails(char *otxt); // provide eclipse details for local position
    void setCurrentMJD(int year, int month, int day, int hour, int min, double sec); // set current time
    void getDatefromMJD(double mjd, int &year, int &month, int &day, int &hour, int &min, double &sec) const; // convert MJD into date and time
    int getLocalVisibility(double &mjd_start, double &mjd_stop); // local start and stop times for eclipse
    int getLocalTotal(double &mjd_start, double &mjd_stop); // local start and stop times for totality/annularity
    int getLocalMax(double &mjdmax, double &magmax, double &elmax); // get local (solar) eclipse maximum
    int getPenumbra(double &mjd_start, double &mjd_stop); // start and stop times for penumbral eclipse of Moon
    int getPartial(double &mjd_start, double &mjd_stop); // (global) start and stop times for partial phase
    int getTotal(double &mjd_start, double &mjd_stop); // (global) start and stop times for totality/annularity
    void getEclYearInfo(char *wbuf); // list of eclipses of the year
    int getEclYearInfo(int k, int &yr, int &month, int &day, int &hour, int &min, double &sec, double &tzone, double &magn);
    int getEclTxt(int j, char *jtxt); // get text for j-th eclipse
    void putEclSelect(int es); // select particular eclipse for details
    void nextEcl(); // select the next eclipse for details
    void previousEcl(); // select the previous eclipse for details
    double getLastMJD() const; // get the MJD last used in calculations
    void getMaxPos(double &lat, double &lng); // get position of maximum eclipse
    int eclPltCentral(bool firstc, double &lat, double &lng); // calc central eclipse line
    int GNSBound(bool firstc, bool north, double &lat, double &lng); // northern or southern boundary
    int GRSBound(bool firstc, double &lat1, double &lng1, double &lat2, double &lng2);
    // Rise / Set Boundary
    int centralBound(bool firstc, double &lat1, double &lng1, double &lat2, double &lng2);
    void getShadowCone(double mjd, bool umbra, int numpts, double *lat, double *lng);
    void setPenumbraAngle(double pa, int mode);

private:
    void esinit(); // initialize EclSolar
    static double atan23(double y, double x); // atan without singularity for x,y=0
    void DefTime(); // Get System Time and Date
    void calcMaxPos(double &lat, double &lng); // get position of maximum eclipse
    static void GetMonth(int mm, char *mchr);
    static double phmjd(double yearf, double phase, double tdut, int &eph, double &ejd, double &emag);
    void ckphase(double minmjd, double maxmjd, double yr, double deltdut, int &mp, PMJD p, double phase);
    static void dtmstr(double jdmoon, char *dts);
    void moonph(); // calculate phases of the Moon
    void eclStart(); // initialize detailed calcs for selected eclipse
    static double getlocmag(double jd, double ep2, double phi, double lamda, double height, const Vec3 &rs, const Vec3 &rm, int &totflg);
    static int iscrs(double vrc0, double vrc1, double dpn, double &vrx0, double &vrx1, double &vrx20, double &vrx21);
    void InitBound(); // initialize boundary calcs
    void InRSBound(); // initialize Sunrise/Sunset boundaries
    static double DegFDms(double h);
    int localStart(int j, double *spt, double *ept, int *spp, int p, char *otxt);
    static double navCourse(double lat1, double lng1, double lat2, double lng2); // navigation course from p1 to p2
    static void navNewPos(double d, double an, double lat1, double lng1, double &lat2, double &lng2);
    static double sunObscure(double l1, double l2, double m); // get the Obscuration of the Sun

    // data fields

    bool eb_start_called; // true if eclStart() has already been called for eclipse
    bool eb_moonph_called; // true if moonph has already been called for year
    bool eb_lunecl; // true if lunar eclipses are to be included
    bool eb_lunactive; // true if current eclipse is a lunar eclipse
    bool eb_local_called; // true if local circumstances calculated

    int eb_day; // date
    int eb_month;
    int eb_year;
    int eb_hour;
    int eb_minute;
    int eb_second;
    double eb_time;
    double eb_tzone; // timezone in hours
    double eb_del_tdut; // TDT - UT in sec
    int eb_del_auto; // 1 = automatic del_tdut,  0 = manual
    double eb_geolat; // geographic coordinates (angles in degrees)
    double eb_geolong;
    double eb_geoheight; // in meters
    int eb_lstcall; // 1 = last call moonph; 2 = caldisp; 0 = no call
    int eb_locecl; // 1 = local eclipse call; 0 = normal (global) call

    bool eb_finished; // true if the loop run on consecutive calls is finished
    bool eb_finished2;
    int eb_numecl; // number of eclipses of the year;
    int eb_eclselect; // eclipse selected for detailed calculation
    int eb_lastyear; // last year for which moon phases were calculated
    double eb_lasttz; // last used timezone
    double eb_lastdlt; // last delta-t used
    double eb_cstep; // step width in minutes used for central eclipse output
    double eb_eclmjd[GBL_ECLBUF]; // the MJD's of the middle of the eclipses
    double eb_magnitude[GBL_ECLBUF]; // magnitude of respective eclipse
    int eb_phase[GBL_ECLBUF]; // phase of the eclipse. 0 if no eclipse,
                              // 1 partial Sun, 2 non-central annular, 3 non-central total,
                              // 4 annular, 5 total, 6 annual/total  Sun
                              // -1 partial penumbral Moon, -2 penumbral Moon,
                              // -3 partial Moon, -4 total Moon.
    int eb_nphase; // number of phases for eclipse details
    int eb_spp[4]; // kind of eclipse phase i
    double eb_spt[4]; // start time in MJD for phase i
    double eb_ept[4]; // end time in MJD for phase i
    int eb_lccnt; // = 0 not visible, 1,2 = first rise/set; 3,4 second r/s
    double eb_lcb1, eb_lcb2, eb_lce1, eb_lce2; // rise and set times (up to 2 possible)
    double eb_jdmaxps; // MJD of maximum phase
    double eb_maxps; // value of maximum phase
    double eb_maxelv; // elevation at maximum phase
    double eb_ltotb; // begin of totality/annularity at local position
    double eb_ltote; // end of totality/annularity at local position
    int eb_cphs; // phase of the central eclipse for center line plotting
    double eb_clat; // current latitude of center line (in decimal degrees)
    double eb_clng; // current longitude of center line (in decimal degrees)
    double eb_cmxlat; // latitude of maximum eclipse (in decimal degrees)
    double eb_cmxlng; // longitude of maximum eclipse (in decimal degrees)
    double eb_jdstart; // (global) start jd of eclipse
    double eb_jdstop; // (global) end jd of eclipse
    double eb_lastjd; // last used MJD for eclipse calcs
    double eb_dpb; // Base value for diameter of penumbra
    double eb_dpd; // delta value for diameter of penumbra
    double eb_penangle; // factor for multiplying the penumbra angle (1.0 for normal borders)
    int eb_penamode; // mode for using eb_penangle
    Vec3 eb_ubm; // Penumbra (or Umbra or Moon) base vector
    Vec3 eb_ube; // Shadow base vector for upper boundary
    Vec3 eb_udm; // Penumbra base delta vector
    Vec3 eb_ude; // Shadow delta vector for upper boundary
    Vec3 eb_lbe; // Shadod base vector for lower boundary
    Vec3 eb_lde; // Shadow delta vector for lower boundary
};

#endif // __eclsolar_h sentry.
