//============================================================================
//
//  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 3.0 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.
//
//=============================================================================

/// @file TimeString.hpp  print and scan using all TimeTag derived classes.

#ifndef GPSTK_TIMESTRING_HPP
#define GPSTK_TIMESTRING_HPP

#include "TimeTag.hpp"
#include "CommonTime.hpp"

namespace gpstk
{
      /// @ingroup TimeHandling
      //@{

      /**
       * The TimeTag classes are the "interface" for CommonTime, so
       * when printing a CommonTime object, each of the TimeTag printf()
       * functions are called to handle the print identifiers that it
       * recognizes.  The following is a list of these identifiers and
       * the meaning for each:
       *
       * - ANSITime:
       *   - K     integer seconds since Unix Epoch (00:00, Jan 1, 1970 UTC)
       *
       * - CivilTime:
       *   - Y     integer 4-digit year
       *   - y     integer 2-digit year
       *   - m     integer month
       *   - b     abbreviated month name string (e.g. "Jan")
       *   - B     full month name string (e.g. "January")
       *   - d     integer day-of-month
       *   - H     integer hour-of-day
       *   - M     integer minute-of-hour
       *   - S     integer second-of-minute
       *   - f     float second-of-minute
       *
       * - Week (GPS/BDS/GAL/QZS):
       *   - E     integer GPS Epoch
       *   - F     integer full (13-bit) GPS Week
       *   - G     integer mod (10-bit) GPS Week
       *   - R     integer BDS Epoch
       *   - D     integer full BDS Week
       *   - e     integer mod BDS Week
       *   - T     integer GAL Epoch
       *   - L     integer full GAL Week
       *   - l     integer mod GAL Week
       *   - V     integer QZS Epoch
       *   - h     integer full QZS Week
       *   - i     integer mod QZS Week - same as I
       *   - X     integer IRNSS Epoch
       *   - O     integer IRNSS week
       *   - o     integer mod INRSS Week 
       *
       * - WeekSecond (GPS/BDS/GAL/QZS):
       *   - w     integer GPS day-of-week
       *   - g     float GPS second-of-week
       *
       * - GPSWeekZcount:
       *   - w     integer GPS day-of-week
       *   - z     integer GPS Z-count
       *   - Z     integer GPS Z-count
       *   - c     integer 29-bit Z-count
       *   - C     integer 32-bit Z-count
       *
       * - JulianDate:
       *   - J     float Julian Date
       *
       * - MJD:
       *   - Q     float Modified Julian Date
       *
       * - UnixTime:
       *   - U     integer seconds since Unix Epoch (00:00, Jan 1, 1970 UTC)
       *   - u     integer microseconds
       *
       * - PosixTime:
       *   - W     integer seconds
       *   - N     integer nanoseconds
       *
       * - YDSTime:
       *   - Y     integer 4-digit year
       *   - y     integer 2-digit year
       *   - j     integer day-of-year
       *   - s     integer second-of-day
       *
       * - Common Identifiers:
       *   - P     string TimeSystem to compare with TimeSystem::Systems enum
       */
   std::string printTime( const CommonTime& t,
                          const std::string& fmt );

      /// This function converts the given CommonTime into the templatized
      /// TimeTag object, before calling the TimeTag's printf(fmt).  If
      /// there's an error in conversion, it instead calls printf(fmt, true)
      /// to signal a conversion error.
   template <class TimeTagType>
   std::string printAs( const CommonTime& t,
                        const std::string& fmt )
   {
      TimeTagType ttt;
      try
      {
         ttt.convertFromCommonTime(t);
         return ttt.printf(fmt);
      }
      catch (InvalidRequest& ir)
      {
         return ttt.printError(fmt);
      }
   }

      /// This function determines if the given format includes items
      /// that would be printed by the TimeTag's printf(fmt); NB
      /// except 'P' (system).  In other words, determine if
      /// printAs<T>(t,fmt) will not modify the string.
   template <class TimeTagType>
   bool willPrintAs( const std::string& fmt )
   {
      TimeTagType ttt;
      std::string chars = ttt.getPrintChars();
      for(size_t i=0; i<chars.length(); i++) {
         if(chars[i] == 'P') continue;
         if(StringUtils::isLike(fmt,TimeTag::getFormatPrefixInt()+chars[i]) ||
            StringUtils::isLike(fmt,TimeTag::getFormatPrefixFloat()+chars[i]))
            return true;
      }
      return false;
   }

      /// Fill the TimeTag object \a btime with time information found in
      /// string \a str formatted according to string \a fmt.
   void scanTime( TimeTag& btime,
                  const std::string& str,
                  const std::string& fmt );

   void scanTime( CommonTime& t,
                  const std::string& str,
                  const std::string& fmt );

      /** This function is like the other scanTime functions except that
       *  it allows mixed time formats.
       *  i.e. Year / 10-bit GPS week / seconds-of-week
       *  The time formats are filled in the following order: GPS Epoch,
       *  year, month, GPS Full Week, GPS 10-bit Week, day-of-week,
       *  day-of-month, day-of-year, 29-bit Zcount, 19-bit Zcount, hour,
       *  minute, second-of-week, second-of-day, second-of-minute.
       *  @note MJD, Julian Date, ANSI time, Unix time, and 32-bit Zcount are
       *  treated as stand-alone types and are not mixed with others if
       *  detected.
       */
   void mixedScanTime( CommonTime& t,
                       const std::string& str,
                       const std::string& fmt );

      //@}

} // namespace

#endif // GPSTK_TIMESTRING_HPP
