#ifndef _INCLUDED_BOBCAT_DATETIME_
#define _INCLUDED_BOBCAT_DATETIME_

#include <ctime>
#include <iosfwd>

namespace FBB
{
    class DateTime;
}

namespace std
{
    ostream &operator<<(ostream &str, FBB::DateTime const &dt);
}

namespace FBB
{

class DateTime
{

    friend  std::ostream &std::operator<<(std::ostream &str, 
                                          DateTime const &dt);
    public:
        enum TimeType
        {
            LOCALTIME,
            UTC
        };
        enum Month
        {
            JANUARY,
            FEBRUARY,
            MARCH,
            APRIL,
            MAY,
            JUNE,
            JULY,
            AUGUST,
            SEPTEMBER,
            OCTOBER,
            NOVEMBER,
            DECEMBER,
        };
        enum WeekDay
        {
            SUNDAY,
            MONDAY,
            TUESDAY,
            WEDNESDAY,
            THIRSDAY,
            FRIDAY,
            SATURDAY,
        };
        enum TriVal
        {
            UNKNOWN,
            NO,
            YES
        };

    private:
        TimeType    d_type; // current type of info in d_tm member
        time_t      d_time; // 
        struct tm   d_tm;   // 
        bool        d_ok;
        size_t    d_errno;

    public:
        DateTime(TimeType type = LOCALTIME);
        DateTime(time_t time, TimeType type = LOCALTIME);
        DateTime(tm *t, TimeType type = LOCALTIME);

        operator bool() const;
        bool breakDown(TimeType type);
        size_t error() const;
        size_t hours() const;
        size_t minutes() const;
        Month month() const;
        size_t monthDayNr() const;

        DateTime &operator+=(DateTime const &other);    // UTC
        DateTime &operator+=(time_t seconds);           // d_type
        DateTime &operator+=(tm const &tm);             // d_type

        DateTime &operator-=(DateTime const &other);    // UTC
        DateTime &operator-=(time_t seconds);           // d_type
        DateTime &operator-=(tm const &tm);             // d_type

        size_t seconds() const;
        time_t time() const;
        WeekDay weekday() const;
        size_t year() const;
        size_t yearDay() const;
        size_t yearDayNr() const;
        TriVal dst() const;
};

inline DateTime::operator bool() const
{
    return d_ok;
}

inline size_t DateTime::error() const
{
    return d_errno;
}

inline size_t DateTime::hours() const
{
    return d_tm.tm_hour;
}

inline size_t DateTime::minutes() const
{
    return d_tm.tm_min;
}

inline DateTime::Month DateTime::month() const
{
    return static_cast<Month>(d_tm.tm_mon);
}

inline size_t DateTime::monthDayNr() const
{
    return d_tm.tm_mday;
}

inline size_t DateTime::seconds() const
{
    return d_tm.tm_sec;
}

inline time_t DateTime::time() const
{
    return d_time;
}

inline DateTime::WeekDay DateTime::weekday() const
{
    return static_cast<WeekDay>(d_tm.tm_wday);
}

inline size_t DateTime::year() const
{
    return d_tm.tm_year + 1900;
}

inline size_t DateTime::yearDay() const
{
    return d_tm.tm_yday;
}

inline size_t DateTime::yearDayNr() const
{
    return d_tm.tm_yday + 1;
}

inline DateTime::TriVal DateTime::dst() const
{
    return static_cast<TriVal>(d_tm.tm_isdst);  
}

}

inline FBB::DateTime operator-(FBB::DateTime const &left,   // UTC
                               FBB::DateTime const &right)
{
    return FBB::DateTime(left) -= right;
}   

inline FBB::DateTime operator-(FBB::DateTime const &left,   // d_type
                               time_t right)
{
    return FBB::DateTime(left) -= right;
}   

inline FBB::DateTime operator-(FBB::DateTime const &left,   // d_type
                               tm const &right)
{
    return FBB::DateTime(left) -= right;
}   

inline FBB::DateTime operator+(FBB::DateTime const &left, 
                               FBB::DateTime const &right)
{
    return FBB::DateTime(left) += right;
}   

inline FBB::DateTime operator+(FBB::DateTime const &left,   // d_type
                               time_t right)
{
    return FBB::DateTime(left) += right;
}   

inline FBB::DateTime operator+(FBB::DateTime const &left,   // d_type
                               tm const &right)
{
    return FBB::DateTime(left) += right;
}   


#endif
