/*
 * AXFTimerInterneal.cpp
 */

#include "AXFEvent.hpp"
#include "AXFStage.hpp"
#include "AXFTimerInternal.hpp"

AXFTimerInternal::AXFTimerInternal(AXFObjectName& name)
    : m_name(name) {
}

AXFTimerInternal::~AXFTimerInternal() {
  killTimer();
}

AXFActor::timerStatus AXFTimerInternal::addTimer(AXFActor* obj,
                                         AXFActor::timeSpec timer,
                                         TimerKind kind,
                                         AXFEvent_t timerEventId,
                                         AXFActor::TimerId_t* TimerId) {
  if (AXFStage::m_timerTask == NULL) {
    return AXFActor::TIMER_ERROR_INIT;
  }

  if (TimerId == NULL) {
    return AXFActor::TIMER_ERROR_PARAMETER;
  }

  AXFTimerUnitInternal* timerUnit = newTimerUnit(AXFStage::m_timerTask, m_name, obj, timerEventId);
  if (timerUnit == NULL) {
    return AXFActor::TIMER_ERROR_CREATE;
  }

  int ret;
  if ((ret = timerUnit->init()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
    delete timerUnit;
    return AXFActor::TIMER_ERROR_INIT;
  }

  CoreTimeSpec settingTime;
  settingTime.sec = timer.sec;
  settingTime.nsec = AXFChrono::convertTickToNsec(timer.tick);
  bool isSingle = (kind == SINGLE_SHOT_TIMER);

  if ((ret = timerUnit->set(&settingTime, isSingle)) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
    delete timerUnit;
    return AXFActor::TIMER_ERROR_SETTIME;
  }

  *TimerId = timerUnit->getId();

  return AXFActor::TIMER_SUCCESS;
}

AXFActor::timerStatus AXFTimerInternal::delTimer(AXFActor::TimerId_t TimerId) {
  if (AXFStage::m_timerTask == NULL) {
    return AXFActor::TIMER_ERROR_INIT;
  }

  int id = (int)TimerId;
  int ret;

  // タイマの存在確認をして同時にタイマを止める
  AXFTimerUnitInternal* timerUnit = NULL;
  if ((ret = AXFStage::m_timerTask->cancel(id, &timerUnit)) != AXFTimerTaskInternal::TIMER_TASK_SUCCESS) {
    if (ret == AXFTimerTaskInternal::TIMER_TASK_ERROR_CANCEL_NOTFOUND) {
      // 単発タイマ満了し既に破棄された
      return AXFActor::TIMER_SUCCESS;
    }
    // 存在確認の前にエラー
    // timerUnit は破棄できない...
    return AXFActor::TIMER_ERROR_DELTIME;
  }

  // ここではタイマが存在してる
  if ((ret = timerUnit->delFromTask()) != AXFTimerUnitInternal::TIMER_UNIT_SUCCESS) {
    return AXFActor::TIMER_ERROR_DELTIME;
  }

  delete timerUnit;
  return AXFActor::TIMER_SUCCESS;
}

AXFActor::timerStatus AXFTimerInternal::getTimer(AXFActor::TimerId_t TimerId,
						 AXFActor::timeSpec* timespec) {
  if (AXFStage::m_timerTask == NULL) {
    return AXFActor::TIMER_ERROR_INIT;
  }

  int id = (int)TimerId;
  int ret;
  CoreTimeSpec spec;

  // タイマの存在確認をして同時にタイマの情報を取得する
  if ((ret = AXFStage::m_timerTask->get(id, &spec)) != AXFTimerTaskInternal::TIMER_TASK_SUCCESS) {
    if (ret == AXFTimerTaskInternal::TIMER_TASK_ERROR_GET_NOTFOUND) {
      // ...
      // 単発タイマ満了し既に破棄された
    }
    return AXFActor::TIMER_ERROR_GETTIME;
  }

  timespec->tick = AXFChrono::convertNsecToTick(spec.nsec);
  timespec->sec = spec.sec;

  return AXFActor::TIMER_SUCCESS;
}

AXFActor::timerStatus AXFTimerInternal::initTimer() {
  return AXFActor::TIMER_SUCCESS;
}

void AXFTimerInternal::killTimer() {
  if (AXFStage::m_timerTask) {
    int ret;
    if ((ret = AXFStage::m_timerTask->del(m_name)) != AXFTimerTaskInternal::TIMER_TASK_SUCCESS) {
      // error
    }
  }
}
