// <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;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

namespace CommonMP.HYMCO.OptionImpl.McMultiplyWeightForDevelop
{
    /// <summary><para>class outline:</para>
    /// <para>重み付き合計モデルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2012/01/24][新規作成]</para>
    /// </remarks>
    public class McMultiplyWeightModel : McStateCalModelBase
    {
        /// <summary> 演算データ（キャスト用） </summary>
        McMultiplyWeightCalInfo m_csMWInf = 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++)
            {   // 入力する伝送データ数分繰り返します。
                HySObjectKind csObjKind = csInputCellData[lLp].GetTranInfoKind();
                if (csObjKind.Equals(McTranInfoDefine.D1_CELL_SERIAL) == false)
                {   // 1次元時系列以外はエラー
                    bRtn = false;

                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(),
                        McMultiplyWeightDefine.MULTIPLY_WEIGHT_MODEL_KIND,
                        Properties.MyModelResources.STATEMENT_UNEXPECT_REC_DATA_TYPE_R + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(),
                   //     McMultiplyWeightDefine.MULTIPLY_WEIGHT_MODEL_KIND,
                   //     "Unexpected receive data type. (Received from " + csInputCellData[lLp].GetUpperElementID().ToString() + ")");
                }
            }

            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++)
            {   // 出力する伝送データ数分繰り返します。
                HySObjectKind csObjKind = csOutputCellData[lLp].GetTranInfoKind();
                if (csObjKind.Equals(McTranInfoDefine.D1_CELL_SERIAL) == false)
                {   // 1次元時系列以外はエラー
                    bRtn = false;
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(),
                        McMultiplyWeightDefine.MULTIPLY_WEIGHT_MODEL_KIND,
                        Properties.MyModelResources.STATEMENT_UNEXPECT_SEND_DATA_PATTERN_S + csOutputCellData[lLp].GetLowerElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(),
                   //     McMultiplyWeightDefine.MULTIPLY_WEIGHT_MODEL_KIND,
                   //     "Unexpected send data Pattern. (send to " + csOutputCellData[lLp].GetLowerElementID().ToString() + ")");
                }
            }
            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 = false;
            // 引数で与えられたデータを　キャストしています。
            McInitialInfo csInDt = csInitialData as McInitialInfo;

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

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

        /// <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)
        {
            double dValue = 0.0;
            // 入力データを取得
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {
                HySCellData[] csCellData = csInputCellData[lLp].GetInterpolatedCellD1();
                HySID csInputPtnID = csInputCellData[lLp].GetReceivePatternID();
                string sInputPtnStr = csInputPtnID.ToString();
                long lIndex = long.Parse(sInputPtnStr.Substring(sInputPtnStr.Length - 2, 2)) - 1;
                dValue += csInputCellData[lLp].Data(csCellData[0], 0) * m_csMWInf.m_dWeight[lIndex];
            }
            m_csMWInf.m_dOut = dValue;
            //McLog.DebugOut(GetSimulationTime(), GetID(), "McMultiplyWeightModel", "Calculate", m_csMWInf.m_dOut.ToString());

            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++)
            {   // 出力する伝送データ数分繰り返します。
                HySCellData[] csSndCellData = csOutputCellData[lLp].PrepareSendCellD1();
                csSndCellData[0].m_dData[0] = m_csMWInf.m_dOut;
                //McLog.DebugOut(GetSimulationTime(), GetID(), "McMultiplyWeightModel", "DataFusion", m_csMWInf.m_dOut.ToString());
            }

            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_csMWInf = (McMultiplyWeightCalInfo)m_csCalInfo;

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

                // 重み
                m_csMWInf.m_dWeight = new double[McMultiplyWeightDefine.MAX_INPUT_NUM];
                for (long lLp = 0; lLp < McMultiplyWeightDefine.MAX_INPUT_NUM; lLp++)
                {
                    csPrptyInfo.GetInfo(string.Format("m_dWeight{0:D2}", lLp), ref m_csMWInf.m_dWeight[lLp]);
                }
                bRtn = true;
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算開始時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReadyCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算開始の　最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool ReadyCalculation()
        {
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算終了時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CompleteCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool CompleteCalculation()
        {
            return true;
        }
    }
}
