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.HSViewer;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

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

using CommonMP.HYMCO.CoreImpl.Data;

using CommonMP.HYMCO.CoreOptionl.HymcoExpansionModel;

namespace CommonMP.HYMCO.Ocean.McOceanBaseModel
{
    /// <summary><para>class outline:</para>
    /// <para>海洋モデル内演算中データクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2021/12/31][新規作成]</para>
    /// <para>remarks</para>
    /// <para>演算中の状態、初期条件等を保持するデータクラス</para>
    /// </remarks>
    [Serializable]
    public class MzOceanModelElementCalInfo : McInterCnnctModelCalInfo
    {
        /// <summary>セルの平面面積 20Km * 20Km</summary>
        static public double m_dFace = 20000.0 * 20000.0;
  
        //========================================================
        /// <summary> XYで区切られた海洋に於いて、自分が含まれる海域のＸ軸番号：将来用 </summary>
        public long m_XLonCellPosNo = 0;
        /// <summary> XYで区切られた海洋に於いて、自分が含まれる海域のＹ軸番号：将来用 </summary>
        public long m_YLatCellPosNo = 0;

        // 計算用データの変数
        /// <summary>層番号 : 深さ方向へ分割 </summary>
        public long m_lLayerNumber = 7;

        /// <summary>トータル深さ幅　ｍ </summary>
        public double m_dDepth = 6000.0;
        /// <summary>深さ方向層深さ</summary>
        public double[] m_dLayerLength = null;
        //　-----------------------
        // 代謝に関する係数（１日当たり）
        /// <summary>一個体のサイズ mm </summary>
        public double m_dSelfSize = 1.0;
        /// <summary>一個体の体重 g </summary>
        public double m_dSelfWeight = 1.0;
        /// <summary>一個体比重 </summary>
        public double m_dBulkDensity = 1.1;

        /// <summary>一日に必要な捕食量：個体毎：自体重の 30% </summary>
        public double m_dEatK = 0.3;
        /// <summary>一日の代謝による体重減少量： 全重量の 2% </summary>
        public double m_dMetabolismK = 0.02;
        /// <summary> １日当たりの最大増殖率 </summary>
        public double m_dMaxProliferation = 0.2;
        /// <summary>排泄量：一回の捕食量の 95% </summary>
        public double m_dEexcretionRatio = 0.95;
        /// <summary>排泄物サイズ：自サイズの 10% </summary>
        public double m_dEexcretionSize = 0.1;
        /// <summary>体の密度増加係数 </summary>
        public double m_dIncDctyRatio = 1.03;

        //　-----------------------
        // 捕食関係（１日当たり）
        /// <summary> 非捕獲率 </summary>
        public double m_CapturedRatio = 0.1;
        /// <summary>捕食した質量の累積 g/m3</summary>
        public double[] m_TotalEatenMass = null;
        /// <summary>★：自身の質量 g/m3</summary>
        public double[] m_TotalSelfMass = null;
        /// <summary>餌の資源量 g/m3</summary>
        public double[] m_TotalFoodMass = null;
        /// <summary>要求質量 g/m3</summary>
        public double[] m_TotalReqedPredationMass = null;
        /// <summary>捕獲された質量 g/m3</summary>
        public double[] m_dCapturedMass = null;

        /// <summary>餌の要求量 g/m3</summary>
        public double[] m_ReqFoodMass = null;
        /// <summary>捕食した質量：１回の計算時間内」g/m3</summary>
        public double[] m_EatenMass = null;
        /// <summary>排泄した質量：１回の計算時間内」 g/m3</summary>
        public double[] m_ExcretionMass = null;
        /// <summary>排泄の比重 </summary>
        public double[] m_dExcretionDencity = null;

        //　-----------------------
        // 呼吸関係（１日当たり）
        /// <summary> 呼吸O2要求量[g/g]：単位体重量あたり </summary>
        public double m_O2AbsRatio = 16E-6 * 1E3;
        /// <summary> 代謝によるCO2発生量[g/g]：単位体重量あたり </summary>
        public double m_CO2GenRatio = 28E-6 * 1E3;
        /// <summary>要求するO2</summary>
        public double[] m_ReqO2 = null;
        /// <summary>O2</summary>
        public double[] m_O2 = null;
        /// <summary>CO2</summary>
        public double[] m_CO2 = null;
        /// <summary>その他ガス１</summary>
        public double[] m_Gass1 = null;
        /// <summary>その他ガス２</summary>
        public double[] m_Gass2 = null;

        //　-----------------------
        // 死関係（１日当たり）
        /// <summary>死亡率：１日当たり </summary>
        public double m_dDeathRatio = 0.001;
        /// <summary>死んだ質量：１日当たり」g/m3</summary>
        public double[] m_Death = null;

        //-------　元素　-----------
        /// <summary>窒素 g/m3</summary>
        public double[] m_N = null;
        /// <summary>リン量 g/m3</summary>
        public double[] m_P = null;
        /// <summary>珪素量 g/m3</summary>
        public double[] m_Si = null;
        /// <summary>鉄量 g/m3</summary>
        public double[] m_Fe = null;

        /// <summary>炭素量 g/m3</summary>
        public double[] m_C = null;
        /// <summary>粒子状有機物（POM）g/m3</summary>
        public double[] m_POM = null;
        /// <summary>溶存有機物（DOM）g/m3</summary>
        public double[] m_DOM = null;
        /// <summary>無機物粒子 g/m3</summary>
        public double[] m_IOP = null;

        //public HySDataHashTable m_RcvDataTbl = new HySDataHashTable();
        //public HySDataHashTable m_SndDataTbl = new HySDataHashTable();

        /// <summary> 人間の行為間隔  </summary>
        //public double m_HmnActTimeSpan = 24 * 3600;

        ////-----------------------------------
        //// 入力データ、出力データの対応
        ////public int m_iInputDtNum = 0;
        //public int[] m_iInKindNo = null;
        //public int[][] m_InDtNo = null;
        ////public int m_iOutputDtNum = 0;
        //public int[] m_iOutKindNo = null;
        //public int[][] m_OutDtNo = null;
        ////-----------------------------------

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MzOceanModelElementCalInfo()
        {
            this.SetLayerNum(7);
            this.m_dDepth = 6000.0;
            //this.m_dFace = 100E3 * 100E3;

            this.m_dLayerLength[0] = 15;   //  "表層混合層(surface mixed layer)"  ;日本近海において、夏季は10～20m程度であるのに対し、冬季は100mを超える
            this.m_dLayerLength[1] = 100 - 15;  // "真光層（euphotic zone)";
            this.m_dLayerLength[2] = 200 - 100;  // "透光層(disphotic zone)";
            this.m_dLayerLength[3] = 1000 - 200;  // "中深層（Mesopelagic zone)";
            this.m_dLayerLength[4] = 3000 - 1000;  // "漸深層（Bathypelagic zone)";
            this.m_dLayerLength[5] = m_dDepth - 3000 -1;  //  "深海層（Abyssopelagic zone)";
            this.m_dLayerLength[6] = 1;  // "海底（Bottom）";

            //m_iInKindNo = new int[McOceanBaseDefine.TransDataKindNum];
            //m_InDtNo = new int[McOceanBaseDefine.TransDataKindNum][];
            //m_iOutKindNo = new int[McOceanBaseDefine.TransDataKindNum];
            //m_OutDtNo = new int[McOceanBaseDefine.TransDataKindNum][];
        }

        public virtual void SetLayerNum( long iLayerNum)
        {
            this.m_lLayerNumber = iLayerNum;

            this.m_dDepth = 6000.0;
            //this.m_dFace = 20E3 * 20E3;

            this.m_dLayerLength = new double[this.m_lLayerNumber];
            for (int i = 0; i < m_lLayerNumber; i++) { this.m_dLayerLength[i] = 1.0; }
            if (m_lLayerNumber >= 7)
            {
                this.m_dLayerLength[0] = 15;   //  "表層混合層(surface mixed layer)"  ;日本近海において、夏季は10～20m程度であるのに対し、冬季は100mを超える
                this.m_dLayerLength[1] = 100 - 15;  // "真光層（euphotic zone)";
                this.m_dLayerLength[2] = 200 - 100;  // "透光層(disphotic zone)";
                this.m_dLayerLength[3] = 1000 - 200;  // "中深層（Mesopelagic zone)";
                this.m_dLayerLength[4] = 3000 - 1000;  // "漸深層（Bathypelagic zone)";
                this.m_dLayerLength[5] = m_dDepth - 3000 - 1;  //  "深海層（Abyssopelagic zone)";
                this.m_dLayerLength[iLayerNum-1] = 1;  // "海底（Bottom）";
            }

            this.m_TotalEatenMass = new double[this.m_lLayerNumber];
            this.m_TotalSelfMass = new double[this.m_lLayerNumber];
            this.m_TotalFoodMass = new double[this.m_lLayerNumber];
            this.m_TotalReqedPredationMass = new double[this.m_lLayerNumber];
            this.m_ReqFoodMass = new double[this.m_lLayerNumber];
            this.m_EatenMass = new double[this.m_lLayerNumber];
            this.m_ExcretionMass = new double[this.m_lLayerNumber];
            this.m_dCapturedMass = new double[this.m_lLayerNumber];
            this.m_Death = new double[this.m_lLayerNumber];
            this.m_dExcretionDencity = new double[this.m_lLayerNumber];
            this.m_O2 = new double[this.m_lLayerNumber];
            this.m_ReqO2 = new double[this.m_lLayerNumber];
            this.m_CO2 = new double[this.m_lLayerNumber];
            this.m_Gass1 = new double[this.m_lLayerNumber];
            this.m_Gass2 = new double[this.m_lLayerNumber];

            this.m_N = new double[this.m_lLayerNumber];
            this.m_P = new double[this.m_lLayerNumber];
            this.m_Si = new double[this.m_lLayerNumber];
            this.m_Fe = new double[this.m_lLayerNumber];
            this.m_C = new double[this.m_lLayerNumber];
            this.m_POM = new double[this.m_lLayerNumber];
            this.m_DOM = new double[this.m_lLayerNumber];
            this.m_IOP = new double[this.m_lLayerNumber];

            for(int ll=0;ll< this.m_lLayerNumber;ll++)
            {
                this.m_TotalEatenMass[ll]=0.0;
                this.m_TotalSelfMass[ll] = 0.0;
                this.m_TotalFoodMass[ll] = 0.0;
                this.m_TotalReqedPredationMass[ll] = 0.0;
                this.m_EatenMass[ll] = 0.0;
                this.m_ExcretionMass[ll] = 0.0;
                this.m_Death[ll] = 0.0;
                this.m_dExcretionDencity[ll] = 1.03;

                this.m_O2[ll] = 0.0;
                this.m_ReqO2[ll] = 0.0;
                this.m_CO2[ll] = 0.0;
                this.m_Gass1[ll] = 0.0;
                this.m_Gass2[ll] = 0.0;

                this.m_N[ll] = 0.0;
                this.m_P[ll] = 0.0;
                this.m_Si[ll] = 0.0;
                this.m_Fe[ll] = 0.0;
                this.m_C[ll] = 0.0;
                this.m_POM[ll] = 0.0;
                this.m_DOM[ll] = 0.0;
                this.m_IOP[ll] = 0.0;
            }
      
        }

        public virtual void Clear()
        {
            for (int ll = 0; ll < this.m_lLayerNumber; ll++)
            {
                this.m_TotalEatenMass[ll] = 0.0;
                this.m_TotalSelfMass[ll] = 0.0;
                this.m_TotalFoodMass[ll] = 0.0;
                this.m_TotalReqedPredationMass[ll] = 0.0;
                this.m_ReqFoodMass[ll] = 0.0;
                this.m_EatenMass[ll] = 0.0;
                this.m_dCapturedMass[ll] = 0.0;
                this.m_ExcretionMass[ll] = 0.0;
                this.m_Death[ll] = 0.0;
                this.m_dExcretionDencity[ll] = 1.03;

                this.m_O2[ll] = 0.0;
                this.m_ReqO2[ll] = 0.0;
                this.m_CO2[ll] = 0.0;
                this.m_Gass1[ll] = 0.0;
                this.m_Gass2[ll] = 0.0;

                this.m_N[ll] = 0.0;
                this.m_P[ll] = 0.0;
                this.m_Si[ll] = 0.0;
                this.m_Fe[ll] = 0.0;
                this.m_C[ll] = 0.0;
                this.m_POM[ll] = 0.0;
                this.m_DOM[ll] = 0.0;
                this.m_IOP[ll] = 0.0;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>自己複製</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Clone( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>同一内容で　別院スタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>収束演算時、特定の時刻に状態を戻す場合等に使用する</para>
        /// </remarks>
        public override McCalInfo Clone()
        {
            MzOceanModelElementCalInfo csRtn = new MzOceanModelElementCalInfo();
            csRtn.CopyInfo(this);
            return csRtn;
        }

        /// <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 override bool CopyInfo(McCalInfo csOrgInfo)
        {
            MzOceanModelElementCalInfo csOrgDt = (MzOceanModelElementCalInfo)csOrgInfo;

            this.SetLayerNum(csOrgDt.m_lLayerNumber);

            for (long lLp = 0; lLp < csOrgDt.m_lLayerNumber; lLp++)
            {
                this.m_XLonCellPosNo = csOrgDt.m_XLonCellPosNo;
                this.m_YLatCellPosNo = csOrgDt.m_YLatCellPosNo;

                this.m_TotalSelfMass[lLp] = csOrgDt.m_TotalSelfMass[lLp];
                this.m_TotalFoodMass[lLp] = csOrgDt.m_TotalFoodMass[lLp];
                this.m_TotalReqedPredationMass[lLp] = csOrgDt.m_TotalReqedPredationMass[lLp];
                this.m_ReqFoodMass[lLp] = csOrgDt.m_ReqFoodMass[lLp]; 
                this.m_EatenMass[lLp] = csOrgDt.m_EatenMass[lLp]; 
                this.m_dCapturedMass[lLp] = csOrgDt.m_dCapturedMass[lLp];
                this.m_ExcretionMass[lLp] = csOrgDt.m_ExcretionMass[lLp];
                this.m_Death[lLp] = csOrgDt.m_Death[lLp];

                this.m_O2[lLp] = csOrgDt.m_O2[lLp];
                this.m_ReqO2[lLp] = csOrgDt.m_ReqO2[lLp];                
                this.m_CO2[lLp] = csOrgDt.m_CO2[lLp];
                this.m_Gass1[lLp] = csOrgDt.m_Gass1[lLp];
                this.m_Gass2[lLp] = csOrgDt.m_Gass2[lLp];
                this.m_N[lLp] = csOrgDt.m_N[lLp];
                this.m_P[lLp] = csOrgDt.m_P[lLp];
                this.m_Si[lLp] = csOrgDt.m_Si[lLp];
                this.m_Fe[lLp] = csOrgDt.m_Fe[lLp];
                this.m_C[lLp] = csOrgDt.m_C[lLp];
                this.m_POM[lLp] = csOrgDt.m_POM[lLp];
                this.m_DOM[lLp] = csOrgDt.m_DOM[lLp];
                this.m_IOP[lLp] = csOrgDt.m_IOP[lLp];

                this.m_dLayerLength[lLp] = csOrgDt.m_dLayerLength[lLp];
            }

            this.m_dDepth = csOrgDt.m_dDepth;
            //this.m_dFace = csOrgDt.m_dFace;

            this.m_dSelfSize = csOrgDt.m_dSelfSize;
            this.m_dSelfWeight = csOrgDt.m_dSelfWeight;
            this.m_dEatK = csOrgDt.m_dEatK;
            this.m_dIncDctyRatio = csOrgDt.m_dIncDctyRatio;
            this.m_dMaxProliferation = csOrgDt.m_dMaxProliferation;   
            this.m_dEexcretionRatio = csOrgDt.m_dEexcretionRatio;
            this.m_dEexcretionSize = csOrgDt.m_dEexcretionSize;

            return true;
        }

    }

}
