/***************************************************************************
                          deepskycomponent.h  -  K Desktop Planetarium
                             -------------------
    begin                : 2005/15/08
    copyright            : (C) 2005 by Thomas Kabelmann
    email                : thomas.kabelmann@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 DEEPSKYCOMPONENT_H
#define DEEPSKYCOMPONENT_H

#include "typedef.h"

#include <QObject>
#include "skycomponent.h"
#include "skylabel.h"
#include "ksparser.h"

#define NNGCFILES 14

class QColor;
class SkyMap;
class KSNumbers;
class DeepSkyObject;
class SkyPoint;
class SkyMesh;
class SkyLabeler;

// NOTE: Although the following symbol has nothing to do with line
// number in any file, we use this name to keep consistency in naming
// conventions with StarComponent
#define MAX_LINENUMBER_MAG 90

typedef QVector< DeepSkyObject*>    DeepSkyList;
typedef QHash< int, DeepSkyList*>   DeepSkyIndex;

/**
 * @class DeepSkyComponent
 * Represents the deep sky objects separated by catalogs. 
 * Custom Catalogs are a standalone component.
 * @note this Component is similar to ListComponent, but 
 * the deep sky objects are stored in four separate QLists.
 * @author Thomas Kabelmann
 * @version 0.1
 */
class DeepSkyComponent: public SkyComponent
{
public:

    explicit DeepSkyComponent( SkyComposite* );

    ~DeepSkyComponent();

    virtual void draw( SkyPainter *skyp );

    /** @short draw all the labels in the prioritized LabelLists and then
     * clear the LabelLists.
     */
    void drawLabels();

    /**
     * @short Update the sky positions of this component.  FIXME -jbb does nothing now
     *
     * This function usually just updates the Horizontal (Azimuth/Altitude)
     * coordinates of the objects in this component.  If the KSNumbers* 
     * argument is not NULL, this function also recomputes precession and
     * nutation for the date in KSNumbers.
     * @p num Pointer to the KSNumbers object
     * @note By default, the num parameter is NULL, indicating that 
     * Precession/Nutation computation should be skipped; this computation 
     * is only occasionally required.
     */
    virtual void update( KSNumbers *num=0 );

    /**
     * @short Search the children of this SkyComponent for 
     * a SkyObject whose name matches the argument
     * @p name the name to be matched
     * @return a pointer to the SkyObject whose name matches
     * the argument, or a NULL pointer if no match was found.
     */
    virtual SkyObject* findByName( const QString &name );

    /**
     * @short Searches the region(s) and appends the SkyObjects found to the list of sky objects
     *
     * Look for a SkyObject that is in one of the regions 
     * If found, then append to the list of sky objects
     * @p list list of SkyObject to which matching list has to be appended to
     * @p region defines the regions in which the search for SkyObject should be done within
     * @return void
     */
    virtual void objectsInArea( QList<SkyObject*>& list, const SkyRegion& region );

    virtual SkyObject* objectNearest( SkyPoint *p, double &maxrad );

    const QList<DeepSkyObject*>& objectList() const { return m_DeepSkyList; }

    void clear();

    bool selected();

private:
    /**
     * @short Read the ngcic.dat deep-sky database.
     * Parse all lines from the deep-sky object catalog files. Construct a DeepSkyObject
     * from the data in each line, and add it to the DeepSkyComponent.
     * 
     * Each line in the file is parsed according to column position:
     * @li 0        IC indicator [char]  If 'I' then IC object; if ' ' then NGC object
     * @li 1-4      Catalog number [int]  The NGC/IC catalog ID number
     * @li 6-8      Constellation code (IAU abbreviation)
     * @li 10-11    RA hours [int]
     * @li 13-14    RA minutes [int]
     * @li 16-19    RA seconds [float]
     * @li 21       Dec sign [char; '+' or '-']
     * @li 22-23    Dec degrees [int]
     * @li 25-26    Dec minutes [int]
     * @li 28-29    Dec seconds [int]
     * @li 31       Type ID [int]  Indicates object type; see TypeName array in kstars.cpp
     * @li 33-36    Type details [string] (not yet used)
     * @li 38-41    Magnitude [float] can be blank
     * @li 43-48    Major axis length, in arcmin [float] can be blank
     * @li 50-54    Minor axis length, in arcmin [float] can be blank
     * @li 56-58    Position angle, in degrees [int] can be blank
     * @li 60-62    Messier catalog number [int] can be blank
     * @li 64-69    PGC Catalog number [int] can be blank
     * @li 71-75    UGC Catalog number [int] can be blank
     * @li 77-END   Common name [string] can be blank
     * @return true if data file is successfully read.
     */
    void loadData();

    void clearList(QList<DeepSkyObject*>& list);

    void mergeSplitFiles();

    void drawDeepSkyCatalog( SkyPainter *skyp, bool drawObject, DeepSkyIndex* dsIndex,
                             const QString& colorString, bool drawImage = false);

    QList<DeepSkyObject*> m_DeepSkyList;
    QList<DeepSkyObject*> m_MessierList;
    QList<DeepSkyObject*> m_NGCList;
    QList<DeepSkyObject*> m_ICList;
    QList<DeepSkyObject*> m_OtherList;

    LabelList*     m_labelList[  MAX_LINENUMBER_MAG + 1 ];
    bool           m_hideLabels;
    double         m_zoomMagLimit;


    SkyMesh* m_skyMesh;
    DeepSkyIndex m_DeepSkyIndex;
    DeepSkyIndex m_MessierIndex;
    DeepSkyIndex m_NGCIndex;
    DeepSkyIndex m_ICIndex;
    DeepSkyIndex m_OtherIndex;

    void appendIndex( DeepSkyObject *o, DeepSkyIndex* dsIndex, Trixel trixel );

    QHash<QString, DeepSkyObject*> nameHash;

    /**
     *@short adds a label to the lists of labels to be drawn prioritized
     *by magnitude.
     */
    void addLabel( const QPointF& p, DeepSkyObject *obj );

};

#endif
