// <summary>ソースコード：>時系列データのレコードとなるデータのＩ／Ｆ</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.Interface.Controller;

namespace CommonMP.HYMCO.CoreImpl.Data
{
    /// <summary><para>class outline:</para>
    /// <para>双方向通信データの実装</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>
    /// 上流から下流、下流から上流へ流れるデータは全て同じ型である事
    /// 本クラスの派生クラスは全て[Serializable]であること
    /// </para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// <para> S.H. [2022/01/21][修正]</para>
    /// </remarks>
    [Serializable]
    public class McMutualTranInfoImpl : McMutualTranInfo, HySVersionManagement
    {
        /// <summary> 伝送データ共通情報　</summary>
        protected McTranInfoCommon m_csCommonInfo = new McTranInfoCommon();
        /// <summary>上流要素→下流要素への伝送データ </summary>
        protected McTranInfo m_csDownStreamTranInfo;
        /// <summary>下流要素→上流要素への伝送データ </summary>
        protected McTranInfo m_csUpStreamTranInfo;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McMutualTranInfoImpl csTranInfo = new McMutualTranInfoImpl() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McMutualTranInfoImpl 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>使用禁止</para>
        /// </remarks>
        public McMutualTranInfoImpl()
        {
            //バージョン情報設定
            SetNowVersion();
        }
        public McMutualTranInfoImpl(McPropertyInfoRoot csPropertyInfo)
        {
            McMutualTranInfoProperty csMutalPrpty = csPropertyInfo as McMutualTranInfoProperty;
            if (csMutalPrpty != null)
            {

         
            }
            
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>上流方向、下流方向への伝送データ設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetTranInfo(csDownTranInfo, csUpTranInfo) </para>
        /// </example>
        /// <param name="csDownstreamTranInfo">上流→下流伝送データ</param>
        /// <param name="csUpstreamTranInfo">下流→上流伝送データ</param>
        /// <returns> 無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetTranInfo(McTranInfo csDownstreamTranInfo, McTranInfo csUpstreamTranInfo)
        {
            m_csDownStreamTranInfo = csDownstreamTranInfo;
            m_csUpStreamTranInfo = csUpstreamTranInfo;
        }
        /// <summary><para>method outline:</para>
        /// <para>引数で与えたＩＤの要素が送信するデータを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> (csDownstreamTranInfo , csUpstreamTranInfo) = GetTranInfo() </para>
        /// </example>
        /// <param name=""></param>
        /// <returns> (csDownstreamTranInfo , csUpstreamTranInfo)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual (McTranInfo, McTranInfo) GetTranInfo()
        {
            return (m_csDownStreamTranInfo, m_csUpStreamTranInfo);
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する</para>
        /// </remarks>
        public virtual void SetOnlineProperty(McPropertyInfoRoot csPropertyInfo)
        {
            // Do Nothing
        }
  
        /// <summary><para>method outline:</para>
        /// <para>引数で与えたＩＤの要素が送信するデータを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McTranInfo csSndTrn = GetSendTranInfo(csElmID) </para>
        /// </example>
        /// <param name="csElmID">接続要素</param>
        /// <returns> McTranInfo 送信伝送データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual McTranInfo GetSendTranInfo(HySIdentifier csElmID)
        {
            McTranInfo csRtn = null;
            if (csElmID.Equals(m_csDownStreamTranInfo.GetUpperElementID()) == true)
            {
                csRtn = m_csDownStreamTranInfo;
            }
            else if (csElmID.Equals(m_csUpStreamTranInfo.GetLowerElementID()) == true)
            {
                csRtn = m_csUpStreamTranInfo;
            }
            else
            {
                // Do Nothing
            }
            return csRtn;
        }
 
        /// <summary><para>method outline:</para>
        /// <para>引数で与えたＩＤの要素が受信するデータを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McTranInfo csSndTrn = GetReceiveTranInfo(csElmID) </para>
        /// </example>
        /// <param name="csElmID">接続要素</param>
        /// <returns> McTranInfo 受信伝送データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual McTranInfo GetReceiveTranInfo(HySIdentifier csElmID)
        {
            McTranInfo csRtn = null;
            if (csElmID.Equals(m_csUpStreamTranInfo.GetUpperElementID()) == true)
            {
                csRtn = m_csUpStreamTranInfo;
            }
            else if (csElmID.Equals(m_csDownStreamTranInfo.GetLowerElementID()) == true)
            {
                csRtn = m_csDownStreamTranInfo;
            }
            else
            {
                // Do Nothing
            }
            return csRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>同一種別比較</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = SameKind( csTranInfo ) </para>
        /// </example>
        /// <param name="csTranInfo">比較する伝送データ</param>
        /// <returns> bool true :同一種別 , false:異種別</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>入力情報が null の場合には　false で返す</para>
        /// </remarks>
        public virtual bool SameKind(McTranInfo csTranInfo)
        {
            return m_csUpStreamTranInfo.SameKind(csTranInfo);
        }

        /// <summary><para>method outline:</para>
        /// <para>内部蓄積データのクリア</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ResetData() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void ResetData()
        {
            m_csDownStreamTranInfo.ResetData();
            m_csUpStreamTranInfo.ResetData();
        }

        /// <summary><para>method outline:</para>
        /// <para>自分と同じクラスのインスタンスを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McTranInfo csNewObj = Clone() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns> McTranInfo 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual McTranInfo Clone( )
        {
            McMutualTranInfoImpl csRtnObj = new McMutualTranInfoImpl();
            csRtnObj.m_csDownStreamTranInfo = m_csDownStreamTranInfo.Clone( );
            csRtnObj.m_csUpStreamTranInfo = m_csUpStreamTranInfo.Clone( );
            return csRtnObj;
        }

        /// <summary><para>method outline:</para>
        /// <para>引数で与えられた情報を自分にコピーを行う</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = CopyInfo(csOrgInfo) </para>
        /// </example>
        /// <param name="csOrgInfo">コピー元情報</param>
        /// <returns> bool true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool CopyInfo(McTranInfo csOrgInfo)
        {
            bool bRtn = false;
            McMutualTranInfoImpl csOrgRecord = csOrgInfo as McMutualTranInfoImpl;
            if (csOrgRecord != null)
            {
                if (m_csUpStreamTranInfo.SameKind(csOrgRecord.m_csUpStreamTranInfo) == true &&
                    m_csDownStreamTranInfo.SameKind(csOrgRecord.m_csDownStreamTranInfo) == true)
                {
                    bRtn = true;
                    if (m_csDownStreamTranInfo.CopyInfo(csOrgRecord.m_csDownStreamTranInfo) != true)
                    { bRtn = false; }
                    if (m_csUpStreamTranInfo.CopyInfo(csOrgRecord.m_csUpStreamTranInfo) != true)
                    { bRtn = false; }
                }
                m_csCommonInfo.CopyInfo(csOrgRecord.m_csCommonInfo);
            }
            return bRtn;
        }
  
        /// <summary><para>method outline:</para>
        /// <para>引数で与えられた情報から、最後に追加された情報を　自分の情報に追加する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = LastDataCopy(csOrgInfo) </para>
        /// </example>
        /// <param name="csOrgInfo">コピー元情報</param>
        /// <returns> bool true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>中継端子処理、別マシンへの伝送情報転送処理等に必要</para>
        /// </remarks>
        public virtual bool LastDataCopy(McTranInfo csOrgInfo)
        {
            bool bRtn = false;
            McMutualTranInfoImpl csOrgRecord = csOrgInfo as McMutualTranInfoImpl;
            if (csOrgRecord != null)
            {
                if (m_csUpStreamTranInfo.SameKind(csOrgRecord.m_csUpStreamTranInfo) == true &&
                    m_csDownStreamTranInfo.SameKind(csOrgRecord.m_csDownStreamTranInfo) == true)
                {
                    bRtn = true;
                    if (m_csDownStreamTranInfo.LastDataCopy(csOrgRecord.m_csDownStreamTranInfo) != true)
                    { bRtn = false; }
                    if (csOrgRecord.m_csUpStreamTranInfo.LastDataCopy(m_csUpStreamTranInfo) != true)
                    { bRtn = false; }
                }
            }
            return bRtn;
        }
   
        /// <summary><para>method outline:</para>
        /// <para>中継端子の導通設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>DataTrans(csOrgTran)</para>
        /// </example>
        /// <param name="csOrgTran">上流側の情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void MakeRelayPortDataTransContinuity(McTranInfo csOrgTran)
        {
            McMutualTranInfoImpl csOrg = csOrgTran as McMutualTranInfoImpl;
            if (m_csDownStreamTranInfo != null && csOrg.m_csDownStreamTranInfo != null)
            {
                csOrg.m_csDownStreamTranInfo.MakeRelayPortDataTransContinuity(this.m_csDownStreamTranInfo);
            }
            if (m_csUpStreamTranInfo != null && csOrg.m_csUpStreamTranInfo != null)
            {
                this.m_csUpStreamTranInfo.MakeRelayPortDataTransContinuity(csOrg.m_csUpStreamTranInfo);
            }
        }

        // ================================================
        // プロパティ設定関連
        // ================================================

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void SetProperty(McPropertyInfoRoot csPropertyInfo)
        {
            m_csDownStreamTranInfo.SetProperty(csPropertyInfo);
            m_csUpStreamTranInfo.SetProperty(csPropertyInfo);
        }

        // ================================================
        // 共通情報設定
        // ================================================
        /// <summary><para>method outline:</para>
        /// <para>接続線共通情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McTranCommonCellDataIF csCnnctInf = GetCommonInf( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McTranCommonCellDataIF 接続線共通情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>要素を接続している接続線の共通情報を取得する</para>
        /// </remarks>
        public virtual McTranCommonCellDataIF GetCommonInf()
        {
            return m_csCommonInfo;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続線ＩＤ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIdentifier csID = GetConnectionID( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySIdentifier 接続線ＩＤ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>要素を接続している接続線のＩＤを取得する</para>
        /// </remarks>
        public virtual HySID GetConnectionID()
        {
            return m_csCommonInfo.GetConnectionID();
        }
 
        /// <summary><para>method outline:</para>
        /// <para>接続線名取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySString csName = GetConnectionName( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySString 接続線名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>要素を接続している接続線の名称を取得する</para>
        /// </remarks>
        public virtual HySString GetConnectionName()
        {
            return m_csCommonInfo.GetConnectionName();
        }
  
        /// <summary><para>method outline:</para>
        /// <para>上流要素識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIdentifier csElmID = GetUpperElementID( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySIdentifier 識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>取得した要素が自分を更新している</para>
        /// </remarks>
        public virtual HySID GetUpperElementID()
        {
            return m_csCommonInfo.GetUpperElementID();
        }
   
        /// <summary><para>method outline:</para>
        /// <para>下流要素識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIdentifier csElmID = GetLowerElementID( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySIdentifier 識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>接続先要素に対して情報を伝送する</para>
        /// </remarks>
        public virtual HySID GetLowerElementID()
        {
            return m_csCommonInfo.GetLowerElementID();
        }
  
        /// <summary><para>method outline:</para>
        /// <para>上流要素取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McElement csElm = GetUpperElement( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McElement 上流要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>取得した要素が自分を更新している</para>
        /// </remarks>
        public virtual McElement GetUpperElement()
        {
            return m_csCommonInfo.GetUpperElement();
        }
   
        /// <summary><para>method outline:</para>
        /// <para>下流要素取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McElement csElm = GetLowerElement( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McElement 下流要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>接続先要素に対して情報を伝送する</para>
        /// </remarks>
        public virtual McElement GetLowerElement()
        {
            return m_csCommonInfo.GetLowerElement();
        }
  
        /// <summary><para>method outline:</para>
        /// <para>伝送データ種別取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySObjectKind csKind = GetTranInfoKind( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySObjectKind 伝送データ種別</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual HySObjectKind GetTranInfoKind()
        { return McTranInfoDefine.MUTUAL_D1_TRAN_SERIAL; }

        /// <summary><para>method outline:</para>
        /// <para>時刻取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySTime csTime = GetTime() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySTime 時刻</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySTime GetLastTime()
        {
            if (m_csDownStreamTranInfo != null)
            {
                return m_csDownStreamTranInfo.GetLastTime();
            }
            else if (m_csUpStreamTranInfo != null)
            {
                return m_csUpStreamTranInfo.GetLastTime();
            }
            else
            {
                return HySTime.DEFAULT_TIME.Clone();
            }
        }

        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <summary>保存バージョン情報</summary>
        private string m_sDecodedVersion;
   
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sDecodedVersion = GetDecodedVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 保存バージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メンバー変数に設定されているバージョン情報を返す</para>
        /// </remarks>
        public string GetDecodedVersion()
        {
            return m_sDecodedVersion;
        }
    
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sVersion = GetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 現在のバージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public string GetNowVersion()
        {
            return "1.00";
        }
   
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在のバージョン情報をメンバー変数に設定する</para>
        /// </remarks>
        public void SetNowVersion()
        {
            m_sDecodedVersion = GetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>復元後の整合性確保処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> PostDeserialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
        /// バージョンによって変数等追加がない場合には、実装の必要がない
        /// </para>
        /// </remarks>
        public virtual void PostDeserialize()
        {
            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>逆シリアル化時追加処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
        /// </example>
        /// <param name="csObj">ダミー</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>予約処理</para>
        /// </remarks>
        void IDeserializationCallback.OnDeserialization(Object csObj)
        {
            PostDeserialize();
        }
   
    }
}
