#include "virtual_timer/VirtualTimer.h"
#include "virtual_timer/VirtualTimerDistributor.h"

using namespace pinetime::virtual_timer;
using namespace pinetime::interfaces;

VirtualTimerDistributor::VirtualTimerDistributor(pinetime::interfaces::HwTimerInterface & timer)
    : hw_timer(timer)
    , num_registered_timers(0)
{
    for(auto it = this->virtual_timer_list.begin(); it != this->virtual_timer_list.end(); ++it) {
        *it = nullptr;
    }
}

void VirtualTimerDistributor::register_timer(VirtualTimerInterface *timer)
{
    volatile bool enable = false;
    if(num_registered_timers == MAX_TIMERS) {
        // FIXME: Error notification
        return;
    }
    if(num_registered_timers == 0) {
        // Timer list is empty - so - hw timer isn't running
        enable = true;
    } else {
        // Check if timer already registered
        for(auto it = this->virtual_timer_list.begin(); it != this->virtual_timer_list.end(); ++it) {
            if(*it == timer) {
                return;
            }
        }
    }
    for(auto it = this->virtual_timer_list.begin(); it != this->virtual_timer_list.end(); ++it) {
        if(*it == nullptr) {
            *it = timer;
            num_registered_timers++;
            break;
        }
    }
    if(enable) {
        hw_timer.enable_timer();
    }
}

void VirtualTimerDistributor::unregister_timer(VirtualTimerInterface *timer)
{
    for(auto it = this->virtual_timer_list.begin(); it != this->virtual_timer_list.end(); ++it) {
        if(*it == timer) {
            *it = nullptr;
            num_registered_timers--;
            break;
        }
    }
    if(num_registered_timers == 0) {
        hw_timer.disable_timer();
    }
}

void VirtualTimerDistributor::notify(uint64_t time_ms)
{
    for(auto it = this->virtual_timer_list.begin(); it != this->virtual_timer_list.end(); ++it) {
        if(*it != nullptr) {
            VirtualTimerInterface *vt = *it;
            vt->timer_notification(time_ms);
        }
    }
}

uint64_t VirtualTimerDistributor::tick()
{
    return hw_timer.tick();
}
