
#include "common/dispatcher.h"
#include <config/xf-config.h>

#if (USE_XF_COMMON_TIMEOUTMANAGER_CLASS != 0)

#include <cassert>
#include "xf/interface/behavior.h"
#include "xf/interface/mutex.h"
#include "timeoutmanager.h"

using Mutex = interface::XFMutex;       // Rename XFMutex interface class to Mutex for easier use.

// Implementation of the getInstance() method of the 'interface::XFTimeoutManager' class.
//
// Note: The implementation is done here because only in this file the real XFTimeoutManager
//       class is known (port specific class). An instance of the XFTimeoutManager class is
//       returned by the 'interface::XFTimeoutManager' class.
interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance() {
    static ::XFTimeoutManager timeoutManager;
    return &timeoutManager;
}

// TODO done: Implement code for XFTimeoutManager class

XFTimeoutManager::XFTimeoutManager() {
}

XFTimeoutManager::~XFTimeoutManager() {

}

void XFTimeoutManager::addTimeout(XFTimeout *pNewTimeout) {
    pMutex_->lock();
    timeouts_.push_front(pNewTimeout);
    pMutex_->unlock();

}

void XFTimeoutManager::returnTimeout(XFTimeout *pTimeout) {
    pMutex_->lock();
    XFDispatcher::getInstance()->pushEvent(pTimeout);
    timeouts_.remove(pTimeout);
    pMutex_->unlock();
}

void XFTimeoutManager::start(std::function<void (uint32_t)> startTimeoutManagerTimer) {
    startTimeoutManagerTimer(tickInterval_);
}

void XFTimeoutManager::scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFBehavior *pBehavior) {
    ::XFTimeout* timeout = new XFTimeout(timeoutId, interval, pBehavior);
    addTimeout(timeout);
}

void XFTimeoutManager::unscheduleTimeout(int32_t timeoutId, interface::XFBehavior *pBehavior) {
    for(XFTimeout* timeout : timeouts_) {
        bool id = ( timeout->getId() == timeoutId );
        bool behavior = ( timeout->getBehavior() == pBehavior);
        if( id && behavior ) {
            timeouts_.remove(timeout);
        }
    }
}

void XFTimeoutManager::tick() {
    for(XFTimeout* timeout : timeouts_) {
        timeout->substractFromRelTicks(tickInterval_);
    }
}

#endif // USE_XF_COMMON_TIMEOUTMANAGER_CLASS
