/*
   Copyright (c) 2018-2019 Nokia.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "private/timerfd.hpp"
#include "private/engine.hpp"
#include "private/system.hpp"

using namespace shareddatalayer;

TimerFD::TimerFD(Engine& engine):
    TimerFD(System::getSystem(), engine)
{
}

TimerFD::TimerFD(System& system, Engine& engine):
    system(system),
    fd(system, system.timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC))
{
    engine.addMonitoredFD(fd, Engine::EVENT_IN, std::bind(&TimerFD::handleEvents, this));
}

TimerFD::~TimerFD()
{
}

void TimerFD::arm(Timer& timer, const Timer::Duration& duration, const Timer::Callback& cb)
{
    const auto absolute(toAbsolute(duration));
    const auto i(queue.insert(std::make_pair(absolute, std::make_pair(&timer, cb))));
    timer.iterator = i;
    if (isFirst(i))
        armTimerFD(absolute);
}

bool TimerFD::isFirst(Queue::iterator it) const
{
    return queue.begin() == it;
}

void TimerFD::disarm(const Timer& timer)
{
    const bool wasFirst(isFirst(timer.iterator));
    queue.erase(timer.iterator);

    if (queue.empty())
        disarmTimerFD();
    else if (wasFirst)
        armTimerFD(nextTrigger());
}

Timer::Duration TimerFD::toAbsolute(const Timer::Duration& duration)
{
    return std::chrono::duration_cast<Timer::Duration>(system.time_since_epoch()) + duration;
}

void TimerFD::handleEvents()
{
    if (timerExpired())
        handleExpiredTimers();
}

bool TimerFD::timerExpired() const
{
    uint64_t count;
    return (system.read(fd, &count, sizeof(count)) == sizeof(count)) && (count > 0U);
}

void TimerFD::handleExpiredTimers()
{
    const auto now(system.time_since_epoch());
    do
    {
        popAndExecuteFirstTimer();
        if (queue.empty())
        {
            disarmTimerFD();
            return;
        }
    }
    while (queue.begin()->first <= now);
    armTimerFD(nextTrigger());
}

void TimerFD::popAndExecuteFirstTimer()
{
    const auto i(queue.begin());
    const auto cb(i->second.second);
    queue.erase(i);
    cb();
}

Timer::Duration TimerFD::nextTrigger() const
{
    return queue.begin()->first;
}

void TimerFD::disarmTimerFD()
{
    setTimeForTimerFD(0, 0);
}

void TimerFD::armTimerFD(const Timer::Duration& duration)
{
    static const long int NANOSECONDS_IN_ONE_SECOND(1E9);
    setTimeForTimerFD(std::chrono::duration_cast<std::chrono::seconds>(duration).count(),
                      std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % NANOSECONDS_IN_ONE_SECOND);
}

void TimerFD::setTimeForTimerFD(time_t seconds, long int nanoseconds)
{
    const itimerspec ts{ { 0, 0 }, { seconds, nanoseconds } };
    system.timerfd_settime(fd, TFD_TIMER_ABSTIME, &ts, nullptr);
}
