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



/**
 * @file FICData.hpp
 * gpstk::FICData - container for the FIC file data.
 */

//============================================================================
//
//  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
//  
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S. 
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software. 
//
//Pursuant to DoD Directive 523024 
//
// DISTRIBUTION STATEMENT A: This software has been approved for public 
//                           release, distribution is unlimited.
//
//=============================================================================






#ifndef FICDATA_HPP
#define FICDATA_HPP

#include <vector>
#include <map>

#include "FFStream.hpp"
#include "FICBase.hpp"
#include "EngEphemeris.hpp"
#include "AlmOrbit.hpp"
#include "CommonTime.hpp"

namespace gpstk
{
      /// This gets thrown if we don't have the right data for cast operations.
      /// @ingroup exceptionclass
   NEW_EXCEPTION_CLASS(WrongBlockNumber, gpstk::Exception);
      
      /// This gets thrown if we don't have the wrong format block is used.
      /// @ingroup exceptionclass
   NEW_EXCEPTION_CLASS(WrongBlockFormat, gpstk::Exception);

      /**
       * This does all the grunt-work in reading/decoding 
       * FIC-formatted files (ASCII And Binary).
       * 
       * \sa fic_test.cpp, fic_read_write.cpp, fica_test.cpp for examples.
       *
       * \sa FICStream, FICAStream, and FICHeader.
       */
   class FICData : public FICBase
   {
   public:
         /// Default constructor
      FICData() : blockNum(0) {}

         /*
          * Construct a FICData from an EngEphemeris object.
          * @param engEph the EngEphemeris to copy
          */
         // if you uncomment this, fix the doxygen comment above as well
         //FICData(const EngEphemeris& engEph) throw();
      
         /// Destructor
      virtual ~FICData() {}
         /**
          * Returns whether or not this FICData is valid.
          * Checks the sizes of the f, i, and c vectors using different
          * metrics for each FIC Record Type.
          * See the ICD-GPS-200 for complete details.
          */
      bool isValid() const;      

         //! This class is "data" so this function always returns "true". 
      virtual bool isData() const {return true;}

         /**
          * Debug output function. 
          * Dump the contents of each of the f, i, and c vectors to the 
          * given ostream \c s.
          */ 
      virtual void dump(std::ostream& s) const;

         /**
          * Prints the FIC data in a nice format, labeling all the important
          * subframes and quantities.
          */
      void prettyDump(std::ostream& os) const;

         /**
          * Sets the transmit time of the current block of data.
          * @param dt (output) a CommonTime object containing the transmit time
          * @return if the process was sucessful, return true, else false
          */
      bool getTransmitTime(CommonTime& dt) const;

         /**  
          * Cast *this to an Engineering Ephemeiris Object.
          * @return the constructed EngEphemeris object
          */
      operator EngEphemeris() const throw(WrongBlockNumber);

         /**
          * cast *this into an AlmOrbit, only for block 62s
          * @return the constructed AlmOrbit object
          */
      operator AlmOrbit() const throw(WrongBlockNumber);

         /// Generates a unique key for this FIC data so that redundant
         /// messages can be filtered.  Uses the same criteria
         /// as other generateUniqueKey() functions.
         /// Currently only for blocks 9 and 62 (otherwise it throws)
         /// @sa NavSF::generateUniqueKey()
         /// @sa EngEphData::generateUniqueKey()
      std::string generateUniqueKey() const throw(WrongBlockNumber,
                                                  WrongBlockFormat);

        /***
         * Standard equality operator.
         */
      bool operator==(const FICData& rhs);

     /***
      * Returns a human readable string describing an entry
      * in a FIC vector.
      * @param block Block number: 9, 109, 62, 162.
      * @param type Which vector type. 'f' for floating, 'i' for integer, 'c' for character.
      * @param indx The number of the element in the vector to describe. Starts with zero.
      * @return String describing the entry.
      */
      std::string getElementLabel(char type, size_t indx) const;
  

           /// @name data members
         //@{
      static const std::string blockString; ///< "BLK " record header constsnt
      long blockNum;             ///< Block number for this FIC Record.
      std::vector<double> f;          ///< Vector of floating point numbers.
      std::vector<long> i;            ///< Vector of long integers.
      std::vector<char> c;            ///< Vector of characters.
         //@}

   protected:
         //! Writes this record to the stream \a s.
      virtual void reallyPutRecord(FFStream& s) const 
         throw(std::exception, gpstk::StringUtils::StringException, 
               gpstk::FFStreamError);
         /**
          * Read a "FICData" record from the FFStream \c s. 
          * If an error is encountered, the function will 
          * return the stream to its original state and mark its fail-bit.
          * @throws FFStreamError when exceptions(failbit) is set and
          *  a read or formatting error occurs.  This also resets the
          *  stream to its pre-read position.
          */
      virtual void reallyGetRecord(FFStream& s)
         throw(std::exception, gpstk::StringUtils::StringException, 
               gpstk::FFStreamError);

   private:
         /// nicely prints the data from a block 9 record
      void prettyDump9(std::ostream& o) const;
         /// nicely prints the data from a block 109 record
      void prettyDump109(std::ostream& o) const;
         /// nicely prints the data from a block 62 record
      void prettyDump62(std::ostream& o) const;
         /// nicely prints the data from a block 162 record
      void prettyDump162(std::ostream& o) const;

         /// nicely prints the time
      void timeDisplay( std::ostream & os, const char * legend,
                        const short week, const double SOW, 
                        const short headerFlag ) const;

         /// shortcut is used in prettyDump9 to convert the
         /// HOW word time to D:H:M:S and print it out.
      void shortcut(std::ostream & os, const double HOW ) const;
   };
   
}

#endif // FICDATA_HPP

