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

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.CoreOptionl.HymcoExpansionModel;
using CommonMP.HYMCO.Ocean.McOceanBaseModel;

namespace CommonMP.HYMCO.Ocean.McOceanSampleModels
{
    /// <summary><para>class outline:</para>
    /// <para> ネクトン類（Nekton)   モデルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2021/12/31][新規作成]</para>
    public class MzOceanNektons : MzOceanZpoplanktons
    {
        /// <summary> 演算データ（キャスト用） </summary>
        MzOceanNektonsCalInfo m_NktnInf = null; // 便利の為、キャスト用に定義しておく

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

        /// <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 override bool CheckReceiveDataConnection(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            // チェック処理を入れる
            bool bRtn = base.CheckReceiveDataConnection(ref csErrorInf, lInputDataNum, csInputCellData);
            //// ディバッグ用送信データ
            //m_csDebugSendCnnct = this.PrepareSndPattern(MzOceanBaseDefine.DEBUG_OUT);
            return bRtn;
        }
        ///// <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 override bool CheckSendDataConnection(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        //{
        //    // チェック処理を入れる
        //    bool bRtn = base.CheckSendDataConnection(ref csErrorInf, lOutputDataNum, csOutputCellData);
        //    return bRtn;
        //}


        protected override void SendDEBUG()
        {
            for (int i = 0; i < m_csDebugSendCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csDebugSendCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                for (int ll = 0; ll < m_NktnInf.m_lLayerNumber; ll++)
                {
                    csCell[ll].m_dData[0] = m_NktnInf.m_TotalSelfMass[ll];
                    csCell[ll].m_dData[1] = m_NktnInf.m_O2[ll];
                    csCell[ll].m_dData[2] = m_NktnInf.m_CO2[ll];
                }
            }
        }


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

        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            ClearAllCalValue();

            // 呼吸の蓄えの一部を無駄にする：絶えず呼吸が必要
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_csOcnBacedlInf.m_O2[ll] = 0.66 * m_csOcnBacedlInf.m_O2[ll];
            }

            // 呼吸関係
            ReceiveBREATHING();

            // 捕食：人間による漁獲等の要求量の取得
            ReceiveReqPREDATION();
            // 動物プランクトン等の取得
            ReceivePREDATION();

            m_NktnInf.d_TotalIN = 0.0;
            for (int i = 0; i < m_NktnInf.m_lLayerNumber; i++)
            {
                m_NktnInf.d_TotalIN += m_NktnInf.m_EatenMass[i];
            }
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            // 捕食/被捕食
            SendPREDATION(m_csOcnBacedlInf.m_dCapturedMass, 0.1, 0.005);
            SendReqPREDATION(m_NktnInf.m_ReqFoodMass);

            // 呼吸
            SendBREATHING();

            // 糞・死
            SendEXCRETION_DEATH(m_csOcnBacedlInf.m_dExcretionDencity, m_csOcnBacedlInf.m_dBulkDensity);

            // Debug
            SendDEBUG();

            //----- Debug Check ------
            double dChk = (m_NktnInf.d_NowTotalMass - m_NktnInf.d_PreTotalMass) - (m_NktnInf.d_TotalIN - m_NktnInf.d_TotalOUT);
            McLog.DebugOut("MzOceanNektons", "SendData", "ネクトン総量チェック:" + dChk.ToString() + " = "
                + (m_NktnInf.d_NowTotalMass - m_NktnInf.d_PreTotalMass).ToString() + " - " + (m_NktnInf.d_TotalIN - m_NktnInf.d_TotalOUT).ToString());
            //------------------------

            return;
        }

        protected override long Calculate(
                            long lOnlyReceveDataNum, ref McReceiveOnlyTranInfo[] csOnlyReceiveCellData,
                            long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
                            long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
                            )
        {
            // 親クラスの計算を呼ぶ
            long lRtn = base.Calculate(lOnlyReceveDataNum, ref csOnlyReceiveCellData, lOnlySendDataNum, ref csOnlySelDataCellData, lRcvSndDataNum, ref csRcvSndCelDataCellData);
            return 0;
        }


        //====================
        // その他必要なメソッド
        //====================


        /// <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_NktnInf = (MzOceanNektonsCalInfo)m_csCalInfo; 

            bool bRtn = base.SetProperty(csCellMdlPropertyInfo);

            //// プロパティ設定
            //McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            //if (csPrptyInfo != null)
            //{
            //}
            return true;
        }
    }
}
