/**
 * @file   AXFTimerTaskInternal.hpp
 * @brief  AXFTimerTaskInternalクラスヘッダ
 *
 * @par    Programming Language
 *         C++
 */

#ifndef AXFTIMERTASKINTERNAL_HPP_
#define AXFTIMERTASKINTERNAL_HPP_

#include <vector>

#include "AXCTimerTaskFreeRTOS.hpp"
#define AXFTIMERTASK_BASE_CLASS AXCTimerTaskFreeRTOS

#include "AXFTask.hpp"
#include "AXFMutex.hpp"
#include "AXFPtrList.hpp"
#include "AXFTimerUnitInternal.hpp"

/**
 * @class AXFTimerTaskInternal
 * @brief Stage内のタイマ・リソースを管理し、タイマ・イベントを該当するアクタへ通知する機能を提供する
 *
 */
class AXFTimerTaskInternal : public AXFTIMERTASK_BASE_CLASS {
  bool m_baseInited;

  AXFTask m_task;
  bool m_taskCreated;
  AXFTask* m_taskPtr;
  AXFObjectName m_taskName;
  AXFLog m_log;

  std::vector<AXFTimerUnitInternal*> m_list;
  AXFMutex m_listMutex;
  bool m_listMutexInited;
  AXFMutex* m_listMutexPtr;

  int m_unitIdCnt;

  AXFPtrList m_simuList;
  AXFPtrList* m_simuListPtr;

  typedef std::vector<AXFTimerUnitInternal*>::iterator ListIt;
  typedef int (AXFTimerTaskInternal::*ListMethod)(bool* found, void** args);

 public:

#ifndef	UNUSE_CHRONO	// baba Chrono非対応
  AXFChrono m_simuStartChrono;
#endif	/* UNUSE_CHRONO */

  /**
   * @brief AXFTimerTaskInternalコンストラクタ
   * @n     引数指定はテスト時のみ指定し、通常は指定しない
   * @n
   * @param [in] listMutexPtr リスト排他処理用のMutexクラス
   * @param [in] taskPtr タスククラス
   */
  AXFTimerTaskInternal(AXFMutex* listMutexPtr = NULL, AXFTask* taskPtr = NULL, AXFPtrList* simuListPtr = NULL);

  /**
   * @brief AXFTimerTaskInternalデストラクタ
   */
  virtual ~AXFTimerTaskInternal();

  /**
   * @brief initAndCreate
   * @n     タイマタスを初期化しタスクを生成する
   * @n
   * @param [in] name 生成するタスクの名前
   * @param [in] priority 生成するタスクの優先度
   * @param [in] stackSize 生成するタスクのスタックサイズ
   * @n
   * @return 設定可否
   */
  virtual int initAndCreate(const std::string& name, AXFTask::taskPriority priority, size_t stackSize);

  /**
   * @brief add
   * @n     タイマタスクの登録リストにタイマを追加する
   * @n
   * @n     追加するタイマが単発タイマとして設定されている場合、
   * @n     後タイマが満了しイベント送信後に、
   * @n     タイマオブジェクトのインスタンスを破棄する
   * @n
   * @n     本クラスからタイマオブジェクトのインスタンスを破棄するのは、
   * @n     単発タイマが満了したときのみ
   * @n
   * @param [in] timer 追加するタイマ
   * @n
   * @return 設定可否
   */
  // AXFTimerUnitInternal set() からのみ呼び出される
  virtual int add(AXFTimerUnitInternal* timer);

  /**
   * @brief del
   * @n     タイマタスクの登録リストからタイマを削除する
   * @n
   * @n     タイマオブジェクトのインスタンス自体は破棄しない
   * @n
   * @param [in] timer 削除するタイマ
   * @n
   * @return 設定可否
   */
  // AXFTimerUnitInternal delFromTask() からのみ呼び出される
  virtual int del(AXFTimerUnitInternal* timer);

  /**
   * @brief del
   * @n     指定の名前のアクタで生成されたタイマ全てを登録リストから削除する
   * @n
   * @n     タイマオブジェクトのインスタンス自体は破棄しない
   * @n
   * @param [in] name 削除するタイマを生成したアクタの名前
   * @param [in] andDeleteObject 削除したタイマオブジェクトを破棄するかどうか
   * @n
   * @return 設定可否
   */
  // AXFTimerInternal killTimer() からのみ呼び出される
  virtual int del(AXFObjectName& name, bool andDeleteObject = true);

  /**
   * @brief delAll
   * @n     タイマタスクに追加されている全てのタイマを
   * @n     登録リストから削除する
   * @n
   * @n     タイマオブジェクトのインスタンス自体は破棄しない
   * @n
   * @param [in] andDeleteObject 削除したタイマオブジェクトを破棄するかどうか
   */
  virtual void delAll(bool andDeleteObject = true);

  /**
   * @brief cancel
   * @n     指定のタイマが登録リストに追加されている事を確認し
   * @n     同時にタイマ動作をキャンセルする
   * @n
   * @param [in] timer キャンセルするタイマ
   * @n
   * @return 設定可否
   */
  virtual int cancel(AXFTimerUnitInternal* timer);

  /**
   * @brief cancel
   * @n     指定のタイマIDが登録リストに追加されている事を確認し
   * @n     同時にタイマ動作をキャンセルする
   * @n
   * @param [in]  id キャンセルするタイマID
   * @param [out] *ret_timer キャンセルしたタイマのインスタンスを返す
   * @n           キャンセルしたタイマが無ければNULLを返す
   * @n           ret_timer にNULLが指定されていると、*ret_timerには値を返さない
   * @n
   * @return 設定可否
   */
  virtual int cancel(int id, AXFTimerUnitInternal** ret_timer = NULL);

  /**
   * @brief cancel
   * @n     登録リスト中の指定の名前のアクタで生成された
   * @n     全てのタイマについてキャンセルする
   * @n
   * @param [in] name キャンセルするタイマを生成したアクタの名前
   * @n
   * @return 設定可否
   */
  // AXFTimerInternal killTimer() からのみ呼び出される
  virtual int cancel(AXFObjectName& name);

  /**
   * @brief get
   * @n     指定のタイマIDが登録リストに追加されている事を確認し
   * @n     同時にタイマ情報を取得する
   * @n
   * @param [in]  id タイマ情報を取得するタイマID
   * @param [out] *ret_spec タイマ周期(満了)の経過時間（秒、秒未満）
   * @n
   * @return 設定可否
   */
  // AXFTimerInternal getTimer() からのみ呼び出される
  virtual int get(int id, CoreTimeSpec* ret_spec);

  static bool isTimeDomainActive();
#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
  void timeDomainSwitched();
#endif	/* UNUSE_CHRONO */
  void simu(AXFActor* actor);

 private:

  bool isExistToActor(AXFActor* toActor);
#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
  int getListToActor(AXFPtrList& ret_list);
#endif	/* UNUSE_CHRONO */

  int listWork(ListMethod method, bool* found, void** args);

  int listWorkAdd(bool* found, void** args);
  int listWorkDel(bool* found, void** args);
  int listWorkDelByName(bool* found, void** args);
  int listWorkDelAll(bool* found, void** args);
  int listWorkCancel(bool* found, void** args);
  int listWorkCancelById(bool* found, void** args);
  int listWorkCancelByName(bool* found, void** args);
  int listWorkGet(bool* found, void** args);

  int listWorkIsExistToActor(bool* found, void** args);
#ifndef	UNUSE_CHRONO	// baba TimeDomainは現状非対応
  int listWorkGetListToActor(bool* found, void** args);
#endif	/* UNUSE_CHRONO */

  int listWorkInitWaitTimer(bool* found, void** args);
  int listWorkWorkerSub(bool* found, void** args);

  static void sendSimuEvent(AXFActor* toActor, AXFLog& log);

  static void* do_worker(void* arg);
  void* do_worker_sub();

};

#endif /* AXFTIMERTASKINTERNAL_HPP_ */
