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> 海洋関連 人間の行動 (HumanAct) モデルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2021/12/31][新規作成]</para>
    public class MzOceanHumanAct : MzOceanModelElement
    {
        /// <summary> 演算データ（キャスト用）便利の為、キャスト用に定義しておく</summary>
        protected MzOceanHumanActCalInfo m_HmnActInf = null;

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

        // CO2排出： McOceanBaseDefine.CO2_EMISSION
        protected McPatternRdvSndTranInfoPair m_csRcvCO2DmyCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndCO2EmissionCnnct = new McPatternRdvSndTranInfoPair();

        // 運航コスト
        protected McPatternRdvSndTranInfoPair m_csRcvECCostCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndECCostCnnct = new McPatternRdvSndTranInfoPair();


        /// <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_csRcvECCostCnnct, m_csSndECCostCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.CHASH);

            // CO2排出
            (m_csRcvCO2DmyCnnct, m_csSndCO2EmissionCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.CO2_EMISSION);

            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);
            McInitialInfo csInDt = csInitialData as McInitialInfo;
            if (csInDt != null)
            {   // 初期化情報有り

                csInDt.GetInfo("m_Facility", ref m_HmnActInf.m_Facility);
                csInDt.GetInfo("m_DepreciationRate", ref m_HmnActInf.m_DepreciationRate);
                csInDt.GetInfo("m_CapitalStock", ref m_HmnActInf.m_CapitalStock);
                csInDt.GetInfo("m_Chash", ref m_HmnActInf.m_Chash);
                csInDt.GetInfo("m_Debt", ref m_HmnActInf.m_CapitalStock);
                csInDt.GetInfo("m_DebtInterestRate", ref m_HmnActInf.m_Chash);
                csInDt.GetInfo("m_Credit", ref m_HmnActInf.m_CapitalStock);
                csInDt.GetInfo("m_CreditInterestRate", ref m_HmnActInf.m_Chash);
                csInDt.GetInfo("m_dNextDealingChash", ref m_HmnActInf.m_dNextDealingChash);
                csInDt.GetInfo("m_dNowUnitCost", ref m_HmnActInf.m_dNowUnitCost);
            }
            return true;
        }

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

        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            // 人間行為によって消費するO2：受信
            ReceiveO2Consumption();
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            // 人間行為によって排出するCO2：送信
            SendCO2Emission();
            return;
        }

        /// <summary>
        /// 人間行為によって消費するO2：受信
        /// </summary>
        protected virtual void ReceiveO2Consumption()
        {
            //------------------------
            //  O2を受け取る               
            for (int i = 0; i < m_csSndCO2EmissionCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndCO2EmissionCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    // O2
                    m_HmnActInf.m_HmnRcvO2 += csCell[0].m_dData[0];
                }
            }

        }

        /// <summary>
        /// 人間行為によって排出するCO2：送信
        /// </summary>
        protected virtual void SendCO2Emission()
        {
            HySCellData[] csSndDt = null;

            // CO2量排出とO2要求量を送る
            for (int i = 0; i < m_csSndCO2EmissionCnnct.m_RcvInfNum; i++)
            {
                csSndDt = m_csSndCO2EmissionCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }

                csSndDt[0].m_dData[0] = m_HmnActInf.m_HmnCO2Emission;
                csSndDt[0].m_dData[1] = m_HmnActInf.m_HmnReqO2;
            }
        }


        /// <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
            )
        {
            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_HmnActInf = (MzOceanHumanActCalInfo)m_csCalInfo;

            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                double dDay = 0.0;
                csPrptyInfo.GetInfo("m_HmnActTimeSpan", ref dDay);
                m_HmnActInf.m_HmnActTimeSpan = dDay * 24 * 3600;

                double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);  
                double dDD = 0.0;
                csPrptyInfo.GetInfo("m_HmnCO2EmissionDay", ref dDD);
                m_HmnActInf.m_HmnCO2EmissionDay = dDD * 1E3; // * dT;


                m_HmnActInf.m_HmnCO2Emission = m_HmnActInf.m_HmnCO2EmissionDay * dT;
                m_HmnActInf.m_HmnReqO2 =  (32.0 / 44.0) * m_HmnActInf.m_HmnCO2EmissionDay * dT;
            }

            return true;
        }

        /// <summary>
        /// 人間行為の間隔
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        protected virtual void SetHumanActionSpanTime(ref McCellModelPropertyInfo csPrptyInfo)
        {
            csPrptyInfo.GetInfo("m_HmnActTimeSpan", ref m_HmnActInf.m_HmnActTimeSpan);
            m_HmnActInf.m_HmnActTimeSpan = m_HmnActInf.m_HmnActTimeSpan * 24.0 * 3600.0;
        }

        protected virtual double GetHumanActionCO2Emission(ref McCellModelPropertyInfo csPrptyInfo)
        {
            double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
            double dDD = 0.0;
            csPrptyInfo.GetInfo("m_HmnCO2EmissionDay", ref dDD);
            return dDD * 1E3; // * dT;
        }
    }
}
