// <summary>ソースコード：入力値加算モデルクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

using CommonMP.HYMCO.Interface;


// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
namespace CommonMP.HYMCO.OptionImpl.McSumForDevelop   
{
    /// <summary><para>class outline:</para>
    /// <para>入力値加算モデル</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class McSumModel :  McStateCalModelBase //McForecastModelBase
    {
        /// <summary> 演算データ（キャスト用） </summary>
        McSumCalInfo m_csSumInfo = null;   // 便利の為、キャスト用に定義しておく

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


        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(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 ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {   // 入力する伝送データ数分繰り返します。

                HySID csInputPtnID = csInputCellData[lLp].GetReceivePatternID();
                if (McSumDefine.RECEIVE_PATTERN_D0.Equals(csInputPtnID) == true)
                {   //ポイント時系列
                }
                else if (McSumDefine.RECEIVE_PATTERN_D1.Equals(csInputPtnID) == true)
                {   //1次元時系列
                }
                else if (McSumDefine.RECEIVE_PATTERN_D2.Equals(csInputPtnID) == true)
                {   //2次元時系列
                }
                else if (McSumDefine.RECEIVE_PATTERN_D3.Equals(csInputPtnID) == true)
                {   //3次元時系列
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                            Properties.McSumResources.STATEMENT_UNEXPECT_REC_DATA_PATTERN + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                   //         "Unexpected receive data pattern. (Received from " + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                    bRtn = false;
                }

                // 伝送データのセル配列及びセル内の変数の数を取得する
                long lCellDataNum = 0;
                long lCellDim = csInputCellData[lLp].GetDimension(ref m_csSumInfo.m_lDim1, ref m_csSumInfo.m_lDim2, ref m_csSumInfo.m_lDim3, ref lCellDataNum);

                HySObjectKind csCellType = csInputCellData[lLp].GetTranInfoKind();
                if (McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D2_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D3_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                             Properties.McSumResources.STATEMENT_UNEXPECT_REC_DATA_TYPE_R + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                   //         "Unexpected receive data type. (Received from " + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                    bRtn = false;
                }

                if (lLp > 0 && m_csSumInfo.m_csCellType.Equals(csCellType) == false)
                {   //同一でない伝送データ種別の場合、エラー
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                             Properties.McSumResources.STATEMENT_NOT_SAME_REC_DATA_TYPE + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                   //         "Not same of receive data type. (Received from " + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                    bRtn = false;
                }
                m_csSumInfo.m_csCellType = csCellType;


                if (lLp == 0)
                {
                    m_csSumInfo.m_lDim1Max = m_csSumInfo.m_lDim1;
                    m_csSumInfo.m_lDim2Max = m_csSumInfo.m_lDim2;
                    m_csSumInfo.m_lDim3Max = m_csSumInfo.m_lDim3;
                }
                else
                {
                    m_csSumInfo.m_lDim1Max = Math.Max(m_csSumInfo.m_lDim1Max, m_csSumInfo.m_lDim1);
                    m_csSumInfo.m_lDim2Max = Math.Max(m_csSumInfo.m_lDim2Max, m_csSumInfo.m_lDim2);
                    m_csSumInfo.m_lDim3Max = Math.Max(m_csSumInfo.m_lDim3Max, m_csSumInfo.m_lDim3);
                }

            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(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 SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。


                HySID csOutPtnID = csOutputCellData[lLp].GetSendPatternID();
                if (McSumDefine.SEND_OUT_PATTERN_D0.Equals(csOutPtnID) == true)
                {   //ポイント時系列
                }
                else if (McSumDefine.SEND_OUT_PATTERN_D1.Equals(csOutPtnID) == true)
                {   //1次元時系列
                }
                else if (McSumDefine.SEND_OUT_PATTERN_D2.Equals(csOutPtnID) == true)
                {   //2次元時系列
                }
                else if (McSumDefine.SEND_OUT_PATTERN_D3.Equals(csOutPtnID) == true)
                {   //3次元時系列
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                         Properties.McSumResources.STATEMENT_UNEXPECT_SND_DATA_PATTERN );
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                   //     "Unexpected send data pattern.");
                    bRtn = false;
                }


                //  伝送データの種別に応じての処理 
                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                long lCellDim = csOutputCellData[lLp].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                HySObjectKind csCellType = csOutputCellData[lLp].GetTranInfoKind();
                if (McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D2_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D3_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                         Properties.McSumResources.STATEMENT_UNEXPECT_SND_DATA_TYPE );
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                   //     "Unexpected send data type.");
                    bRtn = false;
                }

                if (m_csSumInfo.m_csCellType.Equals(csCellType) == false)
                {   //伝送データの種別が受信と違う場合エラー
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND, 
                        Properties.McSumResources.STATEMENT_REC_SND_NO_MATCH );
                   // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND, "receive and send data type do not match.");
                    bRtn = false;
                }


            }
            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 = true;
            // 引数で与えられたデータを　キャストしています。
            McInitialInfo csInDt = csInitialData as McInitialInfo;

            if (csInDt != null)
            {
                bRtn = true;
            }

            m_csSumInfo.m_csLastDataOutTime = new HySTime(0);

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>OnlineInitialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>bool</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool OnlineInitialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            // 
            return true;
        }
        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            HySCellData[] csD0RcvCellData = null;
            HySCellData[] csD1RcvCellData = null;
            HySCellData[,] csD2RcvCellData = null;
            HySCellData[,,] csD3RcvCellData = null;

            //格納用変数初期化
            if(McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(m_csSumInfo.m_csCellType) == true){
                m_csSumInfo.csD0CellData = 0.0;
            }
            else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(m_csSumInfo.m_csCellType) == true){
                m_csSumInfo.csD1CellData = new double[m_csSumInfo.m_lDim1Max];
            }
            else if (McTranInfoDefine.D2_CELL_SERIAL.Equals(m_csSumInfo.m_csCellType) == true)
            {
                m_csSumInfo.csD2CellData = new double[m_csSumInfo.m_lDim1Max, m_csSumInfo.m_lDim2Max];
            }
            else if (McTranInfoDefine.D3_CELL_SERIAL.Equals(m_csSumInfo.m_csCellType) == true)
            {
                m_csSumInfo.csD3CellData = new double[m_csSumInfo.m_lDim1Max, m_csSumInfo.m_lDim2Max, m_csSumInfo.m_lDim3Max];
            }

            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。

                HySObjectKind csCellType = csInputCellData[lLp].GetTranInfoKind(); // 伝送データ種別の取得例
                McTranInfo csTrnInf = csInputCellData[lLp].GetTranInfo();  // 伝送データ本体の取得例

                // 伝送データのセル配列及びセル内の変数の数を取得する
                long lCellDataNum = 0;

                long lCellDim = csInputCellData[lLp].GetDimension(ref m_csSumInfo.m_lDim1, ref m_csSumInfo.m_lDim2, ref m_csSumInfo.m_lDim3, ref lCellDataNum);

                // 伝送データの型式
                //ポイント時系列
                if (McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(csCellType) == true)
                {
                    // セル全体を取得
                    csD0RcvCellData = csInputCellData[lLp].GetInterpolatedCellD1();
                    //入力値を加算する
                    m_csSumInfo.csD0CellData += csInputCellData[lLp].Data(csD0RcvCellData[0], 0);
                }
                //1次元時系列
                else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(csCellType) == true)
                {
                    // セル全体を取得
                    csD1RcvCellData = csInputCellData[lLp].GetInterpolatedCellD1();
                    //入力値を加算する
                    for (long l1 = 0; l1 < m_csSumInfo.m_lDim1; l1++)
                    {
                        m_csSumInfo.csD1CellData[l1] += csInputCellData[lLp].Data(csD1RcvCellData[l1], 0); 
                    }
                }
                //2次元時系列
                else if (McTranInfoDefine.D2_CELL_SERIAL.Equals(csInputCellData[lLp].GetTranInfoKind()) == true)
                {   
                    // セル全体を取得
                    csD2RcvCellData = csInputCellData[lLp].GetInterpolatedCellD2();
                    //入力値を加算する
                    for (long l1 = 0; l1 < m_csSumInfo.m_lDim1; l1++)
                    {
                        for (long l2 = 0; l2 < m_csSumInfo.m_lDim2; l2++)
                        {
                            m_csSumInfo.csD2CellData[l1, l2] += csInputCellData[lLp].Data(csD2RcvCellData[l1, l2], 0);
                        }
                    }
                }
                //3次元時系列
                else if (McTranInfoDefine.D3_CELL_SERIAL.Equals(csInputCellData[lLp].GetTranInfoKind()) == true)
                {
                    // セル全体を取得
                    csD3RcvCellData = csInputCellData[lLp].GetInterpolatedCellD3();
                    //入力値を加算する
                    for (long l1 = 0; l1 < m_csSumInfo.m_lDim1; l1++)
                    {
                        for (long l2 = 0; l2 < m_csSumInfo.m_lDim2; l2++)
                        {
                            for (long l3 = 0; l3 < m_csSumInfo.m_lDim3; l3++)
                            {
                                m_csSumInfo.csD3CellData[l1, l2, l3] += csInputCellData[lLp].Data(csD3RcvCellData[l1, l2, l3], 0);
                            }
                        }
                    }

                }

            }


            return 0;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {

            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。


                HySObjectKind csCellType = csOutputCellData[lLp].GetTranInfoKind(); // 伝送データ種別の取得例
                McTranInfo csTrnInf = csOutputCellData[lLp].GetTranInfo();  // 伝送データ本体の取得例

                long lCellDataNum = 0;

                long lCellDim = csOutputCellData[lLp].GetDimension(ref m_csSumInfo.m_lDim1, ref m_csSumInfo.m_lDim2, ref m_csSumInfo.m_lDim3, ref lCellDataNum);


                // 伝送データの型式
                //ポイント時系列
                if (McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    HySCellData[] csSndCellData = csOutputCellData[lLp].PrepareSendCellD1();
                    csSndCellData[0].m_dData[0] = m_csSumInfo.csD0CellData;

                }
                //1次元時系列
                else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    HySCellData[] csSndCellData = csOutputCellData[lLp].PrepareSendCellD1();
                    for (long l1 = 0; l1 < Math.Min(m_csSumInfo.m_lDim1, m_csSumInfo.m_lDim1Max); l1++)
                    {
                        csSndCellData[l1].m_dData[0] = m_csSumInfo.csD1CellData[l1];
                    }

                }
                //2次元時系列
                else if (McTranInfoDefine.D2_CELL_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    HySCellData[,] csSndCellData = csOutputCellData[lLp].PrepareSendCellD2();
                    for (long l1 = 0; l1 < Math.Min(m_csSumInfo.m_lDim1, m_csSumInfo.m_lDim1Max); l1++)
                    {
                        for (long l2 = 0; l2 < Math.Min(m_csSumInfo.m_lDim2, m_csSumInfo.m_lDim2Max); l2++)
                        {
                            csSndCellData[l1, l2].m_dData[0] = m_csSumInfo.csD2CellData[l1, l2];
                        }
                    }

                }
                //3次元時系列
                else if (McTranInfoDefine.D3_CELL_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    HySCellData[,,] csSndCellData = csOutputCellData[lLp].PrepareSendCellD3();
                    for (long l1 = 0; l1 < Math.Min(m_csSumInfo.m_lDim1, m_csSumInfo.m_lDim1Max); l1++)
                    {
                        for (long l2 = 0; l2 < Math.Min(m_csSumInfo.m_lDim2, m_csSumInfo.m_lDim2Max); l2++)
                        {
                            for (long l3 = 0; l3 < Math.Min(m_csSumInfo.m_lDim3, m_csSumInfo.m_lDim3Max); l3++)
                            {
                                csSndCellData[l1, l2, l3].m_dData[0] = m_csSumInfo.csD3CellData[l1, l2, l3];
                            }
                        }
                    }

                }

            }

            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 = false;
            // 使用しやすいようにキャストしておく
            m_csSumInfo = (McSumCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                m_csSumInfo.m_dDltTime = csPrptyInfo.GetStepTime();
                this.m_csDltTime = new HySTime(m_csSumInfo.m_dDltTime);

                bRtn = true;
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中に　プロパティ情報を変更した場合にコールされる</para>
        /// </remarks>
        public override bool SetOnlineProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                bRtn = true;
            }
            return bRtn;
        }
        

    }
    //
}
