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> 肥料工場</para>
    /// 入力：原料（購入金）、　　　投資（投資配当）
    /// 出力、肥料（売上金）、      CO2（O2使用）
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2022/4/29][新規作成]</para>
    public class MzHmnFertilizerFactory : MzCashflowModelElement
    {
        /// <summary> 演算データ（キャスト用） </summary>
        protected MzHmnFertilizerFactoryCalInfo m_HmnFrtInf = null; // 便利の為、キャスト用に定義しておく

        //========================================================
        //========================================================

        // 人間による施肥料 ：     McOceanBaseDefine.HUMAN_FERTILIZER_KIND  
        // 仕込み品（積み荷）
        protected McPatternRdvSndTranInfoPair m_csSndHmnFertilizerCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csDmyCnnct = 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_csSndHmnFertilizerCnnct = this.PrepareSndPattern(MzOceanBaseDefine.EC_HUMAN_FERTILIZER);
 
            //// コスト　　＜－－親クラスで行っている
            //(m_csRcvECCostCnnct, m_csSndECCostCnnct) = this.PrepareRcvSndPattern(McOceanBaseDefine.CHASH);

            //// CO2排出　＜－－親クラスで行っている
            //(m_csRcvCO2DmyCnnct, m_csSndCO2EmissionCnnct) = this.PrepareRcvSndPattern(McOceanBaseDefine.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)
            {   // 初期化情報有り
                double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
                m_HmnFrtInf.m_N_Fertilize = m_HmnFrtInf.m_N * dT;
                m_HmnFrtInf.m_P_Fertilize = m_HmnFrtInf.m_P * dT;
                m_HmnFrtInf.m_IOPMass_Si = m_HmnFrtInf.m_SI * dT;
                m_HmnFrtInf.m_IOPMass_Fe = m_HmnFrtInf.m_FE * dT;
            }
            return true;
        }
        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            // 操業
            ExpenseReceive();

            //原料受信
            BuyerReceive();

            //人間行為によって消費するO2：受信
            ReceiveO2Consumption();
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            //原料買い付け
            BuyerSend();

            if (m_ActionFlg == true)
            {
                SendDEBUG();

                // 工場からの肥料出荷：船舶積み込み
                SendFertilizer();

            }

            // 操業アウトプット
            OutcomeSend();

            // 人間行為によって排出するCO2：送信
            SendCO2Emission();

            ////----- Debug Check ------
            //double dChk = (m_DtrtsInf.d_NowTotalMass - m_DtrtsInf.d_PreTotalMass) - (m_DtrtsInf.d_TotalIN - m_DtrtsInf.d_TotalOUT);
            //McLog.DebugOut("MzOceanDetritus", "SendData", "デトリタス総量チェック:" + dChk.ToString() + " = "
            //    + (m_DtrtsInf.d_NowTotalMass - m_DtrtsInf.d_PreTotalMass).ToString() + " - " + (m_DtrtsInf.d_TotalIN - m_DtrtsInf.d_TotalOUT).ToString());
            ////------------------------
            return;
        }

        /// <summary>
        /// 工場からの肥料出荷：船舶積み込み
        /// </summary>
        protected virtual void SendFertilizer()
        {
            if (m_csSndHmnFertilizerCnnct.m_RcvInfNum <= 0) { return; }

            // 送信接続数による分配
            double dK = 1.0 / m_csSndHmnFertilizerCnnct.m_RcvInfNum;
            for (int i = 0; i < m_csSndHmnFertilizerCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csSndHmnFertilizerCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = dK * m_HmnFrtInf.m_N_Fertilize;
                csSndDt[0].m_dData[1] = dK * m_HmnFrtInf.m_P_Fertilize;
                csSndDt[0].m_dData[2] = dK * m_HmnFrtInf.m_IOPMass_Si;
                csSndDt[0].m_dData[3] = m_HmnFrtInf.m_Si_Size;
                csSndDt[0].m_dData[4] = dK * m_HmnFrtInf.m_IOPMass_Fe;
                csSndDt[0].m_dData[5] = m_HmnFrtInf.m_Fe_Size;
            }
            // 受信量のリセット
            m_HmnFrtInf.m_N_Fertilize = 0;
            m_HmnFrtInf.m_P_Fertilize = 0;
            m_HmnFrtInf.m_IOPMass_Si = 0;
            m_HmnFrtInf.m_IOPMass_Fe = 0;
        }

        protected override void SendDEBUG()
        {
            for (int i = 0; i < m_csDebugSendCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csDebugSendCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csCell == null) { continue; }
                csCell[0].m_dData[0] = m_HmnFrtInf.m_N_Fertilize;
                csCell[0].m_dData[1] = m_HmnFrtInf.m_P_Fertilize;
                csCell[0].m_dData[2] = m_HmnFrtInf.m_IOPMass_Si;
                csCell[0].m_dData[3] = m_HmnFrtInf.m_IOPMass_Fe;
            }
        }


        /// <summary>
        /// 人間の行為
        /// </summary>
        /// <returns></returns>
        protected override long HumanAction()
        {
            double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);

            m_HmnFrtInf.m_N_Fertilize += m_HmnFrtInf.m_N * dT;
            m_HmnFrtInf.m_P_Fertilize += m_HmnFrtInf.m_P * dT;
            m_HmnFrtInf.m_IOPMass_Si += m_HmnFrtInf.m_SI * dT;
            m_HmnFrtInf.m_IOPMass_Fe += m_HmnFrtInf.m_FE * dT;
            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_HmnFrtInf = (MzHmnFertilizerFactoryCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 散布間隔
                this.SetHumanActionSpanTime(ref csPrptyInfo);
                double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
                csPrptyInfo.GetInfo("m_HmnCO2EmissionDay", ref m_HmnFrtInf.m_HmnCO2EmissionDay);
                m_HmnFrtInf.m_HmnCO2EmissionDay = m_HmnFrtInf.m_HmnCO2EmissionDay * 1E3; // * dT;

                csPrptyInfo.GetInfo("m_Si_Size", ref m_HmnFrtInf.m_Si_Size);
                csPrptyInfo.GetInfo("m_Fe_Size", ref m_HmnFrtInf.m_Fe_Size);
                csPrptyInfo.GetInfo("m_IOPMass_Si", ref m_HmnFrtInf.m_IOPMass_Si);
                csPrptyInfo.GetInfo("m_IOPMass_Fe", ref m_HmnFrtInf.m_IOPMass_Fe);
                csPrptyInfo.GetInfo("m_N_Fertilize", ref m_HmnFrtInf.m_N_Fertilize);
                csPrptyInfo.GetInfo("m_P_Fertilize", ref m_HmnFrtInf.m_P_Fertilize);
                csPrptyInfo.GetInfo("m_SI", ref m_HmnFrtInf.m_SI);
                csPrptyInfo.GetInfo("m_FE", ref m_HmnFrtInf.m_FE);
                csPrptyInfo.GetInfo("m_N", ref m_HmnFrtInf.m_N);
                csPrptyInfo.GetInfo("m_P", ref m_HmnFrtInf.m_P);

            }

            return true;
        }
    }
}
