/***********************************************************************
**
**   reachablelist.h 
**
**   This file is part of Cumulus.
**
************************************************************************
**
**   Copyright (c):  2004 by Eckhard Völlm 
**
**   This file is distributed under the terms of the General Public
**   Licence. See the file COPYING for more information.
**
**   $Id: reachablelist.h,v 1.22 2005/02/28 10:23:51 andre Exp $
**
***********************************************************************/


// Purpose: helds and keeps the list
#ifndef REACHABLELIST_H
#define REACHABLELIST_H

#include <qobject.h>
#include <qpoint.h>
#include <qlist.h>
#include <qmap.h>

#include "mapmatrix.h"
#include "singlepoint.h"
#include "distance.h"
#include "mapcontents.h"
#include "altitude.h"
#include "vector.h"
#include "speed.h"
#include "wp.h"

//class ReachableList;
enum reachable{no,belowSavety,yes};

// class for one entry in ReachableList
class ReachablePoint
{
public:
    ReachablePoint(QString name,
                   QString icao,
		   QString description,
		   bool orignAfl,
                   int type,
                   double frequency,
                   WGSPoint pos,
                   QPoint ppos,
                   int elevation,
                   Distance distance,
                   int bearing,
                   Altitude arrivAlt,
                   int rwDir, 
                   int rwLen,
                   int rwSurf,
                   bool rwOpen );


    ReachablePoint::ReachablePoint(wayPoint *wp,
				   bool orignAfl,
                                   Distance distance,
                                   int bearing,
                                   Altitude arrivAlt );

    inline Distance getDistance() { return _distance; };
    inline void     setDistance(Distance d) { _distance=d; };
    inline QString getName() { return _wp->name; };
    inline QString getDescription() { return _wp->description; };
    inline void setOrignAfl(bool o) { _orignAfl=o; };
    inline bool isOrignAfl() { return _orignAfl; };
    inline int getElevation() { return _wp->elevation; };
    inline int getType() { return _wp->type; };
    inline Altitude getArrivalAlt() { return _arrivalAlt; };
    inline int getBearing() { return _bearing; };
    inline void setBearing(int b) { _bearing=b; };
    inline  wayPoint * getWaypoint() { return _wp; };
    inline void setArrivalAlt( Altitude alt ) { _arrivalAlt = alt; };
    ReachablePoint::~ReachablePoint();
    reachable getReachable();
    
private:
    bool         _orignAfl; // orign is from airfield list
    wayPoint     *_wp;
    Distance     _distance;
    int          _bearing;
    Altitude     _arrivalAlt;
};


/**
 * @short A list of reachable points
 * @author Eckhard Völlm
 * The list of reachables points maintains the distance and arrival
 * altitudes for points in the region of the current position.
 */
class ReachableList: public QObject, QList<ReachablePoint>
{
    Q_OBJECT
    // public slots:
public:

    ~ReachableList();
    ReachableList(QObject *parent);
signals: // Signals
    void newReachList();
public:
    // The one and only Instance
    // static ReachableList * instance( void );
    /**
     * calculates scheduled glide path and full list
     */
    void calculate(bool always);
    /**
     * force to calculate full list
     */
    void calculateFullList();
    /**
     * add glider airport or waypoint site (if not out of reach) to the list
     */
    void addItemsToList(enum MapContents::MapContentsListID item);
    /**
     * print list via qDebug interface
     */
    void show();
    /**
     * compares two entries to sort list either by distance or arrival alt
     */
    int compareItems (QCollection::Item i1, QCollection::Item i2);
    /**
     * returns number of sites
     */
    int getNumberSites() ;
    /**
     * returns site at index (max =  getNumberSites()-1)
     */
    ReachablePoint *getSite( int index );
    QList<ReachablePoint> *getList() { return this; };
    /**
     * returns configured maximum number of sites in list
     */
    inline int getMaxNrOfSites() { return _maxNumberOfSites; };
    /**
     * @returns the colour indicating if the point with the given name
     * is reachable.
     */
    //static QColor getReachColor( QString name );
    static QColor getReachColor( QPoint position );
    
    /**
     * @returns an enum value indicating if the point with the given name
     * is reachable.
     */
    //static reachable getReachable( QString name );
    static reachable getReachable( QPoint position );
    /**
     * @returns an integer with the arrival altitude. If the point is not found, -9999 is returned.
     */
    //static int getArrivalAlt( QString name );
    static int getArrivalAlt( QPoint position );
    /**
     * @returns an Altitude object with the arrival altitude. If the point is not found, an invalid Altitude is returned
     */
    //static Altitude getArrivalAltitude( QString name );
    static Altitude getArrivalAltitude( QPoint position );
    /**
     * @returns a Distance object representing the point. If the point is not found, an invalid Distance is returned
     */
    //static Distance getDistance( QString name );
    static Distance getDistance( QPoint position );
    /**
     * @returns The safety altitude in meters
     */
     static int getSafetyAltititude() {return safetyAlt;};
     
private:
    void calculateGlidePath();
    void calcInitValues();
    /**
     * Removes double entries from the list.
     * Double entries can occur when a point is a waypoint as well as an
     * airfield. In this case, the one with the longer name is prefered.
     * This function ASSUMES THE LIST IS SORTED!
     */
    void removeDoubles();
    static const QString coordinateString(QPoint position) {return QString("%1.%2").arg(position.x()).arg(position.y());};
    // static ReachableList *theInstance;
    QPoint      lastPosition;
    double      lastAltitude;
    Vector      lastWind;
    Speed       lastMc;
    double      _maxReach;
    int         tick;
    bool        modeAltitude;
    bool        initValuesOK;
    bool        isOn;
    int          _maxNumberOfSites;
    static QMap<QString, int> arrivalAltMap;
    static QMap<QString, Distance> distanceMap;
    static int safetyAlt;
};

#define REACHABLELIST ReachableList::instance() 

#endif
