/*
 * AXCTimerTaskFreeRTOS.cpp
 */

#include "AXCStdioFreeRTOS.hpp"
#include "AXCTimerUnitFreeRTOS.hpp"
#include "AXCTimerTaskFreeRTOS.hpp"

AXCTimerTaskFreeRTOS::AXCTimerTaskFreeRTOS()
    : m_flgid(NULL) {
}

AXCTimerTaskFreeRTOS::~AXCTimerTaskFreeRTOS() {
  if (m_flgid >= 0) {
    vEventGroupDelete(m_flgid);
  }
}

int AXCTimerTaskFreeRTOS::init() {
	m_flgid = xEventGroupCreate();
	if (m_flgid == NULL) {
    return TIMER_TASK_ERROR_INIT;
	}
  return TIMER_TASK_SUCCESS;
}

void AXCTimerTaskFreeRTOS::initWait() {
  m_waitList.clear();
}

void AXCTimerTaskFreeRTOS::initWaitTimer(AXCTimerUnit* timer) {
  m_waitList.push_back(timer);
}

int AXCTimerTaskFreeRTOS::wait() {
	EventBits_t waiptn =
    (1 << TIMERTASK_WAKEUP_EXPIRE) |
    (1 << TIMERTASK_WAKEUP_QUIT) |
    (1 << TIMERTASK_WAKEUP_UPDATE_LIST) |
    (1 << TIMERTASK_WAKEUP_UPDATE_TIME);
	
	EventBits_t ptn;
	ptn = xEventGroupWaitBits(m_flgid, waiptn, pdTRUE, pdFALSE, portMAX_DELAY);

  if (ptn & (1 << TIMERTASK_WAKEUP_EXPIRE)) {
    return TIMERTASK_WAKEUP_EXPIRE;
  }
  if (ptn & (1 << TIMERTASK_WAKEUP_QUIT)) {
    return TIMERTASK_WAKEUP_QUIT;
  }
  if (ptn & (1 << TIMERTASK_WAKEUP_UPDATE_LIST)) {
    return TIMERTASK_WAKEUP_UPDATE_LIST;
  }
  if (ptn & (1 << TIMERTASK_WAKEUP_UPDATE_TIME)) {
    return TIMERTASK_WAKEUP_UPDATE_TIME;
  }
  return TIMER_TASK_ERROR_WAIT_PTN;
}

bool AXCTimerTaskFreeRTOS::isExpired(AXCTimerUnit* timer) {
  AXCTimerUnitFreeRTOS* timerFreeRTOS = (AXCTimerUnitFreeRTOS*)timer;
  return timerFreeRTOS->isExpired();
}

int AXCTimerTaskFreeRTOS::wakeup(TimerTaskWakeup v) {
  EventBits_t setptn = 1 << v;
	(void)xEventGroupSetBits(m_flgid, setptn);	/* 戻り値は別タスク再度クリアされるため確認しない */
  return TIMER_TASK_SUCCESS;
}

bool AXCTimerTaskFreeRTOS::isInWaitList(AXCTimerUnit* timer) {
  std::list<AXCTimerUnit*>::iterator it = m_waitList.begin();
  while (it != m_waitList.end()) {
    if (*it++ == timer) {
      return true;
    }
  }
  return false;
}
