/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2013/08/26
/// 
/// @brief  両方向リスト関連
///
/// @note
/// オブジェクトそのものがノード扱いとなる。\n
/// 必ず継承して使うこととする。\n
/// 多重継承に組み込む場合は、最初に継承すること。\n
/// 基本的に、リストクラスで保持するポインタが、オブジェクトの先頭ポインタを指すよう設計してください。
///
/// ****************************************************************************

#pragma once

#include "../../Base/CPL_Core_Basic.h"


namespace CPL {
namespace Core {
namespace List {


// _____________________________________________________________________________
/// @brief 双方向リングリストクラス
///
// *****************************************************************************
template<class T_Type>
class LingList
  : virtual public Core::BaseObject
{
protected:
  friend class LingList<T_Type>;
  T_Type* m_ptr_prev;
  T_Type* m_ptr_next;

public:
  T_Type* GetNodePrev(){ return m_ptr_prev; }
  T_Type* GetNodeNext(){ return m_ptr_next; }

  void Detach();
  void AddNodePrev( T_Type* in_ptr_node );
  void AddNodeNext( T_Type* in_ptr_node );

  LingList()
  {
    m_ptr_prev = static_cast<T_Type*>(this);
    m_ptr_next = static_cast<T_Type*>(this);
  }

  ~LingList()
  {
    Detach();
  }
};


// _____________________________________________________________________________
/// @brief リストから除外。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
void LingList<T_Type>::Detach()
{
  m_ptr_prev->m_ptr_next = m_ptr_next;
  m_ptr_next->m_ptr_prev = m_ptr_prev;
  m_ptr_prev = static_cast<T_Type*>(this);
  m_ptr_next = static_cast<T_Type*>(this);
}


// _____________________________________________________________________________
/// @brief 前方に追加。
///
/// @param[in] in_ptr_node : 追加するノードのポインタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
void LingList<T_Type>::AddNodePrev( T_Type* in_ptr_node )
{
  // ポインタ保存
  T_Type* ptr_prev_A = m_ptr_prev;
  T_Type* ptr_next_B = in_ptr_node->m_ptr_next;
  // 設定
  this  ->m_ptr_prev = in_ptr_node;
  in_ptr_node ->m_ptr_next = static_cast<T_Type*>(this);
  ptr_prev_A->m_ptr_next = ptr_next_B;
  ptr_next_B->m_ptr_prev = ptr_prev_A;
}


// _____________________________________________________________________________
/// @brief 後方に追加。
///
/// @param[in] in_ptr_node : 追加するノードのポインタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Type> inline
void LingList<T_Type>::AddNodeNext( T_Type* in_ptr_node )
{
  // ポインタ保存
  T_Type* ptr_next_A = m_ptr_next;
  T_Type* ptr_prev_B = in_ptr_node->m_ptr_prev;
  // 設定
  this  ->m_ptr_next = in_ptr_node;
  in_ptr_node ->m_ptr_prev = static_cast<T_Type*>(this);
  ptr_next_A->m_ptr_prev = ptr_prev_B;
  ptr_prev_B->m_ptr_next = ptr_next_A;
}


} // namespace List
} // namespace Core
} // namespace CPL
