/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#ifndef _NMM_LOCAL_TIME_HPP
#define _NMM_LOCAL_TIME_HPP

#include "nmm/nmm_prefix.hpp"

#include <string>
#include <time.h>

#include "nmm/nmm_inttypes.hpp"

#include "visibility.hpp"

namespace NMM {
  
  class Time;
 
  /**
   *  @brief Local time
   *
   *  Represents broken down calendar time. This is a wrapper of the C struct 'tm'.
   */
  class DLLEXPORT LocalTime {
  public:
    /**
     *  @brief Default constructor
     */
    LocalTime();

    /**
     *  @brief Constructor
     *  @param time A time value
     *  @param local Create local time
     *
     *  Creates the broken down time representation of the given @a time.
     *  If @a local is true, the broken down time is in local time. Otherwise it is in GMT.
     */
    LocalTime(const Time& time, bool local=true);
    
    /**
     *  @brief Constructor
     *  @param tm_struct C structure representing broken down time
     *
     *  Creates the broken down time directly from the C structure @a tm_struct.
     */
    LocalTime(const struct ::tm& tm_struct);
    
    /**
     *  @brief Copy constructor
     */
    LocalTime(const LocalTime&);
    
    /**
     *  @brief Get second
     *  @return The second of the minute (0~59)
     */
    unsigned getSecond() const;

    /**
     *  @brief Set second
     *  @return The second of the minute (0~59)
     */
    void setSecond(uint8_t s);
    
    /**
     *  @brief Get minute
     *  @return The minute of the hour (0~59)
     */
    unsigned getMinute() const;

    /**
     *  @brief Set minute
     *  @return The minute of the hour (0~59)
     */
    void setMinute(uint8_t m);

    /**
     *  @brief Get hour
     *  @return The hour of the day (0~23)
     */
    unsigned getHour() const;

    /**
     *  @brief Set hour
     *  @return The hour of the day (0~23)
     */
    void setHour(uint8_t h);

    /**
     *  @brief Get day of month
     *  @return The day of the month (1~number of days for this month)
     */
    unsigned getDayOfMonth() const;

    /**
     *  @brief Set day of month
     *  @return The day of the month (1~number of days for this month)
     */
    void setDayOfMonth(uint8_t d);

    /**
     *  @brief Get day of week
     *  @return The day of the month (0~6 where 0=Sunday)
     */
    unsigned getDayOfWeek() const;

    /**
     *  @brief Get day of year
     *  @return The day of the month (0~number of days for this year-1)
     */
    unsigned getDayOfYear() const;
    
    /**
     *  @brief Get month
     *  @return The month of the year (0~11)
     */
    unsigned getMonth() const;

    /**
     *  @brief Set month
     *  @return The month of the year (0~11)
     */
    void setMonth(uint8_t m);
    
    /**
     *  Get GMT offset.
     *  @return The timezone as GMT offset in seconds
     *
     *  Returns the time zone that was used to compute
     *  this broken-down time value, including any adjustment for
     *  daylight saving; it is the number of seconds that you must
     *  add to UTC to get local time.  You can also think of this as
     *  the number of seconds east of UTC.  For example, for U.S.
     *  Eastern Standard Time, the value is `-5*60*60'.
     */
    unsigned getGMTOffset() const;

    /**
     *  Set GMT offset.
     */
    void setGMTOffset(unsigned gmt_offfset);
    
    /**
     *  @brief Get year.
     *  @return The year
     */
    unsigned getYear() const;

    /**
     *  @brief Set year.
     *  @return The year
     */
    void setYear(unsigned int y);

    /**
     *  @brief Check for daylight savings time
     *  @return Daylight savings time flag
     *
     *  This is a flag that indicates whether Daylight Saving Time is
     *  (or was, or will be) in effect at the time described.
     */
    bool isDaylightSavingsTime() const;

    /**
     *  @brief Set for daylight savings time
     *
     *  This is a flag that indicates whether Daylight Saving Time is
     *  (or was, or will be) in effect at the time described.
     */
    void setDaylightSavingsTime(bool is_dst);
    
    /**
     *  @brief Get time zone
     *  @return Name of time zone
     *
     *  This field is the name for the time zone that was used to
     *  compute this broken-down time value.
     */
    std::string getTimeZone() const;
    
    /**
     *  @brief Reset time
     *  @param tm_struct C structure representing broken down time
     *
     *  Creates the broken down time directly from the C structure @a tm_struct.
     */
    void reset(const struct ::tm& tm_struct);
    
    /**
     *  @brief Reset time
     *  @param time A time value
     *  @param local Create local time
     *
     *  Creates the broken down time representation of the given @a time.
     *  If @a local is true, the broken down time is in local time. Otherwise it is in GMT.
     */
    void reset(const Time& time, bool local=true);
    
    /**
     *  @brief Get string representation
     *  @param format String describing format
     *
     *  Generate a string representation of this time. The format of the representation
     *  is determined by the @a format string. The string is interpreted in the same way
     *  as the format argument of the ISO C99 function strftime. See 'info libc' for details.
     */
    std::string toString(const std::string& format) const;
    
    /**
     * @brief transform this to GMT
     *
     * transform the stored time to GMT time-representation
     */ 
    void toGMT();

    /**
     * @brief transform to local timezone
     *
     * transforms the stored time to timerepresentation is the local timezone
     */
    void toLocalTimeZone();

    /**
     * @brief get stored time as time_t
     * @return time_t of the stored time
     * 
     * returns the stored time as a time_t-datatype
     */
    time_t getTime_t() const;
    
    /** Compares two LocalTime objects
     * 
     * @param lt that is compared with this LocalTime
     * @return true if this LocalTime is greater than lt, otherwise false
     */    
    bool operator<(const LocalTime &lt) const;

    /** Checks if two LocalTime objects are equal.
     * 
     * @param lt that is compared with this LocalTime
     * @return true if this LocalTime is equalt to lt, otherwise false
     */    
    bool operator==(const LocalTime &lt) const;

    /** Substract a LocalTime from this Localtime 
     * 
     * @param lt specifies the subtrahend 
     * @return a LocalTime including the result
     */    
    LocalTime operator-(const LocalTime &lt);

    /** Add a LocalTime from this Localtime 
     * 
     * @param lt specifies the summand
     * @return a LocalTime including the result
     */    
    LocalTime operator+(const LocalTime &lt);

    /** Subtracts an integer from this Localtime 
     * 
     * @param sub specifies the subtrahend
     * @return a LocalTime including the result
     */    
    LocalTime operator-(const int &sub);

    /** Add an integer from this Localtime 
     * 
     * @param add specifies the summand
     * @return a LocalTime including the result
     */    
    LocalTime operator+(const int &add);
    
    /**
     *  @brief Update attributes
     *
     *  Updates the internal C structure after deserialization.
     */
    void updateAttributes();
    
  private:
    /** Second.
     */
    uint8_t  __second;
    
    /** Minute.
     */
    uint8_t  __minute;
    
    /** Hour.
     */
    uint8_t  __hour;
    
    /** Day of month.
     */
    uint8_t  __day_of_month;
    
    /** Day of week.
     */
    uint8_t  __day_of_week;
    
    /** Day of year.
     */
    uint8_t  __day_of_year;
    
    /** Month of year.
     */
    uint8_t  __month;
    
    /** GMT offset.
     */
    uint16_t  __gmt_offset;
    
    /** Year.
     */
    unsigned  __year;
    
    /** Daylight savings time flag.
     */
    bool      __is_dst;
    
    /** Time zone name.
     */
    std::string    __time_zone;
    
    /** Internal C structure.
     */
    struct ::tm         __tm_struct;
  };
  
  inline unsigned LocalTime::getSecond() const {
    return __second;
  }
  
  inline unsigned LocalTime::getMinute() const {
    return __minute;
  }
  
  inline unsigned LocalTime::getHour() const {
    return __hour;
  }
  
  inline unsigned LocalTime::getDayOfMonth() const {
    return __day_of_month;
  }

  inline unsigned LocalTime::getDayOfWeek() const {
    return __day_of_week;
  }
  
  inline unsigned LocalTime::getDayOfYear() const {
    return __day_of_year;
  }
  
  inline unsigned LocalTime::getMonth() const {
    return __month;
  }
  
  inline unsigned LocalTime::getGMTOffset() const {
    return __gmt_offset;
  }
  
  inline unsigned LocalTime::getYear() const {
    return __year;
  }
  
  inline bool LocalTime::isDaylightSavingsTime() const {
    return __is_dst;
  }
  
  inline std::string LocalTime::getTimeZone() const {
    return __time_zone;
  }
  
  inline bool operator<(const time_t &t, const LocalTime &lt) {
    return t < lt.getTime_t();
  }

  inline bool operator<=(const time_t &t, const LocalTime &lt) {
    return t <= lt.getTime_t();
  }

  inline bool operator>(const time_t &t, const LocalTime &lt) {
    return t > lt.getTime_t();
  }

  inline bool operator>=(const time_t &t, const LocalTime &lt) {
    return t >= lt.getTime_t();
  }

  inline bool operator==(const time_t &t, const LocalTime &lt) {
    return t == lt.getTime_t();
  }
  
}

#include "nmm/nmm_suffix.hpp"

#endif
