

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

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Controller;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.CoreImpl.Data.FileIO;
using CommonMP.HYMCO.CoreImpl.Data.StructInfo;
using CommonMP.HYMCO.CoreImpl.Tool;


namespace CommonMP.HYMCO.CoreOption.McSTGSystemBase
{
    /// <summary><para>class outline:</para>
    /// <para>
    /// フィードバック情報出力要素モデルクラス作成用基底クラス
    /// フィードバック情報出力要素モデルを作成する場合には、本クラスから派生させる。
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2011/11/01][新規作成]</para>
    /// </remarks>
    public abstract class McSTGFeedbackModelBase : McBasicIOCtlModelBase
    {
        /// <summary>フィードバック情報</summary>
        protected McSTGSysFeedbackDataBase m_csFeedbackData = null;

        /// <summary>自身を所有しているエレメントのＩＤ </summary>
        protected string m_csOwnerElmID = null;

        /// <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)
        {
            // Do Nothing
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(ref csInitialData,lInputDataNum,ref csInputCellData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</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 Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            m_csOwnerElmID = this.m_csElement.GetOwnerProjectID();
            if (m_csOwnerElmID != null)
            {   // Not Null
                if (m_csFeedbackData == null)
                {   // Null
                    m_csFeedbackData = HySCommonInfoHash.GetCorrespondData(McSTGSysDefine.TABLE_KEY_FEEDBACK_DATA, m_csOwnerElmID) as McSTGSysFeedbackDataBase;
                }
            }
            if (m_csFeedbackData != null)
            {   // Not Null
                return InitializeFeedbackData(ref csInitialData, lInputDataNum, ref  csInputCellData, ref m_csFeedbackData);
            }
            else
            {   // no FeedbackData
                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInfo.AddSimuErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_SUBSYSTEM,
                            Properties.HymcoSTGResources.STATEMENT_FEEDBACKDATA_NULL );
                   // csErrorInfo.AddSimuErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_SUBSYSTEM,
                   //         "FeedbackData is null.");
                }
               // ver1.5 エラートレース日本語対応
                McLog.DebugOut(this.m_csSimTime, this.m_csElement.GetID(), McLog.SYSTEM, "Initialize",
                    Properties.HymcoSTGResources.STATEMENT_FEEDBACKDATA_NULL );
               // McLog.DebugOut(this.m_csSimTime, this.m_csElement.GetID(), McLog.SYSTEM, "Initialize",
               //     "FeedbackData is null.");
                
                return false;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>フィードバック情報を初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>InitializeFeedbackData(ref csInitialData,lInputDataNum,ref csInputCellData, ref csFeedbackData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <param name="csFeedbackData">フィードバック情報</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract bool InitializeFeedbackData(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData, ref McSTGSysFeedbackDataBase csFeedbackData);

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="csInputDataList">演算に必要な入力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long Calculate(ref HySDataLinkedList csInputDataList)
        {
            m_lCalculate_Call_Before_DataFution_Call += 1; // Calculate Call 回数カウントアップ
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分
                if (m_InputCellData[lP] != null)
                {
                    m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            if (m_csFeedbackData != null)
            {   // Not Null
                return this.WriteToFeedbackData(m_lInputDataNum, ref m_InputCellData, ref m_csFeedbackData);
            }
            else
            {   // no FeedbackData
                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInfo.AddSimuErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_SUBSYSTEM,
                            Properties.HymcoSTGResources.STATEMENT_FEEDBACKDATA_NULL );
                   // csErrorInfo.AddSimuErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_SUBSYSTEM,
                   //         "FeedbackData is null.");
                }
               // ver1.5 エラートレース日本語対応
                McLog.DebugOut(this.m_csSimTime, this.m_csElement.GetID(), McLog.SYSTEM, "Calculate",
                    Properties.HymcoSTGResources.STATEMENT_FEEDBACKDATA_NULL );
               // McLog.DebugOut(this.m_csSimTime, this.m_csElement.GetID(), McLog.SYSTEM, "Calculate",
               //     "FeedbackData is null.");

                return -1;
            }

        }
        /// <summary><para>method outline:</para>
        /// <para>入力値を元にフィードバック情報を書き込む</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = WriteToFeedbackData(lInputDataNum, ref csInputCellData,ref csFeedbackData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <param name="csFeedbackData">フィードバック書き込み情報</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract long WriteToFeedbackData(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData, ref McSTGSysFeedbackDataBase csFeedbackData);
        /// <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)
        {
            m_lCalculate_Call_Before_DataFution_Call = 0;
            return 0;
        }

        /// <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()
        {
            bool bRtn = base.ReadyCalculation();
            if (bRtn == true)
            {
                bRtn = this.ReadyCalculation(ref m_csFeedbackData);
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>計算開始時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReadyCalculation(csFeedbackData)</para>
        /// </example>
        /// <param name="csFeedbackData">フィードバックデータ</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算開始の　最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        protected abstract bool ReadyCalculation(ref McSTGSysFeedbackDataBase csFeedbackData);
        /// <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()
        {
            bool bRtn = base.CompleteCalculation();
            if (bRtn == true)
            {
                bRtn = this.CompleteCalculation(ref m_csFeedbackData);
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>計算終了時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CompleteCalculation(csFeedbackData)</para>
        /// </example>
        /// <param name="csFeedbackData">フィードバックデータ</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        protected abstract bool CompleteCalculation(ref McSTGSysFeedbackDataBase csFeedbackData);
        /// <summary><para>method outline:</para>
        /// <para>シミュレーションデータコンテナの内容を設定する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetSimDataContainerInfo( csDataContainer )</para>
        /// </example>
        /// <param name="csDataContainer">シミュレーションデータコンテナ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void SetSimDataContainer(HySSimulationDataContainer csDataContainer)
        {
            if (csDataContainer != null)
            {
                m_csFeedbackData = csDataContainer.GetData(McSTGSysDefine.DATA_KEY_FEEDBACK_DATA) as McSTGSysFeedbackDataBase;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>計算状態復元のためのデータクラスを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McCmnElementOutData csElementOutData = CreateOutData()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McCmnElementOutData データクラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override McCmnElementOutData CreateOutData()
        {
            return new McCmnElementOutData();
        }
        /// <summary><para>method outline:</para>
        /// <para>ファイルにモデル内情報を全て書き出す</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = FileOUT(csData)</para>
        /// </example>
        /// <param name="csData">演算要素データ</param>
        /// <returns>bool true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool FileOUT(HySDataRoot csData)
        {
            // 演算モデルの保存
            ((McCmnElementOutData)(csData)).SetData(m_csCalInfo);

            // 時刻データの保存
            ((McCmnElementOutData)(csData)).SetTimeData(McDefine.SIMULATION_TIME, m_csSimTime);
            ((McCmnElementOutData)(csData)).SetTimeData(McDefine.TARGET_TIME, m_csTgtTime);
            ((McCmnElementOutData)(csData)).SetTimeData(McDefine.DELTA_TIME, m_csDltTime);

            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>ファイルからモデル情報を全て読み出す</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = FileIN(csData)</para>
        /// </example>
        /// <param name="csData">演算要素データ</param>
        /// <returns>bool true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool FileIN(HySDataRoot csData)
        {
            // 演算状態の復元
            McCalInfo csCalInfo = ((McCmnElementOutData)(csData)).GetData();
            if (m_csCalInfo != null)
            {
                m_csCalInfo.CopyInfo(csCalInfo);
            }
            // 時刻データの復元
            m_csSimTime = (HySTime)((McCmnElementOutData)(csData)).GetTimeData(McDefine.SIMULATION_TIME);
            m_csTgtTime = (HySTime)((McCmnElementOutData)(csData)).GetTimeData(McDefine.TARGET_TIME);
            m_csDltTime = (HySTime)((McCmnElementOutData)(csData)).GetTimeData(McDefine.DELTA_TIME);

            // 復元後の整合性確保
            if (m_csCalInfo != null)
            {
                if (m_csCalInfo is HySVersionManagement)
                {
                    ((HySVersionManagement)m_csCalInfo).PostDeserialize();
                }
            }

            return true;
        }

    }
}
