/***************************************************************************
                          distance.h  -  general distance representation
                             -------------------
    begin                : Sat Jul 20 2002
    copyright            : (C) 2002 by Andre Somers
    email                : andre@kflog.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 DISTANCE_H
#define DISTANCE_H

#include <qstring.h>

/** @short Abstract Distance
  *
  * An object of this class represents a distance. It can express this distance in a number of major formats.
  * It also features a couple of static methods to convert from the set unit to meters or to display a
  * distance in the currently selected unit.
  *
  * @author Heiner Lamprecht
  */

const double mFromKm=1000.0; //1000.0 meters in 1 km.
const double mFromMile=1609.3; //1609.3 meters in a mile
const double mFromNMile=1852.0; //1852 meters in a nautical mile
const double mFromFeet=0.3048; //a foot is a bit more than 30 cm

class Distance {
public: 

public:
  enum distanceUnit{meters=0, feet=1, kilometers=2, miles=3, nautmiles=4};

public:
  Distance();
  /**
   * Constructor
   *
   * Initializes the object to meters.
   */
  Distance(int meters);
  /**
   * Constructor
   *
   * Initializes the object to meters.
   */
  Distance(double meters);
  /**
   * Copy constructor
   */
  Distance(const Distance& dst);
  /**
   * Destructor
   */
  ~Distance();

  /**
   * Set the distance in meters
   */
  void setMeters(int meters);
  /**
   * Set distance in feet
   */
  void setFeet (int feet);
  /**
   * Set the distance in meters
   */
  void setMeters(double meters);
  /**
   * Set distance in feet
   */
  void setFeet (double feet);
  /**
   * Get distance in feet
   */
  double getFeet() const;
  /**
   * Returns distance in meters
   */
  double getMeters() const;
  /**
   * implements == operator for distance
   */
  bool operator == (const Distance& x) const;
  /**
   * implements != operator for distance
   */
  bool operator != (const Distance& x) const;
  /**
   * implements minus operator
   */
  Distance operator - (const Distance& op) const;
  /**
   * implements divide operator
   */
  double operator / (const Distance& op) const;
  /**
   * implements multiply operator
   */
  inline Distance operator * (const int& op) const {return Distance(_dist * op);};
  /**
   * implements multiply operator
   */
  inline Distance operator * (const double& op) const {return Distance(_dist * op);};
  /**
   * Represent a distance as a string.
   *
   * @return A string containing the distance in the set unit (see @ref setUnit).
   * The string that identifies the unit used is added if withUnit is true.
   *
   * example:
   * <pre>
   *    getText(1,true,1)
   * </pre>
   * with the distance unit set to feet would return "3.2 ft".
   *
   * @param meter The distance expressed in meters
   * @param withUnit determines if the unit-string is included in the output
   * @param precision number of digits after the decimal separator
   */
  static QString getText(double meters, bool withUnit, int precision=1);
  /**
   * Basicly the same as @ref getText, but returns the internally stored distance.
   */
  QString getText(bool withUnit, uint precision=1, uint chopOrder=0) const;
  /**
   * Sets the unit for distances.
   */
  static void setUnit(distanceUnit unit);
  /**
   * Converts a distance from the current unit set with @ref setUnit to meters.
   */
  static double convertToMeters(double dist);

  /**
   * Sets the distance in kilometers
   */
  void setKilometers(double km);
  /**
   * Sets the distance in kilometers
   */
  void setKilometers(int km);
  /**
   * sets the distance in Nauticle miles
   */
  void setNautMiles(double value);
  /**
   * Sets the distance in miles
   */
  void setMiles(double value);
  /**
   * Return the currently set unit for distances
   */
  static distanceUnit getUnit();
  /**
   * Returns the distance in Nautical Miles
   */
  double getNautMiles() const;
  /**
   * returns the distance in miles
   */
  double getMiles() const ;
  /**
   * returns the distance in kilometers
   */
  double getKilometers() const;
  /**
   * Sets the distance to be invalid
   */
  inline void setInvalid() {_isValid=false; _dist=0;};
  /**
   * Gets if the distance is valid
   */
  inline bool isValid() {return _isValid;};
  
protected: // Private attributes
  /**
   * internal representation (in meters)
   */
  double _dist;
  /**
   * value valid?
   */
  bool _isValid;

private:
  static distanceUnit _distanceUnit;
};

#endif
