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>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[2022/4/29][新規作成]</para>
    /// </remarks>
    public class MzEcJapanSociety : MzCashflowModelElement
    {
        protected MzEcJapanSocietyCalInfo m_SctyCalInf = null;

        // バイオ燃料を買う
        protected McPatternRdvSndTranInfoPair m_csBuyerBioFuelCnnct = new McPatternRdvSndTranInfoPair();

        // 魚を食品としてとして買う：
        protected McPatternRdvSndTranInfoPair m_csRcvFishFoodCnnct = new McPatternRdvSndTranInfoPair();

        // CO2排出権
        protected McPatternRdvSndTranInfoPair m_csBuyerCO2CreditCnnct = new McPatternRdvSndTranInfoPair();
        
        // 税金
        protected McPatternRdvSndTranInfoPair m_csRcvTaxCnnct = new McPatternRdvSndTranInfoPair();
        // 雇用
        protected McPatternRdvSndTranInfoPair m_csRcvEmploymentCnnct = new McPatternRdvSndTranInfoPair();

        //---- ワーク
        protected double m_dWorkDay = 0;

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

            McPatternRdvSndTranInfoPair m_csDumyCnnct = new McPatternRdvSndTranInfoPair();
            // CO2排出権出荷
            (m_csBuyerCO2CreditCnnct, m_csDumyCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.CO2_EMISSION_CREDIT);

            // バイオ燃料を買う
            (m_csBuyerBioFuelCnnct, m_csDumyCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.PRODUCT_BIO_FUEL);

            // 魚食品 を買う
            (m_csRcvFishFoodCnnct, m_csDumyCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.PRODUCT_FOOD);

            // 税金
            (m_csRcvTaxCnnct, m_csDumyCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.SC_TAX);
            // 雇用
            (m_csRcvEmploymentCnnct, m_csDumyCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.SC_EMPLOYMENT);

            return bRtn;
        }

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

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

            {
                CO2CreditBuyerReceive();
                BuyerBioFuelReceive();
                BuyerFishFoodReceive();
                TaxPaymentReceive();
                EmploymentReceive();
            }

            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
SendDEBUG();
           if (m_ActionFlg == true)
            {

                CO2CreditBuyerSend();
                BuyerBioFuelSend();
                BuyerFishFoodSend();
                TaxPaymentSend();
                EmploymentSend();
            }
            base.SendData();

            return;
        }

        //------------ CO2排出権売買用 ------------------
        /// <summary>
        /// CO2排出権代金受け取り：売り手
        /// </summary>
        protected virtual void CO2CreditBuyerReceive()
        {
            double dSum = 0.0;
            for (int i = 0; i < m_csBuyerCO2CreditCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csBuyerCO2CreditCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    m_SctyCalInf.m_CO2_Emission_Credit += csCell[0].m_dData[0];  // CO2排出権
                    m_csBuyerCO2CreditCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;
                    dSum += csCell[0].m_dData[0] + 1E-16;
                    if (csCell[0].m_dData[1] > 0.0)
                    {
                        m_SctyCalInf.m_CO2_Emission_Credit_UnitCost = csCell[0].m_dData[1]; // "CO2排出権単価"
                        m_SctyCalInf.m_CO2_Emission_Capability = csCell[0].m_dData[2];  // "CO2排出権共有能力"
                    }
                }
            }
            for (int i = 0; i < m_csBuyerCO2CreditCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csBuyerCO2CreditCnnct.m_dSendRatioData[i][0] = m_csBuyerCO2CreditCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// CO2排出権を売る
        /// </summary>
        protected virtual void CO2CreditBuyerSend()
        {
            // 予め通知された購入額に応じて納入
            for (int i = 0; i < m_csBuyerCO2CreditCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csBuyerCO2CreditCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_SctyCalInf.m_CO2_Credit_DealingChash * m_csBuyerCO2CreditCnnct.m_dSendRatioData[i][0];  //"購入代金／費用
                csSndDt[0].m_dData[1] = m_SctyCalInf.m_CO2_Credit_NextChash * m_csBuyerCO2CreditCnnct.m_dSendRatioData[i][0];   //発注（次回購入予定）
            }
        }

        //------------ バイオ燃料：物品売買用 ------------------
        /// <summary>
        /// バイオ燃料受け取り：買い手（卸売）
        /// </summary>
        protected virtual void BuyerBioFuelReceive()
        {
            double dSum = 0.0;
            for (int i = 0; i < m_csBuyerBioFuelCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csBuyerBioFuelCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    m_SctyCalInf.m_d2ndFuelStock += csCell[0].m_dData[0];
                    dSum += csCell[0].m_dData[0] + 1.0E-16;
                    m_csBuyerBioFuelCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1.0E-16;
                    if (csCell[0].m_dData[1] > 0.0)
                    {
                        m_SctyCalInf.m_d2ndFuelUnitCost = csCell[0].m_dData[1];
                        m_SctyCalInf.m_d2ndFuelFeedCapability = csCell[0].m_dData[2];
                    }
                }
            }
            // 分配係数設定
            for (int i = 0; i < m_csBuyerBioFuelCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csBuyerBioFuelCnnct.m_dSendRatioData[i][0] = m_csBuyerBioFuelCnnct.m_dRcvRatioData[i][0] / dSum;
            }
            // 発注分は入荷の為減らす
            m_SctyCalInf.m_d2ndFuelNextDealingChash -= dSum * m_SctyCalInf.m_d2ndFuelUnitCost;
        }
        /// <summary>
        /// バイオ燃料代金支払い：買い手（卸売）
        /// </summary>
        protected virtual void BuyerBioFuelSend()
        {
            for (int i = 0; i < m_csBuyerBioFuelCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csBuyerBioFuelCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_SctyCalInf.m_d2ndFuelDealingChash * m_csBuyerBioFuelCnnct.m_dSendRatioData[i][0];
                csSndDt[0].m_dData[1] = m_SctyCalInf.m_d2ndFuelNextDealingChash * m_csBuyerBioFuelCnnct.m_dSendRatioData[i][0];
            }
        }
    
        //------------ 魚食品：物品売買用 ------------------
        /// <summary>
        /// 魚受け取り：買い手（卸売）
        /// </summary>
        protected virtual void BuyerFishFoodReceive()
        {
            double dSum = 0.0;
            for (int i = 0; i < m_csRcvFishFoodCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvFishFoodCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    m_SctyCalInf.m_dFishFoods += csCell[0].m_dData[0];  // 食品
                    dSum += csCell[0].m_dData[0] + 1.0E-16;
                    m_csRcvFishFoodCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1.0E-16;
                    if (csCell[0].m_dData[1] > 0.0)
                    {
                        m_SctyCalInf.m_dFishFoodUnitCost = csCell[0].m_dData[1];  // 現在単価
                        m_SctyCalInf.m_dFeedCapability = csCell[0].m_dData[2];  // 共有能力
                    }
                }
            }
            // 分配係数設定
            for (int i = 0; i < m_csRcvFishFoodCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvFishFoodCnnct.m_dSendRatioData[i][0] = m_csRcvFishFoodCnnct.m_dRcvRatioData[i][0] / dSum;
            }
            // 発注分は入荷の為減らす
            m_SctyCalInf.m_dFishFoodNextDealingChash -= dSum * m_SctyCalInf.m_dFishFoodUnitCost;
            // 製品積み上げ
            m_SctyCalInf.m_dFishFoods += dSum;
        }
        /// <summary>
        /// 魚代金支払い：買い手（卸売）
        /// </summary>
        protected virtual void BuyerFishFoodSend()
        {
            for (int i = 0; i < m_csRcvFishFoodCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvFishFoodCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_SctyCalInf.m_dFishFoodDealingChash * m_csRcvFishFoodCnnct.m_dSendRatioData[i][0];  //  "購入代金／費用
                csSndDt[0].m_dData[1] = m_SctyCalInf.m_dFishFoodNextDealingChash * m_csRcvFishFoodCnnct.m_dSendRatioData[i][0];  // "発注（次回購入予定）"
            }
        }

        //---------------納税---------------------
        /// <summary>
        /// 納税請求受け取り：
        /// </summary>
        protected virtual void TaxPaymentReceive()
        {
            double dSum = 0.0;
            for (int i = 0; i < m_csRcvTaxCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvTaxCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if (csCell[0].m_dData[0] > 0.0)
                    {   //""支払い期日：請求日からX日後が設定されているならば
                        m_SctyCalInf.m_TaxIncom += csCell[0].m_dData[0];  // "税金支払額"
                        dSum += csCell[0].m_dData[0] + 1E-16;
                        m_csRcvTaxCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                        m_SctyCalInf.m_TaxDeclaration = csCell[0].m_dData[1]; // 税金支払申告額
                        m_SctyCalInf.m_Tax_Capability = csCell[0].m_dData[2];  //""利益申告""
                    }
                }
            }
            // 分配係数設定（現在支払われた納入金ではなく、次回購入予定である事に注意）
            for (int i = 0; i < m_csRcvTaxCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvTaxCnnct.m_dSendRatioData[i][0] = m_csRcvTaxCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 納税：納税者
        /// </summary>
        protected virtual void TaxPaymentSend()
        {
            if (m_SctyCalInf.m_Tax_Ordert < 0.0) { return; }

            for (int i = 0; i < m_csRcvTaxCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvTaxCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_SctyCalInf.m_Tax_Ordert * m_csRcvTaxCnnct.m_dSendRatioData[i][0];  //"税金請求額"
                csSndDt[0].m_dData[1] = m_SctyCalInf.m_NextTax_Day; // "支払い期日："
            }
        }

        //---------------雇用---------------------
        /// <summary>
        /// 雇用
        /// </summary>
        protected virtual void EmploymentReceive()
        {
            double dSum = 0.0;
            m_SctyCalInf.m_EmploymentPay = 0.0;
            for (int i = 0; i < m_csRcvEmploymentCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvEmploymentCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if (csCell[0].m_dData[0] > 0.0)
                    {
                        m_SctyCalInf.m_EmploymentPay += csCell[0].m_dData[0];  // "賃金支払い額
                        dSum += csCell[0].m_dData[0] + 1E-16;
                        m_csRcvEmploymentCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                        m_SctyCalInf.m_NextEmploymentPeople = csCell[0].m_dData[1];  // "次の雇用数
                        m_SctyCalInf.m_NextEmploymentUnitCost = csCell[0].m_dData[2];  // "次の賃金単価
                    }
                }
            }
            // 分配係数設定（現在支払われた納入金ではなく、次回購入予定である事に注意）
            for (int i = 0; i < m_csRcvEmploymentCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvEmploymentCnnct.m_dSendRatioData[i][0] = m_csRcvEmploymentCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 雇用
        /// </summary>
        protected virtual void EmploymentSend()
        {
            if (m_SctyCalInf.m_EmploymentPay < 0.0) { return; }

            for (int i = 0; i < m_csRcvEmploymentCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvEmploymentCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_SctyCalInf.m_EmploymentApplication * m_csRcvEmploymentCnnct.m_dSendRatioData[i][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_SctyCalInf.m_Chash;
                csCell[0].m_dData[1] = m_SctyCalInf.m_CO2_Emission_Credit;
                csCell[0].m_dData[2] = m_SctyCalInf.m_CO2_Emission_Credit * m_SctyCalInf.m_CO2_Emission_Credit_UnitCost;
                csCell[0].m_dData[3] = m_SctyCalInf.m_d2ndFuelStock;
                csCell[0].m_dData[4] = m_SctyCalInf.m_dFishFoods;
            }
        }

        //---------------------------------

        /// <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)
        {
            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_SctyCalInf.Clear();
                m_dWorkDay = 0;

                csInDt.GetInfo("m_d2ndFuelUnitCost", ref m_SctyCalInf.m_d2ndFuelUnitCost);
                // 単位変換　(\/L) →　億円/t
                m_SctyCalInf.m_d2ndFuelUnitCost = m_SctyCalInf.m_d2ndFuelUnitCost * 1E3 / 1E8;
 
                csInDt.GetInfo("m_d2ndFuelFeedCapability", ref m_SctyCalInf.m_d2ndFuelFeedCapability);

                csInDt.GetInfo("m_dFishFoodUnitCost", ref m_SctyCalInf.m_dFishFoodUnitCost);
                // 単位変換　万円/t →　億円/t
                m_SctyCalInf.m_dFishFoodUnitCost = m_SctyCalInf.m_dFishFoodUnitCost / 1E4;
                //csInDt.GetInfo("m_dFishNowUnitCost", ref m_SctyCalInf.m_dFishNowUnitCost);

                csInDt.GetInfo("m_CO2_Emission_Credit_UnitCost", ref m_SctyCalInf.m_CO2_Emission_Credit_UnitCost);
                // 単位変換　万円/t →　億円/t
                m_SctyCalInf.m_CO2_Emission_Credit_UnitCost = m_SctyCalInf.m_CO2_Emission_Credit_UnitCost / 1E4;

                csInDt.GetInfo("m_Benefit", ref m_SctyCalInf.m_Benefit);
                csInDt.GetInfo("m_NextTax_Day", ref m_SctyCalInf.m_NextTax_Day);
                //csInDt.GetInfo("m_EmploymentPeriod", ref m_SctyCalInf.m_EmploymentPeriod);

                csInDt.GetInfo("m_NextEmploymentUnitCost", ref m_SctyCalInf.m_NextEmploymentUnitCost);
                // 単位変換　万円 →　億円
                m_SctyCalInf.m_NextEmploymentUnitCost = m_SctyCalInf.m_NextEmploymentUnitCost / 1E4;
            }
            m_ActionFlg = false;
            return true;
        }


        /// <summary>
        /// 人間の行為
        /// </summary>
        /// <returns></returns>
        protected override long HumanAction()
        {
            // 仮
            //------------ CO2排出権売買用 ------------------
            m_SctyCalInf.m_CO2_Credit_DealingChash = m_SctyCalInf.m_CO2_Emission_Capability * m_SctyCalInf.m_CO2_Emission_Credit_UnitCost;
            m_SctyCalInf.m_CO2_Credit_NextChash = m_SctyCalInf.m_CO2_Emission_Capability * m_SctyCalInf.m_CO2_Emission_Credit_UnitCost;
            //------------ バイオ燃料：物品売買用 ------------------
            m_SctyCalInf.m_d2ndFuelDealingChash = 10;  // 仮
            m_SctyCalInf.m_d2ndFuelNextDealingChash = 10;  // 仮
            //------------ 魚食品：物品売買用 ------------------
            m_SctyCalInf.m_Tax_Ordert =10;  // 仮
            //------------ 納税用 ------------------
            m_SctyCalInf.m_Tax_Ordert = m_SctyCalInf.m_TaxDeclaration;
            //------------ 雇用 ------------------
            m_SctyCalInf.m_dFishFoodDealingChash = m_SctyCalInf.m_NextEmploymentPeople;
            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)
        {
            bool bRtn = base.SetProperty(csCellMdlPropertyInfo);

            // 使用しやすいようにキャストしておく
            m_SctyCalInf = (MzEcJapanSocietyCalInfo)m_csCalInfo;
           
            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);

            }

            return true;
        }

    }
}
