//
// Copyright 2011-2013 Ettus Research LLC
//
// This program 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, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include "time_spec.h"

namespace gr {
  namespace gsm {

    /***********************************************************************
     * Time spec system time
     **********************************************************************/

    #ifdef HAVE_CLOCK_GETTIME
    #include <time.h>
    time_spec_t time_spec_t::get_system_time(void){
        timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);
        return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9);
    }
    #endif /* HAVE_CLOCK_GETTIME */


    #ifdef HAVE_MACH_ABSOLUTE_TIME
    #include <mach/mach_time.h>
    time_spec_t time_spec_t::get_system_time(void){
        mach_timebase_info_data_t info; mach_timebase_info(&info);
        intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom;
        return time_spec_t::from_ticks(nanosecs, 1e9);
    }
    #endif /* HAVE_MACH_ABSOLUTE_TIME */


    #ifdef HAVE_QUERY_PERFORMANCE_COUNTER
    #include <Windows.h>
    time_spec_t time_spec_t::get_system_time(void){
        LARGE_INTEGER counts, freq;
        QueryPerformanceCounter(&counts);
        QueryPerformanceFrequency(&freq);
        return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart));
    }
    #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */


    #ifdef HAVE_MICROSEC_CLOCK
    #include <boost/date_time/posix_time/posix_time.hpp>
    namespace pt = boost::posix_time;
    time_spec_t time_spec_t::get_system_time(void){
        pt::ptime time_now = pt::microsec_clock::universal_time();
        pt::time_duration time_dur = time_now - pt::from_time_t(0);
        return time_spec_t(
            time_t(time_dur.total_seconds()),
            long(time_dur.fractional_seconds()),
            double(pt::time_duration::ticks_per_second())
        );
    }
    #endif /* HAVE_MICROSEC_CLOCK */

    /***********************************************************************
     * Time spec constructors
     **********************************************************************/
    #define time_spec_init(full, frac) { \
        const time_t _full = time_t(full); \
        const double _frac = double(frac); \
        const int _frac_int = int(_frac); \
        _full_secs = _full + _frac_int; \
        _frac_secs = _frac - _frac_int; \
        if (_frac_secs < 0) {\
            _full_secs -= 1; \
            _frac_secs += 1; \
        } \
    }

    inline long long fast_llround(const double x){
        return (long long)(x + 0.5); // assumption of non-negativity
    }

    time_spec_t::time_spec_t(const time_spec_t & spec){
        time_spec_init(spec.get_full_secs(), spec.get_frac_secs());
    }

    time_spec_t::time_spec_t(double secs){
        time_spec_init(0, secs);
    }

    time_spec_t::time_spec_t(time_t full_secs, double frac_secs){
        time_spec_init(full_secs, frac_secs);
    }

    time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){
        const double frac_secs = tick_count/tick_rate;
        time_spec_init(full_secs, frac_secs);
    }

    time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){
        const long long rate_i = (long long)(tick_rate);
        const double rate_f = tick_rate - rate_i;
        const time_t secs_full = time_t(ticks/rate_i);
        const long long ticks_error = ticks - (secs_full*rate_i);
        const double ticks_frac = ticks_error - secs_full*rate_f;
        return time_spec_t(secs_full, ticks_frac/tick_rate);
    }

    /***********************************************************************
     * Time spec accessors
     **********************************************************************/
    long time_spec_t::get_tick_count(double tick_rate) const{
        return long(fast_llround(this->get_frac_secs()*tick_rate));
    }

    long long time_spec_t::to_ticks(double tick_rate) const{
        const long long rate_i = (long long)(tick_rate);
        const double rate_f = tick_rate - rate_i;
        const long long ticks_full = this->get_full_secs()*rate_i;
        const double ticks_error = this->get_full_secs()*rate_f;
        const double ticks_frac = this->get_frac_secs()*tick_rate;
        return ticks_full + fast_llround(ticks_error + ticks_frac);
    }

    double time_spec_t::get_real_secs(void) const{
        return this->get_full_secs() + this->get_frac_secs();
    }

    /***********************************************************************
     * Time spec math overloads
     **********************************************************************/
    time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){
        time_spec_init(
            this->get_full_secs() + rhs.get_full_secs(),
            this->get_frac_secs() + rhs.get_frac_secs()
        );
        return *this;
    }

    time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){
        time_spec_init(
            this->get_full_secs() - rhs.get_full_secs(),
            this->get_frac_secs() - rhs.get_frac_secs()
        );
        return *this;
    }

    bool operator==(const time_spec_t &lhs, const time_spec_t &rhs){
        return
            lhs.get_full_secs() == rhs.get_full_secs() and
            lhs.get_frac_secs() == rhs.get_frac_secs()
        ;
    }

    bool operator<(const time_spec_t &lhs, const time_spec_t &rhs){
        return (
            (lhs.get_full_secs() < rhs.get_full_secs()) or (
            (lhs.get_full_secs() == rhs.get_full_secs()) and
            (lhs.get_frac_secs() < rhs.get_frac_secs())
        ));
    }
  }
}
