#ifndef INCLUDED_BOBCAT_HIGHSYSCLOCK_
#define INCLUDED_BOBCAT_HIGHSYSCLOCK_

#include <bobcat/clockbase>

namespace FBB
{

template<typename ChronoClock>
class HighSysClock;

template <typename ChronoClock>
std::ostream &operator<<(std::ostream &out,
                         HighSysClock<ChronoClock> const &clock);

template<typename ChronoClock>
class HighSysClock: public ClockBase<ChronoClock>
{
    friend std::ostream &operator<< <>(std::ostream &out,               // .f
                                    HighSysClock<ChronoClock> const &clock);

    mutable char const *d_putTime;      // put_time config
    mutable bool d_localTime;           // true: show local time

    public:
        using TimePoint = ClockBase<ChronoClock>::TimePoint;
    
        HighSysClock(TimePoint const &timePoint);
    
        std::time_t timeT() const;
    
        HighSysClock<ChronoClock> &setTimeT(std::time_t seconds);

                                                                        // .f
        HighSysClock<ChronoClock> const &operator()(
                                            char const *putTime,
                                            bool localTime = true) const;
        
    private:
        std::ostream &insert(std::ostream &out) const;                  // .f
};

template<typename ChronoClock>
inline HighSysClock<ChronoClock>::HighSysClock(TimePoint const &timePoint)
:
    ClockBase<ChronoClock>(timePoint),
    d_putTime(0),
    d_localTime(true)
{}

template <typename ChronoClock>
inline std::time_t HighSysClock<ChronoClock>::timeT() const
{
                     // cf. Annotations 23.1.1
    return ChronoClock::to_time_t(this->timePoint());
}

template <typename ChronoClock> 
HighSysClock<ChronoClock> &HighSysClock<ChronoClock>::setTimeT(
                                                            std::time_t secs)
{
    ChronoClock::from_time_t(secs);
    return *this;
}

template<typename ChronoClock>
HighSysClock<ChronoClock> const &HighSysClock<ChronoClock>::operator()(
                                                    char const *putTime,
                                                    bool localTime)  const
{
    d_putTime = putTime;
    d_localTime = localTime;
    return *this;
}

template<typename ChronoClock>
std::ostream &HighSysClock<ChronoClock>::insert(std::ostream &out) const
{
    if (d_putTime == 0)
         return out << static_cast<ClockBase<ChronoClock>>(*this);

    time_t tt = timeT();
    tm *tmPtr = d_localTime ? std::localtime(&tt) : std::gmtime(&tt);
    out << std::put_time(tmPtr, d_putTime);
    d_putTime = 0;

    return out;
}
    

template <typename ChronoClock>
inline std::ostream &operator<<(std::ostream &out,               // .f
                         HighSysClock<ChronoClock> const &clock)
{
    return clock.insert(out);
}



} // FBB        
#endif
