/***************************************************************************
                          ksplanet.h  -  K Desktop Planetarium
                             -------------------
    begin                : Sun Jul 22 2001
    copyright            : (C) 2001 by Jason Harris
    email                : jharris@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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef KSPLANET_H_
#define KSPLANET_H_

#include <QVector>
#include <QHash>

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

/** @class KSPlanet
 *A subclass of KSPlanetBase for seven of the major planets in the solar system
 *(Earth and Pluto have their own specialized classes derived from KSPlanetBase).  
 *@note The Sun is subclassed from KSPlanet.
 *
 *KSPlanet contains internal classes to manage the computations of a planet's position.
 *The position is computed as a series of sinusoidal sums, similar to a Fourier
 *transform.  See "Astronomical Algorithms" by Jean Meeus or the file README.planetmath
 *for details.
 *@short Provides necessary information about objects in the solar system.
 *@author Jason Harris
 *@version 1.0
 */
class KSPlanet : public KSPlanetBase {
public:

    /**
     * Constructor.
     * @param s Name of planet
     * @param image_file filename of the planet's image
     * @param c the color for the planet
     * @param pSize physical diameter of the planet, in km
     */
    explicit KSPlanet( const QString &s="unnamed", const QString &image_file=QString(),
                       const QColor & c=Qt::white, double pSize=0 );

    /**
     * Simplified constructor
     * @param n identifier of the planet to be created
     * @see PLANET enum
     */
    explicit KSPlanet( int n );

    virtual KSPlanet* clone() const;
    virtual SkyObject::UID getUID() const;
    
    /**
     * Destructor (empty)
     */
    virtual ~KSPlanet() {}

    /** @short return the untranslated name
     *This is a dirty way to solve a lot of localization-related trouble for the KDE 4.2 release
     *TODO: Change the whole architecture for names later
     */
    QString untranslatedName( void ) const;

    /** @short Preload the data used by findPosition.
    	*/
    virtual bool loadData();

    /** Calculate the ecliptic longitude and latitude of the planet for
    	*the given date (expressed in Julian Millenia since J2000).  A reference
    	*to the ecliptic coordinates is returned as the second object.
    	*@param jm Julian Millenia (=jd/1000)
    	*@param ret The ecliptic coordinates are returned by reference through this argument.
    	*/
    virtual void calcEcliptic(double jm, EclipticPosition &ret) const;

protected:

    bool data_loaded;

    /** Calculate the geocentric RA, Dec coordinates of the Planet.
    	*@note reimplemented from KSPlanetBase
    	*@param num pointer to object with time-dependent values for the desired date
    	*@param Earth pointer to the planet Earth (needed to calculate geocentric coords)
    	*@return true if position was successfully calculated.
    	*/
    virtual bool findGeocentricPosition( const KSNumbers *num, const KSPlanetBase *Earth=NULL );

    /** @class OrbitData
    	*This class contains doubles A,B,C which represent a single term in a planet's
    	*positional expansion sums (each sum-term is A*COS(B+C*T)).
    	*@author Mark Hollomon
    	*@version 1.0
    	*/
    class OrbitData  {
    public:
        /**
        	*Default constructor
        	*/
        OrbitData() : A(0.), B(0.), C(0.) {}
        /**
        	*Constructor 
        	*@param a the A value
        	*@param b the B value
        	*@param c the C value
        	*/
        OrbitData(double a, double b, double c) : A(a), B(b), C(c) {}

        /**
        	*Assignment operator
        	*/
        OrbitData operator= ( const OrbitData o ) { return o; }

        double A, B, C;
    };

    typedef QVector<OrbitData> OBArray[6];

    /** OrbitDataColl contains three groups of six QVectors.  Each QVector is a
    	*list of OrbitData objects, representing a single sum used in computing
    	*the planet's position.  A set of six of these vectors comprises the large
    	*"meta-sum" which yields the planet's Longitude, Latitude, or Distance value.
    	*@author Mark Hollomon
    	*@version 1.0
    	*/
    class OrbitDataColl {
    public:
        /**Constructor*/
        OrbitDataColl();

        OBArray Lon;
        OBArray Lat;
        OBArray Dst;
    };


    /** OrbitDataManager places the OrbitDataColl objects for all planets in a QDict
    	*indexed by the planets' names.  It also loads the positional data of each planet
    	*from disk.
    	*@author Mark Hollomon
    	*@version 1.0
    	*/
    class OrbitDataManager {
    public:
        /** Constructor*/
        OrbitDataManager();

        /** Load orbital data for a planet from disk.
        	*The data is stored on disk in a series of files named 
        	*"name.[LBR][0...5].vsop", where "L"=Longitude data, "B"=Latitude data,
        	*and R=Radius data.
        	*@param n the name of the planet whose data is to be loaded from disk.
        	*@param odc reference to the OrbitDataColl containing the planet's orbital data.
        	*@return true if data successfully loaded
        	*/
        bool loadData( OrbitDataColl &odc, const QString &n);

    private:
        /** Read a single orbital data file from disk into an OrbitData vector.
        *The data files are named "name.[LBR][0...5].vsop", where 
        *"L"=Longitude data, "B"=Latitude data, and R=Radius data.
        *@param fname the filename to be read.
        *@param vector pointer to the OrbitData vector to be filled with these data.
        */
        bool readOrbitData(const QString &fname, QVector<KSPlanet::OrbitData> *vector);

        QHash<QString, OrbitDataColl> hash;
    };

    static OrbitDataManager odm;

private:
    virtual void findMagnitude(const KSNumbers*);
};

#endif
