/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2013/09/08 - 2013/09/08
/// 
/// @brief  イベント管理クラス。
/// 
/// ****************************************************************************

#include "../CPL_Core.h"

namespace CPL {
namespace Core {


// _____________________________________________________________________________
/// @brief コンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventCatcher::EventCatcher()
  : m_ptr_event_store_old( stm_ptr_evt_store() )
  , m_ptr_event_top(nullptr)
  , m_ptr_event_end(nullptr)
{
  stm_ptr_evt_store() = this;
}


// _____________________________________________________________________________
/// @brief デストラクタ。
///
/// キャッチしたイベントの
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventCatcher::~EventCatcher()
{
  //
  stm_ptr_evt_store() = m_ptr_event_store_old;
  // イベントアイテムを全て削除（イベントアイテムのデストラクタでイベントがコールされる）
  EventItem* ptr_del_event = m_ptr_event_top;
  while( ptr_del_event )
  {
    (*ptr_del_event)(); // イベントをコール。
    DEL( ptr_del_event, ptr_del_event->GetNodeNext() );
  }
}


// _____________________________________________________________________________
/// @brief イベントを追加。
///
/// @param[in] in_ptr_event
///   : 追加対象のイベントクラスポインタ。\n
///   : なお、渡すデータは単独でnewしたものでないといけない。
///
/// @retval true  : リストに追加（イベントはコールされない）
/// @retval false : リスト追加失敗（すぐにイベントがコールされる）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//bool EventCatcher::Add( EventItem* in_ptr_event )
//{
//  if( !stm_ptr_evt_store() )
//  {
//    DEL( in_ptr_event ); // すぐにイベントをコール。つまり削除。
//    return false;
//  }
//  ef( stm_ptr_evt_store()->m_ptr_event_end )
//  {
//    stm_ptr_evt_store()->m_ptr_event_end->AddNodeNext( in_ptr_event );
//  }
//  else
//  {
//    stm_ptr_evt_store()->m_ptr_event_top = in_ptr_event;
//  }
//  stm_ptr_evt_store()->m_ptr_event_end = in_ptr_event;
//  return true;
//}


//// _____________________________________________________________________________
///// @brief 限定追加（最初のみ）。
/////
///// 同じものがあれば、最初のアイテムのみ保持される（つまり追加されない）
///// 
///// @param[in] in_ptr_event
/////   : 追加対象のイベントクラスポインタ。\n
/////   : なお、渡すデータは単独でnewしたものでないといけない。
/////
///// @retval true  : リストに追加（イベントはコールされない）
///// @retval false : リスト追加失敗（すぐにイベントがコールされる）
//// _____________________________________________________________________________
//bool EventCatcher::AddOnlyFirst( EventItem* in_ptr_event )
//{
//  if( !stm_ptr_evt_store() )
//  {
//    DEL( in_ptr_event ); // すぐにイベントをコール。つまり削除。
//    return false;
//  }
//  if( Check( in_ptr_event ) == nullptr )
//  {
//    return Add( in_ptr_event );
//  }
//  return false;
//}


//// _____________________________________________________________________________
///// @brief 限定追加（最後のみ）
/////
///// 同じものがあれば、最後のアイテムのみ保持される（先のイベントは破棄される）
/////
///// @param[in] in_ptr_event
/////   : 追加対象のイベントクラスポインタ。\n
/////   : なお、渡すデータは単独でnewしたものでないといけない。
/////
///// @retval true  : リストに追加（イベントはコールされない）
///// @retval false : リスト追加失敗（すぐにイベントがコールされる）
//// _____________________________________________________________________________
//bool EventCatcher::AddOnlyLast( EventItem* in_ptr_event )
//{
//  if( !stm_ptr_evt_store() )
//  {
//    DEL( in_ptr_event ); // すぐにイベントをコール。つまり削除。
//    return false;
//  }
//  // 
//  EventItem* ptr_check_event = stm_ptr_evt_store()->m_ptr_event_top;
//  if( !ptr_check_event )
//  {
//    return Add( in_ptr_event );
//  }
//  // 先頭のアイテムの検査
//  if( ptr_check_event->Comp( in_ptr_event ) ) // 同じと判断されたら
//  {
//    // 追加
//    Add( in_ptr_event );
//    // 先頭ポインタの変更
//    stm_ptr_evt_store()->m_ptr_event_top = ptr_check_event->GetNodeNext();
//    // アイテムの削除
//    DEL( ptr_check_event );
//    return true;
//  }
//  else
//  {
//    // 
//    while( ptr_check_event->GetNodeNext() )
//    {
//      if( ptr_check_event->GetNodeNext()->Comp( in_ptr_event ) )
//      {
//        if( ptr_check_event->GetNodeNext() == stm_ptr_evt_store()->m_ptr_event_end )
//        {
//          // 削除対象が終端ならば、終端ポインタを調整
//          stm_ptr_evt_store()->m_ptr_event_end = ptr_check_event;
//        }
//        EventItem* pDelItem = ptr_check_event->GetNodeNext();
//        // リンクポインタの修正
//        ptr_check_event->_SetNodeNext( ptr_check_event->GetNodeNext()->GetNodeNext() );
//        // アイテムの削除
//        DEL( pDelItem );
//        break;
//      }
//      ptr_check_event = ptr_check_event->GetNodeNext();
//    }
//    return Add( in_ptr_event );
//  }
//}


// _____________________________________________________________________________
/// @brief 存在するかチェック。
///
/// @param[in] in_ptr_event : 比較するイベントアイテムのポインタ。
///
/// @return 該当したイベントアイテムのポインタ。
/// @return なければnullptrを返す。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventItem* EventCatcher::Check( EventItem* in_ptr_event )
{
  if( !stm_ptr_evt_store() )
  {
    return nullptr;
  }
  // 同じものがあるか検査
  EventItem* ptr_check_event = stm_ptr_evt_store()->m_ptr_event_top;
  while( ptr_check_event )
  {
    if( in_ptr_event->Comp( ptr_check_event ) ) // チェック
    {
      return ptr_check_event;
    }
    ptr_check_event = ptr_check_event->GetNodeNext();
  }
  return nullptr;
}




} // namespace Core
} // namespace CPL
