// <summary>ソースコード：>ＨＹＳＳＯＰリンクリストノード管理クラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.Interface.HSData;

namespace CommonMP.HYSSOP.CoreImpl.HSData
{
    /// <summary><para>class outline:</para>
    /// <para>リンクリストノード管理クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>
    /// [CommonMP][ver 1.0.0][2008/10/01][新規作成]
    /// データを乗せる為だけの処理
    /// ★重要★　将来にわたり　本クラスにメンバー変数を追加してはならない。
    /// </para>
    /// </remarks>
    [Serializable]
    internal class HySDataLinkedListNode
    {
        /// <summary>前ノード</summary>
        protected HySDataLinkedListNode m_csPrev = null;        // 前のリンク先(linked list使用の場合)

        /// <summary>次ノード</summary>
        protected HySDataLinkedListNode m_csNext = null;        // 後のリンク先(linked list使用の場合)

        /// <summary>データ</summary>
        protected HySDataRoot m_csData = null;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csDataLinkedListNode = new HySDataLinkedListNode() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode  生成したインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode()
        {
        }
                       
        /// <summary><para>method outline:</para>
        /// <para>デストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>無し</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メモリーリーク防止の為　内部変数は必ず null にセットする</para>
        /// </remarks>
        ~HySDataLinkedListNode()
        {
            m_csData = null;
            m_csNext = null;
            m_csPrev = null;
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csDataLinkedListNode = new HySDataLinkedListNode(csData) </para>
        /// </example>
        /// <param name="csData">データ</param>
        /// <returns>HySDataLinkedListNode  生成したインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode(HySDataRoot csData)
        {
            m_csData = csData;
        }

        /// <summary><para>method outline:</para>
        /// <para>前ノード取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csPrevNode = GetPrev() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode　前ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode GetPrev()
        {
            return m_csPrev;
        }

        /// <summary><para>method outline:</para>
        /// <para>前ノード設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetPrev(csPrev) </para>
        /// </example>
        /// <param name="csPrev">前ノード</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal void SetPrev(HySDataLinkedListNode csPrev)
        {
            m_csPrev = csPrev;
            if (csPrev != null)
            {
                csPrev.m_csNext = this;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>次ノード取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csNextNode = GetNext() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode　次ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode GetNext()
        {
            return m_csNext;
        }

        /// <summary><para>method outline:</para>
        /// <para>次ノード設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetPrev(csNext) </para>
        /// </example>
        /// <param name="csNext">次ノード</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal void SetNext(HySDataLinkedListNode csNext)
        {
            m_csNext = csNext;
            if (csNext != null)
            {
                csNext.m_csPrev = this;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>先頭ノード取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csHeadNode = GetHead() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode　先頭ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode GetHead()
        {
            // StackOverflowException回避のため再帰呼出ではなくループに変更する
            HySDataLinkedListNode csCur = this;
            while (csCur.m_csPrev != null)
            {
                csCur = csCur.m_csPrev;
            }
            return csCur;
        }

        /// <summary><para>method outline:</para>
        /// <para>最終ノード取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csTailNode = GetTail() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode　最終ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode GetTail()
        {
            if (m_csNext == null)
            {
                return this;
            }
            else
            {
                return m_csNext.GetTail();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>前ノード追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csHeadNode = AddPrev(csAddNode) </para>
        /// </example>
        /// <param name="csAddNode">ノード</param>
        /// <returns>HySDataLinkedListNode　先頭ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode AddPrev(HySDataLinkedListNode csAddNode)
        {
            if (m_csPrev == null)
            {
                m_csPrev = csAddNode;
                csAddNode.m_csNext = this;
            }
            else
            {
                csAddNode.m_csPrev = m_csPrev;
                csAddNode.m_csNext = this;
                m_csPrev.m_csNext = csAddNode;
                m_csPrev = csAddNode;
            }
            return csAddNode.GetHead();
        }

        /// <summary><para>method outline:</para>
        /// <para>次ノード追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csDataLinkedListNode = AddNext(csAddNode) </para>
        /// </example>
        /// <param name="csAddNode">ノード</param>
        /// <returns>HySDataLinkedListNode　先頭ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode AddNext(HySDataLinkedListNode csAddNode)
        {
            if (m_csNext == null)
            {
                m_csNext = csAddNode;
                csAddNode.m_csPrev = this;
            }
            else
            {
                csAddNode.m_csPrev = this;
                csAddNode.m_csNext = m_csNext;
                m_csNext.m_csPrev = csAddNode;
                m_csNext = csAddNode;
            }
            return this.GetHead();
        }


        /// <summary><para>method outline:</para>
        /// <para>次ノード追加(高速版)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csDataLinkedListNode = AddNext(csAddNode) </para>
        /// </example>
        /// <param name="csAddNode">ノード</param>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void AddNextQuick(HySDataLinkedListNode csAddNode)
        {
            if (m_csNext == null)
            {
                m_csNext = csAddNode;
                csAddNode.m_csPrev = this;
            }
            else
            {
                csAddNode.m_csPrev = this;
                csAddNode.m_csNext = m_csNext;
                m_csNext.m_csPrev = csAddNode;
                m_csNext = csAddNode;
            }
            return;
        }

        /// <summary><para>method outline:</para>
        /// <para>自ノード取り外し</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csNode = Remove() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedListNode　ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataLinkedListNode Remove()
        {
            HySDataLinkedListNode csRemoveNode = this;
            HySDataLinkedListNode csPrev = csRemoveNode.GetPrev();
            HySDataLinkedListNode csNext = csRemoveNode.GetNext();
            csRemoveNode.Clear();

            if (csPrev == null)
            {
                if (csNext == null)
                {
                    // Do Nothing
                }
                else
                {
                    csNext.m_csPrev = null;
                    csRemoveNode.m_csNext = null;
                }
                return csNext;
            }
            else
            {
                if (csNext == null)
                {
                    csPrev.m_csNext = null;
                    csRemoveNode.m_csPrev = null;
                }
                else
                {
                    csPrev.m_csNext = csNext;
                    csNext.m_csPrev = csPrev;
                    csRemoveNode.m_csPrev = null;
                    csRemoveNode.m_csNext = null;
                }
                return csPrev.GetHead();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>指定場所ノード取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedListNode csNode = GetAfterNode(lNum) </para>
        /// </example>
        /// <param name="lNum">指定場所</param>
        /// <returns>HySDataLinkedListNode　ノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>自分から指定数後のノードインスタンスを取得する</para>
        /// </remarks>
        public HySDataLinkedListNode GetAfterNode(long lNum)
        {
            if (lNum == 0)
            {
                return this;
            }
            else
            {
                if (m_csNext == null)
                {
                    return null;
                }
                else
                {
                    return m_csNext.GetAfterNode(lNum - 1);
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>データセット</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetData(csData) </para>
        /// </example>
        /// <param name="csData">データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetData(HySDataRoot csData)
        {
            m_csData = csData;
        }

        /// <summary><para>method outline:</para>
        /// <para>データ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataRoot csData = GetData() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataRoot　データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySDataRoot GetData()
        {
            return m_csData;
        }

        /// <summary><para>method outline:</para>
        /// <para>データ比較</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bWork = EqualData(csData) </para>
        /// </example>
        /// <param name="csData">データ</param>
        /// <returns>bool　true:=一致, false:=不一致</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public bool EqualData(HySDataRoot csData)
        {
            if (m_csData == csData)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>データ削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Clear() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void Clear()
        {
            m_csData = null;
        }
    }
}
