/***************************************************************************
                          ksmoon.h  -  K Desktop Planetarium
                             -------------------
    begin                : Sun Aug 26 2001
    copyright            : (C) 2001 by Jason Harris
    email                : kstars@30doradus.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#pragma once

#include "ksplanetbase.h"
#include "dms.h"

class KSSun;

/**
 * @class KSMoon
 * @short Provides necessary information about the Moon.
 * A subclass of SkyObject that provides information
 * needed for the Moon.  Specifically, KSMoon provides a moon-specific
 * findPosition() function.  Also, there is a method findPhase(), which returns
 * the lunar phase as a floating-point number between 0.0 and 1.0.
 *
 * @author Jason Harris
 * @version 1.0
 */
class KSMoon : public KSPlanetBase
{
  public:
    using KSPlanetBase::findPhase;

    /** Default constructor. Set name="Moon". */
    KSMoon();
    /** Copy constructor */
    KSMoon(const KSMoon &o);

    ~KSMoon() override;

    KSMoon *clone() const override;
    SkyObject::UID getUID() const override;

    /**
     * Determine the phase angle of the moon, and assign the appropriate moon image
     * @param Sun a KSSun pointer with coordinates updated to the time of computation.
     * If not supplied, the sun is retrieved via KStarsData
     * @note Overrides KSPlanetBase::findPhase()
     */
    void findPhase(const KSSun *Sun = nullptr);

    /** @return the illuminated fraction of the Moon as seen from Earth */
    double illum() const { return 0.5 * (1.0 - cos(Phase * dms::PI / 180.0)); }

    /** @return a short string describing the moon's phase */
    QString phaseName() const;

    /** reimplemented from KSPlanetBase */
    bool loadData() override;

    /** @return iPhase, which is used as a key to find the right image file */
    inline short int getIPhase() const { return iPhase; }

    /**
     * Reimplemented from KSPlanetBase, this function employs unique algorithms for
     * estimating the lunar coordinates.  Finding the position of the moon is
     * much more difficult than the other planets.  For one thing, the Moon is
     * a lot closer, so we can detect smaller deviations in its orbit.  Also,
     * the Earth has a significant effect on the Moon's orbit, and their
     * interaction is complex and nonlinear.  As a result, the positions as
     * calculated by findPosition() are only accurate to about 10 arcseconds
     * (10 times less precise than the planets' positions!)
     * @short moon-specific coordinate finder
     * @param num KSNumbers pointer for the target date/time
     * @note we don't use the Earth pointer here
     */
    bool findGeocentricPosition(const KSNumbers *num, const KSPlanetBase *) override;

    /**
     * @brief updateMag calls findMagnitude() to calculate current magnitude of moon
     * according to current phase. This function is required to perform findMagnitude()
     * from any where in Kstars
     */
    void updateMag() { findMagnitude(nullptr); }

    void initPopupMenu(KSPopupMenu *pmenu) override;

  private:
    void findMagnitude(const KSNumbers *) override;

    static bool data_loaded;
    static int instance_count;

    /**
     * @class MoonLRData
     * @short Moon Longitude and radius data object
     * Encapsulates the Longitude and radius terms of the sums
     * used to compute the moon's position.
     */
    struct MoonLRData
    {
        int nd { 0 };
        int nm { 0 };
        int nm1 { 0 };
        int nf { 0 };
        double Li { 0 };
        double Ri { 0 };
    };

    static QList<MoonLRData> LRData;

    /**
     * @class MoonBData
     * Encapsulates the Latitude terms of the sums used to compute the moon's position.
     * @short Moon Latitude data object
     */
    struct MoonBData
    {
        int nd { 0 };
        int nm { 0 };
        int nm1 { 0 };
        int nf { 0 };
        double Bi { 0 };
    };

    static QList<MoonBData> BData;
    unsigned int iPhase { 0 };
    KSSun *defaultSun=nullptr;
};
