#pragma ident "$Id: GloEphemerisStore.hpp 3140 2012-06-18 15:03:02Z susancummins $"

/**
 * @file GloEphemerisStore.hpp
 * Get GLONASS broadcast ephemeris data information
 */

#ifndef GPSTK_GLOEPHEMERISSTORE_HPP
#define GPSTK_GLOEPHEMERISSTORE_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
//
//  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2011
//
//============================================================================


#include <iostream>
#include "XvtStore.hpp"
#include "GloEphemeris.hpp"
#include "Rinex3NavData.hpp"
#include "PZ90Ellipsoid.hpp"
#include "Vector.hpp"
#include "YDSTime.hpp"
#include "TimeSystemCorr.hpp"


namespace gpstk
{

      /** @addtogroup ephemstore */
      /** @addtogroup ephemcalc */

      //@{

      // First, let's declare some useful type definitions

   typedef std::map<CommonTime, GloEphemeris> TimeGloMap;

   typedef std::map<SatID, TimeGloMap> GloEphMap;

      /**
       * This adds the interface to get GLONASS broadcast ephemeris information
       */
   class GloEphemerisStore : public XvtStore<SatID>
   {
   public:

         /// Default constructor
      GloEphemerisStore()
         throw()
         : initialTime(CommonTime::END_OF_TIME),
           finalTime(CommonTime::BEGINNING_OF_TIME),
           step(1.0), checkHealthFlag(false)
      { };


         /** Common constructor
          *
          * @param rkStep     Runge-Kutta integration step in seconds.
          * @param checkHealth   Enable or disable the use of the health bit.
          */
      GloEphemerisStore( double rkStep,
                         double checkHealth )
         throw()
         : initialTime(CommonTime::END_OF_TIME),
           finalTime(CommonTime::BEGINNING_OF_TIME),
           step(rkStep), checkHealthFlag(checkHealth)
      { };


         /// Destructor
      virtual ~GloEphemerisStore() {};


         /// Add ephemeris information from a Rinex3NavData object.
         /// @return true unless the data was not added.
      bool addEphemeris(const Rinex3NavData& data)
         throw();


         /** Returns the position, velocity and clock offset of the indicated
          *  satellite in ECEF coordinates (meters) at the indicated time,
          *  in the PZ-90 ellipsoid.
          * 
          *  @param[in] sat   Satellite's identifier
          *  @param[in] epoch Time to look up
          * 
          *  @return the Xvt of the object at the indicated time
          * 
          *  @throw InvalidRequest If the request can not be completed for any
          *  reason, this is thrown. The text may have additional information
          *  as to why the request failed.
          */
      Xvt getXvt( const SatID& sat,
                  const CommonTime& epoch ) const
         throw( InvalidRequest );


         /// Get integration step for Runge-Kutta algorithm.
      double getIntegrationStep() const
      { return step; };


         /** Set integration step for Runge-Kutta algorithm.
          *
          * @param rkStep  Runge-Kutta integration step in seconds.
          */
      GloEphemerisStore& setIntegrationStep( double rkStep )
      { step = rkStep; return (*this); };


         /// Get whether satellite health bit will be used or not.
      bool getCheckHealthFlag() const
      { return checkHealthFlag; };


         /** Set whether satellite health bit will be used or not.
          *
          * @param checkHealth   Enable or disable the use of the health bit.
          */
      GloEphemerisStore& setCheckHealthFlag( bool checkHealth )
      { checkHealthFlag = checkHealth; return (*this); };


         /** A debugging function that outputs in human readable form,
          *  all data stored in this object.
          * 
          * @param[in] s      The stream to receive the output; defaults to cout
          * @param[in] detail The level of detail to provide
          *
          * @warning GLONASS position, velocity and acceleration information are
          * given in km, km/s and km/(s*s), respectively.
          */
      virtual void dump(std::ostream& s = std::cout, short detail = 0) const
         throw();


         /** Edit the dataset, removing data outside the indicated time interval
          * 
          * @param[in] tmin   Defines the beginning of the time interval
          * @param[in] tmax   Defines the end of the time interval
          */
      virtual void edit( const CommonTime& tmin,
                         const CommonTime& tmax = CommonTime::END_OF_TIME )
         throw();


         /// Clear the dataset, meaning remove all data
      virtual void clear(void) throw()
      { pe.clear();
        initialTime = CommonTime::END_OF_TIME;
        finalTime = CommonTime::BEGINNING_OF_TIME;
        return;
      };


         /// Return time system (NB assumed always to be GLONASS)
      virtual TimeSystem getTimeSystem(void) const throw()
      { return TimeSystem::GLO; }

         /** Determine the earliest time for which this object can successfully
          *  determine the Xvt for any object.
          *
          * @return The initial time.
          *
          * @throw InvalidRequest This is thrown if the object has no data.
          */
      virtual CommonTime getInitialTime() const
         throw(InvalidRequest);


         /** Determine the latest time for which this object can successfully
          *  determine the Xvt for any object.
          *
          * @return The final time.
          *
          * @throw InvalidRequest This is thrown if the object has no data.
          */
      virtual CommonTime getFinalTime() const
         throw(InvalidRequest);


         /// Return true if velocity data is present in the store. GLONASS
         /// ephemeris data always include velocity.
      virtual bool hasVelocity() const throw()
      { return true; };


         /// Return true if the given SatID is present in the store
      virtual bool isPresent(const SatID& id) const throw();

         /// Return the number of satellites present in the store
      int size(void) const throw()
      { return pe.size(); }


         /** Find the corresponding GLONASS ephemeris for the given epoch.
          *
          * @param sat     SatID of satellite of interest.
          * @param epoch   time with which to search for ephemeris.
          *
          * @return a reference to the desired ephemeris.
          * @throw InvalidRequest object thrown when no ephemeris is found.
          */
      const GloEphemeris& findEphemeris( const SatID& sat,
                                         const CommonTime& epoch ) const
         throw( InvalidRequest );


         /** Find the corresponding GLONASS ephemeris for the given epoch.
          *
          * @param sat SatID of satellite of interest.
          * @param t time with which to search for ephemeris.
          *
          * @return a reference to the desired ephemeris.
          * @throw InvalidRequest object thrown when no ephemeris is found.
          *
          * @note This method is added for consistency with classes
          * GPSEphemerisStore.hpp and GalEphemerisStore.hpp, because in GLONASS
          * the returned ephemeris is ALWAYS the nearest one.
          */
      const GloEphemeris& findUserEphemeris( const SatID& sat,
                                             const CommonTime& t ) const
         throw( InvalidRequest )
      { return findEphemeris(sat, t); };


         /** Find the corresponding GLONASS ephemeris for the given epoch.
          *
          * @param sat SatID of satellite of interest.
          * @param t time with which to search for ephemeris.
          *
          * @return a reference to the desired ephemeris.
          * @throw InvalidRequest object thrown when no ephemeris is found.
          *
          * @note This method is added for consistency with classes
          * GPSEphemerisStore.hpp and GalEphemerisStore.hpp, because in GLONASS
          * the returned ephemeris is ALWAYS the nearest one.
          */
      const GloEphemeris& findNearEphemeris( const SatID& sat,
                                             const CommonTime& t ) const
         throw( InvalidRequest )
      { return findEphemeris(sat, t); };

      /// Add all ephemerides to an existing list<GloEphemeris>.
      /// @return the number of ephemerides added.
      int addToList( std::list<GloEphemeris>& v ) const
         throw();


   private:


         /// The map of SVs and Xvt's
      GloEphMap pe;


         /// Earliest epoch of data available
      CommonTime initialTime;


         /// Latest epoch of data available
      CommonTime finalTime;


         /// Integration step for Runge-Kutta algorithm (1 second by default)
      double step;


         /// Flag signaling if satellites will be screened out according to
         /// their health bit (by default it is false)
      bool checkHealthFlag;


   };  // End of class 'GloEphemerisStore'

}  // End of namespace gpstk

#endif   // GPSTK_GLOEPHEMERISSTORE_HPP
