// <summary>ソースコード：ＨＹＭＣＯインポートされたＤＬＬ演算モデルＩ／Ｆ</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;

using CommonMP.HYSSOP.Interface.HSData;
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.Interface.Controller;

using CommonMP.HYMCO.CoreImpl.Model;
using CommonMP.HYMCO.CoreOptionl.HymcoModelDLLWrapper;

namespace CommonMP.HYMCO.OptionImpl.Hymco64FortranWrapp
{
    /// <summary><para>class outline:</para>
    /// <para>FORTRAN ラッパー要素モデルクラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>フォートラン等異種言語処理をラッピングして使用する要素モデル</para>
    /// <para>history:</para>
    /// <para>[CommonMP][ver 1.3.0][2011/04/01][新規作成]</para>
    /// </remarks>
    public class Mc64BitFortranWrapperModel : Mc64BitWrapperModel
    {
        /// <summary>Fortran用：キャストしておく</summary>
        Mc64BitFortranModelDLLImport m_csFrtnDLLImport = null;

        /// <summary>プロパティ情報を保持しておく:チェックの時に必要 </summary>
        Mc64BitFortranModelPropertyInfo m_csPrpytInfo = null;


        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csInputDataList, ref csErrorInf)</para>
        /// </example>
        /// <param name="csInputDataList">入力情報リスト</param>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        public override bool ReceiveConnectionCheck(ref HySDataLinkedList csInputDataList, ref McStructErrorInfo csErrorInf)
        {
            m_csFrtnDLLImport.SetReceiveConnection(ref csInputDataList);
            return base.ReceiveConnectionCheck(ref csInputDataList, ref csErrorInf);
        }
        /// <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 = m_csFrtnDLLImport.ReceiveConnectionCheck( ref csErrorInf,lInputDataNum,csInputCellData);
            //for (long lLp = 0; lLp < lInputDataNum; lLp++)
            //{   // 入力する伝送データ数分繰り返します。
            //}
            //m_csLastRevDataPutTime = new HySTime[lInputDataNum];

            return bRtn;
        }
 
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csOutputDataList, ref csErrorInf)</para>
        /// </example>
        /// <param name="csOutputDataList">出力情報リスト</param>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        public override bool SendConnectionCheck(ref HySDataLinkedList csOutputDataList, ref McStructErrorInfo csErrorInf)
        {
            m_csFrtnDLLImport.SetSendConnection(ref csOutputDataList);
            return base.SendConnectionCheck(ref csOutputDataList, ref csErrorInf);
        }
        /// <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 = m_csFrtnDLLImport.SendConnectionCheck(ref csErrorInf,lOutputDataNum,csOutputCellData);
            //for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            //{   // 出力する伝送データ数分繰り返します。
            //}
            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;
            
            //for (long lLp = 0; lLp < lInputDataNum; lLp++)
            //{   // 入力する伝送データ数分繰り返します。
            //    m_csLastRevDataPutTime[lLp] = HySTime.DEFAULT_TIME.Clone();
            //}

            try
            {
                // ＤＬＬに初期化情報を設定する
                bRtn = m_csFrtnDLLImport.SetInitialInf(this.m_csStartTime, ref csInitialData);
            }
            catch (Exception ex)
            {
                // ログ出力
                HySLog.LogOut(HySLog.ONLINE, "Mc32BitFortranWrapperModel::Initialize", "Exception Catch in Class " + m_csFrtnDLLImport.GetDLLName().ToString() + " :: " + ex.Message);

                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                    csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                            "Exception Catch in " + m_csFrtnDLLImport.GetDLLName().ToString() + ".Initialize() :: " + ex.Message);
                }
                bRtn = false;
            }
            return bRtn;
        }

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

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref InputCellData)</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)
        {
            long lRtn = 0;
            double dTm = m_csFrtnDLLImport.WantDataTime();
            //m_csWantTime.SetTime(m_csStartTime.GetTime() + dTm);

            try
            {
                // ＤＬＬ側モデルへ受信情報を設定する
                m_csFrtnDLLImport.PutReceivedData(dTm);

                // ＤＬＬ側モデルの計算指示
                lRtn = (long)m_csFrtnDLLImport.Calculate();
            }
            catch (Exception ex)
            {
                // ログ出力
                HySLog.LogOut(HySLog.ONLINE, "Mc32BitFortranWrapperModel::Calculate", "Exception Catch in Class " + m_csFrtnDLLImport.GetDLLName().ToString() + " :: " + ex.Message);

                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                    csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                            "Exception Catch in " + m_csFrtnDLLImport.GetDLLName().ToString() + ".Calculate() :: " + ex.Message);
                }
                lRtn = -1;
            }
            return lRtn;
        }

        /// <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)
        {
            long lRtn = 0;
            try
            {
                // ＤＬＬ側モデルから情報を取得し、送信データに乗せる
                m_csFrtnDLLImport.GetSendData();
            }
            catch (Exception ex)
            {
                // ログ出力
                HySLog.LogOut(HySLog.ONLINE, "Mc32BitFortranWrapperModel::DataFusion", "Exception Catch in Class " + m_csFrtnDLLImport.GetDLLName().ToString() + " :: " + ex.Message);

                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                    csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                            "Exception Catch in " + m_csFrtnDLLImport.GetDLLName().ToString() + ".DataFusion() :: " + ex.Message);
                }
                lRtn = -1;
            }
            return lRtn;
        }

        //=========================
        // その他必要なメソッド
        //=========================

        /// <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 = true;
            m_csPrpytInfo = csCellMdlPropertyInfo as Mc64BitFortranModelPropertyInfo;
            if (m_csPrpytInfo != null)
            {
                m_csFrtnDLLImport = new Mc64BitFortranModelDLLImport();
                m_csDLL = m_csFrtnDLLImport;
                m_bForecastFlg = m_csPrpytInfo.GetForecastFlg();

                //HySString csDLLName = m_csPrpytInfo.GetModelKind().GetString() as HySString;
                //bRtn = m_csFrtnDLLImport.ImportDLL(csDLLName.ToString());
                string sDLLName = m_csPrpytInfo.GetDLLName();
                bRtn = m_csFrtnDLLImport.ImportDLL(sDLLName);
                if (bRtn != true) { return bRtn; }
                bRtn = m_csFrtnDLLImport.Prepare();
                if (bRtn != true) { return bRtn; }

                try
                {
                    bRtn = m_csFrtnDLLImport.SetPropertyInf(csCellMdlPropertyInfo);
                }
                catch (Exception ex)
                {
                    // ログ出力
                    HySLog.LogOut(HySLog.ONLINE, "Mc32BitFortranWrapperModel::SetProperty", "Exception Catch in Class " + sDLLName + " :: " + ex.Message);

                    McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                    if (csErrorInfo != null)
                    {
                        csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                                "Exception Catch in " + sDLLName + ".SetProperty() :: " + ex.Message);
                    }
                    bRtn =false;
                }

                double dDltT = m_csPrpytInfo.GetStepTime();
                this.SetDeltaTime(new HySTime(dDltT));


            }
            return bRtn;
        }

    }
}
