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;

namespace CommonMP.HYMCO.Ocean.McOceanBaseModel
{
    /// <summary><para>class outline:</para>
    /// <para> 海の地域１単位面(Ocean Column)モデルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2021/12/31][新規作成]</para>
    public class MzOceanAreaColumnModel : MzOceanModelElement
    {

        /// <summary> 演算データ（キャスト用） </summary>
        MzOceanAreaColumnModelCalInfo m_OcLyrMdlInf = null; // 便利の為、キャスト用に定義しておく


        //----------------------------------
        public MzOceanAreaColumnModel()
        {
        }

        /// <summary> ワーク：量 </summary>
        protected double[] m_dWorkMass = null;

        //=========================
        // 演算実行前処理関連メソッド
        //=========================
        public MzOceanAreaColumnModelCalInfo GetOcnColumModel(long x, long y)
        {
            return m_OcLyrMdlInf;
        }

        /// <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);
            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;
        //}

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = base.Initialize(ref csInitialData, lInputDataNum, ref csInputCellData);
            for (int ll = 0; ll < m_OcLyrMdlInf.m_lLayerNumber; ll++)
            {
                m_OcLyrMdlInf.m_meanAllMass[ll] = m_OcLyrMdlInf.m_TotalSelfMass[ll];
            }

            McInitialInfo csInDt = csInitialData as McInitialInfo;
            //if (csInDt != null)
            //{   // 初期化情報有り
  
            //    }
            //}
            return bRtn;
        }

        //=======================
        // 演算実行処理関連メソッド
        //=======================
        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            return;
        }

        /// <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 override long Calculate(
            long lOnlyReceveDataNum, ref McReceiveOnlyTranInfo[] csOnlyReceiveCellData,
            long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
            long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
            )
        {
            double dltT = m_csDltTime.TotalSec();
            //------------------------------------------------------
            //// 沈降
            //this.SinkingParticle();

            double dWorkSum = 0.0;
            for (int ll = 0; ll < m_OcLyrMdlInf.m_lLayerNumber; ll++)
            {
                dWorkSum = m_OcLyrMdlInf.m_TotalSelfMass[ll];
                //dWorkSum += m_OcLyrMdlInf.m_SumDetritusMass[ll];
                dWorkSum += m_OcLyrMdlInf.m_IOP[ll];
                m_OcLyrMdlInf.m_meanAllMass[ll] = dWorkSum; // / dltT;


                m_OcLyrMdlInf.m_TotalSelfMass[ll] = 0.0; 
                m_OcLyrMdlInf.m_IOP[ll] = 0.0;
            }

            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)
        {
            base.SetProperty(csCellMdlPropertyInfo);

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

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 各種係数設定
                csPrptyInfo.GetInfo("L0", ref m_OcLyrMdlInf.m_sLayerName[0]);
                csPrptyInfo.GetInfo("L1", ref m_OcLyrMdlInf.m_sLayerName[1]);
                csPrptyInfo.GetInfo("L2", ref m_OcLyrMdlInf.m_sLayerName[2]);
                csPrptyInfo.GetInfo("L3", ref m_OcLyrMdlInf.m_sLayerName[3]);
                csPrptyInfo.GetInfo("L4", ref m_OcLyrMdlInf.m_sLayerName[4]);
                csPrptyInfo.GetInfo("L5", ref m_OcLyrMdlInf.m_sLayerName[5]);
                csPrptyInfo.GetInfo("L6", ref m_OcLyrMdlInf.m_sLayerName[6]);

                double dDt = 100;
                csPrptyInfo.GetInfo("m_dFace", ref dDt);
                MzOceanModelElementCalInfo.m_dFace = (dDt * 1E3) * (dDt * 1E3);  // Km2 を m2 に変換

            }

            m_dWorkMass = new double[m_OcLyrMdlInf.m_iDetritusSizeNum];
            for(int j=0;j< m_OcLyrMdlInf.m_iDetritusSizeNum;j++)
            {
                m_dWorkMass[j] = 0.0;
            }

            return true;
        }


        ///// <summary><para>method outline:</para>
        ///// <para>深さ方向への物質沈降</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para>SinkingParticle()</para>
        ///// </example>
        ///// <returns>無し</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para>δＴ時間に沈降する物質量 </para>
        ///// </remarks>
        //protected int SinkingParticle()
        //{
        //    double dSec = GetDeltaTime().GetTime();
        //    double dDpth = 0.0;  // 沈降の深さ
        //    double dMass = 0.0;  // 量
        //    double dHH = m_OcLyrMdlInf.m_dDepth - m_OcLyrMdlInf.m_dCelLength[m_OcLyrMdlInf.m_lLayerNumber - 1];
        //    for( long k = m_OcLyrMdlInf.m_lLayerNumber-2; k>= 0; k--)
        //    {

        //        // 粒子状無機物（InOrganic_Particulates） 計算
        //        for (int i = 0; i < m_OcLyrMdlInf.m_iDetritusSizeNum; i++)
        //        {
        //            dDpth = dSec * DroppingV((dHH + m_OcLyrMdlInf.m_dCelLength[k] / 2.0), m_OcLyrMdlInf.m_DetritusSize[i], m_OcLyrMdlInf.m_DensityIOP);
        //            dMass = dDpth * (m_OcLyrMdlInf.m_IOPMass[k][i] / m_OcLyrMdlInf.m_dCelLength[k]);
        //            m_OcLyrMdlInf.m_IOPMass[k][i] += dMass;
        //            m_OcLyrMdlInf.m_IOPMass[k + 1][i] += dMass;
        //        }

        //        dHH -= m_OcLyrMdlInf.m_dCelLength[k];
        //    }  // end of for(層No)

        //    //------------------------
        //    // データの集計
        //    for (long k = 0; k< m_OcLyrMdlInf.m_lLayerNumber;k++)
        //    {
        //        //m_csOcnBacedlInf.m_ExcretionMass[k] = 0;
        //        m_OcLyrMdlInf.m_IOP[k] = 0;

        //        // 粒子状無機物（InOrganic_Particulates） 計算
        //        for (int i = 0; i < m_OcLyrMdlInf.m_iDetritusSizeNum; i++)
        //        {
        //            m_OcLyrMdlInf.m_IOP[k] += m_OcLyrMdlInf.m_IOPMass[k][i];
        //        }
        //    }
        //    return 0;
        //}

   
    }
}
