using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Collections;

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Controller;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

using CommonMP.HYMCO._SYSTEM_;



namespace CommonMP.HYMCO.CoreOptionl.HymcoExpansionModel
{

    /// <summary><para>class outline:</para>
    /// <para>相互接続演算モデル基底クラス（相互結合に対応するモデルは本クラスを派生して作成する）</para>
    /// </summary>
    /// <remarks>
    /// <para>history:</para>
    /// <para>
    /// [2021/12/31][新規作成]
    /// </para>
    /// <para>remarks:</para>
    /// <para> 補間処理付き </para>
    /// </remarks>
    public abstract class McInterCnnctModel : McForecastModelBase
    {
        /// <summary> 演算データ（キャスト用）  便利の為、キャスト用に定義しておく </summary>
        protected McInterCnnctModelCalInfo m_cInterCnnctCalInf = null;
        //========================================================

        //---------- 相互型結合の内部を含めた送受信データ接続 --------
        /// <summary> セル型受信データ数 </summary>
        protected long m_lDataNumTrnInfRcvCell = 0;
        /// <summary> セル型受信データ接続回線 </summary>
        protected McReceiveCellDataIF[] m_csRcvCellDataTrnInf = null;
        /// <summary> セル型送信信データ数 </summary>
        protected long m_lDataNumTrnInfSncCell = 0;
        /// <summary> セル型受信データ数接続回線 </summary>
        protected McSendCellDataIF[] m_csSndCellDataTrnInf = null;

        /// <summary> データパターン別接続リスト </summary>
        protected long m_lOnlyReceveDataNum = 0;
        protected McReceiveOnlyTranInfo[] m_csOnlyReceiveCellData = null;
        protected long m_lOnlySendDataNum = 0;
        protected McSendOnlyTranInfo[] m_csOnlySelDataCellData = null;
        protected long m_lRcvSndDataNum = 0;
        protected McRdvSndTranInfoPair[] m_csSndRcvCellData = null;
        //--------------------------
        protected List<McConnectPatternPairInfo> m_csRcvOnlyConnectionPatternList = new List<McConnectPatternPairInfo>();
        protected List<McConnectPatternPairInfo> m_csSendOnlyConnectionPatternList = new List<McConnectPatternPairInfo>();
        protected List<McConnectPatternPairInfo> m_csMutualConnectionPatternList = new List<McConnectPatternPairInfo>();

        public McInterCnnctModel()
        {
            // 同期型
            m_eDtFusionTiming = McDefine.DataFusionTiming.SYNCHRONOUS;
        }

        //=========================
        // 演算実行前処理関連メソッド
        //=========================

        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            try
            {
                // 同期型
                if (m_eDtFusionTiming != McDefine.DataFusionTiming.SYNCHRONOUS)
                {
                    bRtn = false;
                    csErrorInf.AddCheckErrorData(this.GetID(), new HySObjectKind("McInterCnnctModel"), "ﾒﾆｭｰの[ﾌﾟﾛｼﾞｪｸﾄ管理]-[制御ﾊﾟﾗﾒｰﾀ設定]を選択し、表示されたﾀﾞｲｱﾛｰｸﾞで、[非同期]→[同期]に変更してください。または、全ての部分系が [同期] に設定されていることを確認してください");
                }

                // キャストしていない場合の対処
                if (m_cInterCnnctCalInf == null)
                {
                    m_cInterCnnctCalInf = (McInterCnnctModelCalInfo)m_csCalInfo;
                }

                //---------------------------
                // 接続チェック開始
                //----------------------------
                m_lDataNumTrnInfRcvCell = 0;
                m_lDataNumTrnInfSncCell = 0;
                for (int i = 0; i < m_lInputDataNum; i++)
                {
                    m_lDataNumTrnInfRcvCell += 1;
                    if (m_csInputData[i] is McTimeSeriesMutualCellTranInfor)
                    {
                        m_lDataNumTrnInfSncCell += 1;
                    }
                }
            }
            catch(Exception e)
            {
                csErrorInf.AddCheckErrorData(this.GetID(), new HySObjectKind("McInterCnnctModel::ReceiveConnectionCheck()"), " catch Exception "+e.ToString());

                bRtn = false;
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;

            try
            {
                for (int i = 0; i < m_lOutputDataNum; i++)
                {
                    m_lDataNumTrnInfSncCell += 1;
                    if (m_csOutputData[i] is McTimeSeriesMutualCellTranInfor)
                    {
                        m_lDataNumTrnInfRcvCell += 1;
                    }
                }

                //---------------------------
                Hashtable workOnlyRcvPtnTbl = new Hashtable();
                Hashtable workOnlySndPtnTbl = new Hashtable();
                Hashtable workSndRcvPtnTbl = new Hashtable();
                McConnectPatternPairInfo csPairInf = null;
                //---------------------------
                m_csRcvCellDataTrnInf = new McReceiveCellDataIF[m_lDataNumTrnInfRcvCell];
                m_csSndCellDataTrnInf = new McSendCellDataIF[m_lDataNumTrnInfSncCell];

                int iRcvCnt = 0;
                int iSndCnt = 0;
                for (int i = 0; i < m_lInputDataNum; i++)
                {
                    HySID PttnID = ((McTranInfoCommon)m_csInputData[i].GetCommonInf()).GetRcvPatternID();
                    if (m_csInputData[i] is McTimeSeriesMutualCellTranInfor)
                    {
                        csPairInf = (McConnectPatternPairInfo)workSndRcvPtnTbl[PttnID];
                        if (csPairInf == null)
                        {
                            csPairInf = new McConnectPatternPairInfo();
                        }
                        else
                        {
                            workSndRcvPtnTbl.Remove(PttnID);
                        }

                        m_csRcvCellDataTrnInf[iRcvCnt] = ((McTranInfoIFCellType)((McTimeSeriesMutualCellTranInfor)m_csInputData[i]).GetDownstream()).GetReceiveCellData();
                        long RcvDim = m_csRcvCellDataTrnInf[iRcvCnt].GetCellDimention();
                        iRcvCnt += 1;
                        m_csSndCellDataTrnInf[iSndCnt] = ((McTranInfoIFCellType)((McTimeSeriesMutualCellTranInfor)m_csInputData[i]).GetUpstream()).GetSendCellData();
                        iSndCnt += 1;

                        csPairInf.m_PatternID = PttnID;
                        //csPairInf.m_Kbn = McSndRcvTypeKbn.Rcv;
                        csPairInf.m_RcvSndPairList.Add((m_csRcvCellDataTrnInf[iRcvCnt - 1], m_csSndCellDataTrnInf[iSndCnt - 1], RcvDim, McSndRcvTypeKbn.Rcv));
                        workSndRcvPtnTbl.Add(PttnID, csPairInf);
                    }
                    else
                    {
                        csPairInf = (McConnectPatternPairInfo)workOnlyRcvPtnTbl[PttnID];
                        if (csPairInf == null)
                        {
                            csPairInf = new McConnectPatternPairInfo();
                        }
                        else
                        {
                            workOnlyRcvPtnTbl.Remove(PttnID);
                        }

                        m_csRcvCellDataTrnInf[iRcvCnt] = ((McTranInfoIFCellType)m_csInputData[i]).GetReceiveCellData();
                        long RcvDim = m_csRcvCellDataTrnInf[iRcvCnt].GetCellDimention();
                        iRcvCnt += 1;

                        csPairInf.m_PatternID = PttnID;
                        //csPairInf.m_Kbn = McSndRcvTypeKbn.OnlyRcv;
                        csPairInf.m_RcvSndPairList.Add((m_csRcvCellDataTrnInf[iRcvCnt - 1], null, RcvDim, McSndRcvTypeKbn.OnlyRcv));
                        workOnlyRcvPtnTbl.Add(PttnID, csPairInf);
                    }
                }
                //-------------------------
                for (int i = 0; i < m_lOutputDataNum; i++)
                {
                    HySID PttnID = ((McTranInfoCommon)m_csOutputData[i].GetCommonInf()).GetRcvPatternID();

                    if (m_csOutputData[i] is McTimeSeriesMutualCellTranInfor)
                    {
                        ////HySID csBckObjID = new HySID("B)_" + CnnctID.ToString());
                        //HySID csBckObjID = ((McTimeSeriesMutualCellTranInfor)m_csOutputData[i]).GetUpStreamPtternID();
                        //string sss = csBckObjID.ToString();
                        //if( PttnID.ToString() != sss.Substring(3))
                        //{
                        //    int zzz = 0;
                        //    PttnID = new HySID(sss.Substring(3));
                        //}
                        csPairInf = (McConnectPatternPairInfo)workSndRcvPtnTbl[PttnID];
                        if (csPairInf == null)
                        {
                            csPairInf = new McConnectPatternPairInfo();
                        }
                        else
                        {
                            workSndRcvPtnTbl.Remove(PttnID);
                        }

                        m_csRcvCellDataTrnInf[iRcvCnt] = ((McTranInfoIFCellType)((McTimeSeriesMutualCellTranInfor)m_csOutputData[i]).GetUpstream()).GetReceiveCellData();
                        long RcvDim = m_csRcvCellDataTrnInf[iRcvCnt].GetCellDimention();
                        iRcvCnt += 1;
                        m_csSndCellDataTrnInf[iSndCnt] = ((McTranInfoIFCellType)((McTimeSeriesMutualCellTranInfor)m_csOutputData[i]).GetDownstream()).GetSendCellData();
                        iSndCnt += 1;

                        csPairInf.m_PatternID = PttnID;
                        //csPairInf.m_Kbn = McSndRcvTypeKbn.Snd;
                        csPairInf.m_RcvSndPairList.Add((m_csRcvCellDataTrnInf[iRcvCnt - 1], m_csSndCellDataTrnInf[iSndCnt - 1], RcvDim, McSndRcvTypeKbn.Snd));
                        workSndRcvPtnTbl.Add(PttnID, csPairInf);
                    }
                    else
                    {
                        csPairInf = (McConnectPatternPairInfo)workOnlySndPtnTbl[PttnID];
                        if (csPairInf == null)
                        {
                            csPairInf = new McConnectPatternPairInfo();
                        }
                        else
                        {
                            workOnlySndPtnTbl.Remove(PttnID);
                        }

                        m_csSndCellDataTrnInf[iSndCnt] = ((McTranInfoIFCellType)m_csOutputData[i]).GetSendCellData();
                        iSndCnt += 1;

                        csPairInf.m_PatternID = PttnID;
                        //csPairInf.m_Kbn = McSndRcvTypeKbn.OnlySnd;
                        csPairInf.m_RcvSndPairList.Add((null, m_csSndCellDataTrnInf[iSndCnt - 1], 0, McSndRcvTypeKbn.OnlySnd));
                        workOnlySndPtnTbl.Add(PttnID, csPairInf);
                    }

                }
                //------------  Calculate 引数作成 -------------
                // 受信のみ
                m_csRcvOnlyConnectionPatternList.Clear();
                long lNumConnectionPattern = 0;
                foreach (DictionaryEntry csDE in workOnlyRcvPtnTbl)
                {
                    m_csRcvOnlyConnectionPatternList.Add((McConnectPatternPairInfo)csDE.Value);
                    lNumConnectionPattern += 1;
                }
                List<McReceiveOnlyTranInfo> csRcvList = new List<McReceiveOnlyTranInfo>();
                for (int i = 0; i < lNumConnectionPattern; i++)
                {
                    for (int kk = 0; kk < m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        McReceiveOnlyTranInfo csReceiveOnlyTranInfo = new McReceiveOnlyTranInfo();
                        csReceiveOnlyTranInfo.m_PatternID = m_csRcvOnlyConnectionPatternList[i].m_PatternID;
                        var Dt = m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        csReceiveOnlyTranInfo.m_csRcvInf = Dt.Item1;
                        csReceiveOnlyTranInfo.m_DimNum = Dt.Item3;
                        csRcvList.Add(csReceiveOnlyTranInfo);
                    }
                }
                m_lOnlyReceveDataNum = csRcvList.Count;
                m_csOnlyReceiveCellData = csRcvList.ToArray();


                // 送信のみ
                m_csSendOnlyConnectionPatternList.Clear();
                lNumConnectionPattern = 0;
                foreach (DictionaryEntry csDE in workOnlySndPtnTbl)
                {
                    m_csSendOnlyConnectionPatternList.Add((McConnectPatternPairInfo)csDE.Value);
                    lNumConnectionPattern += 1;
                }
                List<McSendOnlyTranInfo> csSndList = new List<McSendOnlyTranInfo>();
                for (int i = 0; i < lNumConnectionPattern; i++)
                {
                    for (int kk = 0; kk < m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        McSendOnlyTranInfo csSndOnlyTranInfo = new McSendOnlyTranInfo();
                        csSndOnlyTranInfo.m_PatternID = m_csSendOnlyConnectionPatternList[i].m_PatternID;
                        var Dt = m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        csSndOnlyTranInfo.m_csSndInf = Dt.Item2;
                        csSndOnlyTranInfo.m_DimNum = Dt.Item3;
                        csSndList.Add(csSndOnlyTranInfo);
                    }
                }
                m_lOnlySendDataNum = csSndList.Count;
                m_csOnlySelDataCellData = csSndList.ToArray();

                // 送受信
                m_csMutualConnectionPatternList.Clear();
                lNumConnectionPattern = 0;
                foreach (DictionaryEntry csDE in workSndRcvPtnTbl)
                {
                    m_csMutualConnectionPatternList.Add((McConnectPatternPairInfo)csDE.Value);
                    lNumConnectionPattern += 1;
                }
                List<McRdvSndTranInfoPair> csRcvSndList = new List<McRdvSndTranInfoPair>();
                for (int i = 0; i < lNumConnectionPattern; i++)
                {
                    for (int kk = 0; kk < m_csMutualConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        McRdvSndTranInfoPair csRcvSndTranInfo = new McRdvSndTranInfoPair();
                        csRcvSndTranInfo.m_PatternID = m_csMutualConnectionPatternList[i].m_PatternID;
                        //csRcvSndTranInfo.m_Kbn = m_csMutualConnectionPatternList[i].m_Kbn;

                        var Dt = m_csMutualConnectionPatternList[i].m_RcvSndPairList[kk];
                        csRcvSndTranInfo.m_csRcvInf = Dt.Item1;
                        csRcvSndTranInfo.m_csSndInf = Dt.Item2;
                        csRcvSndTranInfo.m_DimNum = Dt.Item3;
                        csRcvSndTranInfo.m_Kbn = Dt.Item4;
                        csRcvSndList.Add(csRcvSndTranInfo);
                    }
                }
                m_lRcvSndDataNum = csRcvSndList.Count;
                m_csSndRcvCellData = csRcvSndList.ToArray();

                //-------------------------

                bool bRtn1 = CheckReceiveDataConnection(ref csErrorInf, m_lDataNumTrnInfRcvCell, m_csRcvCellDataTrnInf);
                if (bRtn1 == false)
                {
                    bRtn = false;
                }
                bool bRtn2 = CheckSendDataConnection(ref csErrorInf, m_lDataNumTrnInfSncCell, m_csSndCellDataTrnInf);
                if (bRtn2 == false)
                {
                    bRtn = false;
                }
            }
            catch(Exception e)
            {
                csErrorInf.AddCheckErrorData(this.GetID(), new HySObjectKind("McInterCnnctModel::SendConnectionCheck()"), " catch Exception " + e.ToString());
                bRtn = false;
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CheckReceiveDataConnection(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected virtual bool CheckReceiveDataConnection(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CheckSendDataConnection(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected virtual bool CheckSendDataConnection(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            // 同期型
            //m_eDtFusionTiming = McDefine.DataFusionTiming.SYNCHRONOUS;

            // 使用しやすいようにキャストしておく
            m_cInterCnnctCalInf = (McInterCnnctModelCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());
            }

            return true;
        }

        //public virtual long ReceiveData(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        //{

        //    return 0;
        //}

        
        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(ref csInitialData, ref csInputDataList, ref csOutputDataList)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        /// <param name="csOutputDataList">前段接続要素への伝送情報リスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Initialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList, ref HySDataLinkedList csOutputDataList)
        {
            bool bRtn = true;
            try
            {
                // 内挿処理に現在時刻を設定
                for (long lP = 0; lP < m_lInputDataNum; lP++)
                {   // 入力データ数分
                    if (m_InputCellData[lP] != null)
                    {
                        m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                    }
                }
                for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
                {
                    if (m_csSndCellDataTrnInf[lLp] != null)
                    {
                        m_csSndCellDataTrnInf[lLp].SetCurrentTime(this.m_csSimTime);
                    }
                }

                // デフォルトの値を送信準備
                HySCellData[] csSndCell = null;
                for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
                {
                    if (m_csSndCellDataTrnInf[lLp] != null)
                    {
                        csSndCell = m_csSndCellDataTrnInf[lLp].PrepareSendCellD1();
                    }
                }

                // 初期化
                bRtn = this.Initialize(ref csInitialData, m_lInputDataNum, ref m_InputCellData);

                if (bRtn == true)
                {
                    // 初期情報送信
                    bRtn = SendInitData(
                                m_lOnlySendDataNum, ref m_csOnlySelDataCellData,
                                m_lRcvSndDataNum, ref m_csSndRcvCellData);

                    // 送信
                    for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
                    {
                        if (m_csSndCellDataTrnInf[lLp] != null)
                        {
                            m_csSndCellDataTrnInf[lLp].SendData();
                        }
                    }
                }
            }
            catch( Exception ex)
            {
                string sClssName = $"クラス名＝{this.GetType().Name}";
                HySLog.LogOut(HySLog.ONLINE, "McOceanBaseModel::Initialize", " Catch.Exception in " + sClssName + "Calculate()" + " : Exception message = " + ex.Message);
                bRtn = false;
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>初期値の送信</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = SendInitData()</para>
        /// </example>
        /// <param name="lOnlySendDataNum">出力だけの情報数</param>
        /// <param name="csOnlySelDataCellData">出力だけの情報配列</param>
        /// <param name="lRcvSndDataNum">相互接続報数</param>
        /// <param name="csReceiveCellData">相互接続入力側情報配列</param>
        /// <param name="csSelDataCellData">相互接続出力側情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>派生クラス側で必ずオーバライドする必要がある</para>
        /// </remarks>
        protected abstract bool SendInitData(
                        long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
                        long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
                    );
        /// <summary>
        /// 受信
        /// </summary>
        protected abstract void ReceiveData();

        /// <summary>
        /// 送信例
        /// </summary>
        protected abstract void SendData();

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="csInputDataList">演算に必要な入力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>McBasicCalculateModelBase::Calculate　実装のオーバーライド</para>
        /// </remarks>
        public override long Calculate(ref HySDataLinkedList csInputDataList)
        {
            long lRtn = -1;
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lDataNumTrnInfRcvCell; lP++)
            {   // 入力データ数分
                if (m_csRcvCellDataTrnInf[lP] != null)
                {
                    m_csRcvCellDataTrnInf[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            // 各伝送データに現在時刻を指定して伝送するレコード情報を作成する
            for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
            {
                if (m_csSndCellDataTrnInf[lLp] != null)
                {
                    m_csSndCellDataTrnInf[lLp].SetCurrentTime(this.m_csSimTime);
                }
            }
            // 計算を行う
            try
            {
                // 受信情報取得
                ReceiveData();
                // 計算
                lRtn = this.Calculate(
                    m_lOnlyReceveDataNum, ref m_csOnlyReceiveCellData,
                    m_lOnlySendDataNum, ref m_csOnlySelDataCellData,
                    m_lRcvSndDataNum, ref m_csSndRcvCellData);
                // 送信情報設定
                SendData();
            }
            catch (Exception ex)
            {
                lRtn = -1;
                // ログ出力
                string sClssName = $"クラス名＝{this.GetType().Name}";
                HySLog.LogOut(HySLog.ONLINE, "McOceanBaseModel::Calculate", " Catch.Exception in " + sClssName + "Calculate()" + " : Exception message = " + ex.Message);
            }
            // データを出力する
            if (lRtn == 0)
            {
                //// 各伝送データに現在時刻を指定して伝送するレコード情報を作成する
                //for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
                //{
                //    if (m_csSndCellDataTrnInf[lLp] != null)
                //    {
                //        m_csSndCellDataTrnInf[lLp].SetCurrentTime(this.m_csSimTime);
                //    }
                //}
                // モデルがセットした伝送情報を　実際に伝送データとして流す
                for (long lLp = 0; lLp < m_lDataNumTrnInfSncCell; lLp++)
                {
                    if (m_csSndCellDataTrnInf[lLp] != null)
                    {
                        m_csSndCellDataTrnInf[lLp].SendData();
                    }
                }
            }
            return lRtn;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="lOnlyReceveDataNum">入力だけの情報数</param>
        /// <param name="csOnlyReceiveCellData">入力だけの情報配列</param>
        /// <param name="lOnlySendDataNum">出力だけの情報数</param>
        /// <param name="csOnlySelDataCellData">出力だけの情報配列</param>
        /// <param name="lRcvSndDataNum">相互接続報数</param>
        /// <param name="csReceiveCellData">相互接続入力側情報配列</param>
        /// <param name="csSelDataCellData">相互接続出力側情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>派生クラス側で必ずオーバライドする必要がある</para>
        /// </remarks>
        protected abstract long Calculate(
            long lOnlyReceveDataNum, ref McReceiveOnlyTranInfo[] csOnlyReceiveCellData,
            long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
            long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
            );


        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            // ここで、何もしないことが重要
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>複数接続があった場合、全て同じ情報が出ることに注意（流量を分配して出しているわけではない）</para>
        /// </remarks>
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            // ここで、何もしないことが重要
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion(ref csOutputDataList)</para>
        /// </example>
        /// <param name="csOutputDataList">演算結果を公開する出力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>>McBasicCalculateModelBase::DataFusion　実装のオーバーライド</para>
        /// </remarks>
        public override long DataFusion(ref HySDataLinkedList csOutputDataList)
        {
            // ここで、何もしないことが重要
            return 0;
        }
    
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する(将来拡張用)</para>
        /// </remarks>
        public override bool SetOnlineProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            // Do Nothing
            return true;
        }
   
    }
}
