// <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.HYSSOP.Interface.HSData;

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

namespace CommonMP.HYMCO.OptionImpl.McSampleModelForDeveloper
{
    /// <summary><para>class outline:</para>
    /// <para>テスト用３次元ＣＳＶファイル入力クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>
    /// [CommonMP][ver 1.0.0][2008/10/01][新規作成]
    /// [CommonMP][ver 1.1.0][2010/10/01][修正]
    /// </para>
    /// </remarks>
    public class McTestReadD3CSVFileModel : McBasicFileInCtl
    {
        /// <summary> 内部変数 </summary>
        McTestReadD3CSVFileInfo m_csInFileInfo = 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)
        {
            bool bRtn = true;
            if (lOutputDataNum == 0)
            {
                // 警告（エラーではない）
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckWarningData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND, 
                     Properties.Resources.STATEMENT_NO_SND_PORT );
               // csErrorInf.AddCheckWarningData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND, "No send port.");
            }

            for (long lP = 0; lP < lOutputDataNum; lP++)
            {   // 出力側接続線数分チェックを行う
                if (McModelSampleDefine.IN_OUT_PATTERN_ANY_D3.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                {   // ３次元配列セル出力ならば
                    m_csInFileInfo.m_lOutPutPortNum += 1;
                    long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                    long lCellDim = csOutputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);
                    if (this.m_csInFileInfo.m_lDim1 > lD1 || this.m_csInFileInfo.m_lDim2 > lD2 || this.m_csInFileInfo.m_lDim3 > lD3)
                    {
                        // エラー
                        bRtn = false;
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                             Properties.Resources.STATEMENT_CELLDIM_TOO_SHORT_S + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                       //      "Cell Dimension is too short. (Send To " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                    }
                }
                else
                {
                    // エラー
                    bRtn = false;
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                        Properties.Resources.STATEMENT_UNEXPECT_DATA_TYPE );
                   // csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                   //     "Unexpected send data type.");
                }
            }

            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;
            string  DispStatement = "";

            // 送信済み関連情報初期値
            m_csInFileInfo.m_csLastDataSendTime = HySTime.DEFAULT_TIME.Clone();
            m_csInFileInfo.m_lSndRcrdNum = 0;
            
            // CSV入力データの格納用クラス
            if (m_csInFileInfo.m_csReadCSVData == null)
            {
                m_csInFileInfo.m_csReadCSVData = new HySCSVFileDim3Data();
            }

            m_csInFile = new HySFile(m_csInFileInfo.m_sInPutFile);
            if (m_csInFile.Exist() == true)
            {   // データの読み込み
                m_csInFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
                m_csInFileInfo.m_lRecNum = m_csInFileInfo.m_csReadCSVData.ReadCSVFile(m_csInFile);
                m_csInFile.Close();
                if (m_csInFileInfo.m_lRecNum > 0)
                {
                    bRtn = true;
                    HySDataLinkedList csHoldData = m_csInFileInfo.m_csReadCSVData.GetDataList();
                    csHoldData.SetCursorFirst(); // 読み出しカーソル位置を最初に持ってきておく
                    m_csInFileInfo.m_csNextSndRcrd = csHoldData.GetCursorData() as　HySCSVFileDim3Data.CSVDim3Recorde;

                    m_csInFileInfo.m_csReadCSVData.GetDimention(ref m_csInFileInfo.m_lDim1, ref m_csInFileInfo.m_lDim2, ref m_csInFileInfo.m_lDim3);
                    for (long lP = 0; lP < m_lOutputDataNum; lP++)
                    {
                        long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                        long lCellDim = m_OutputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);
                        if (this.m_csInFileInfo.m_lDim1 > lD1 || this.m_csInFileInfo.m_lDim2 > lD2 || this.m_csInFileInfo.m_lDim3 > lD3)
                        {   // 伝送クラスが、読み込みデータを送信出来ない。
                            bRtn = false;

                            // ver1.5 エラートレース日本語対応
                            DispStatement = Properties.Resources.STATEMENT_WARNING_CELLDIMENSION + " (" +
                                            Properties.Resources.STATEMENT_SENDTO +
                                            m_OutputCellData[lP].GetLowerElementID().ToString() + ")";
                            McLog.DebugOut(this.GetSimulationTime(), this.GetID(), McLog.SYSTEM, "Initialize", DispStatement);
                            //McLog.DebugOut(this.GetSimulationTime(), this.GetID(), McLog.SYSTEM, "Initialize",
                            //     "Cell Dimension is too short. (Send To " + m_OutputCellData[lP].GetLowerElementID().ToString() + ")");
                        }
                    }
                }
                else
                {   // ファイル読込エラー

                    // ver1.5 エラートレース日本語対応
                    DispStatement = Properties.Resources.STATEMENT_FAILED_READ_DATAFILE + " (" + m_csInFile + ")";
                    McLog.DebugOut(this.GetSimulationTime(), this.GetID(), McLog.SYSTEM, "Initialize", DispStatement);
                    //McLog.DebugOut(this.GetSimulationTime(), this.GetID(),
                    //    McLog.SYSTEM, "Initialize", "Cannot read data file(" + m_csInFile + ")");
                }
            }
            // Ver1.5 追加（SetProperty で事前チェックするため以下コメント）
            //else
            //{   // 読み込みファイルが存在しない。
            //    McLog.DebugOut(this.GetSimulationTime(), this.GetID(),
            //        McLog.SYSTEM, "Initialize", "Cannot open data file(" + m_csInFileInfo.m_sInPutFile + ")");
            //}
           
            return bRtn;
        }

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

            HySTime csCursTm = HySTime.DEFAULT_TIME.Clone();
            HySCellData[,,] csSndCellData = null;
            HySCSVFileDim3Data.CSVDim3Recorde.CSVDim2Recorde[] csReadDataD2 = null;
            HySCSVFileDim3Data.CSVDim3Recorde.CSVDim2Recorde.CSVRowData[] csReadData = null;
            double[] dReadData = null;

            // 送信すべき時系列データリスト
            HySDataLinkedList csHoldData = m_csInFileInfo.m_csReadCSVData.GetDataList();
            csHoldData.SetCursorFirst();
            for (long lNum = 0; lNum < m_csInFileInfo.m_lRecNum; lNum++)
            {   // 時系列データ数分繰り返し
                if (lNum < m_csInFileInfo.m_lSndRcrdNum)
                {   // 既に送信した情報は空読み（なにもしない）
                    csHoldData.MoveCursorNext();
                    continue;
                }
                // 次に送信すべきレコード(カーソルデータ）
                m_csInFileInfo.m_csNextSndRcrd = csHoldData.GetCursorData() as HySCSVFileDim3Data.CSVDim3Recorde;

                if (m_csInFileInfo.m_csNextSndRcrd.GetTime().After(this.GetSimulationTime()) != true)
                {  // カーソルデータが現在時刻よりも前 or 同じならば 送信しなければならない
                    if( m_csInFileInfo.m_csNextSndRcrd.GetTime().After(m_csInFileInfo.m_csLastDataSendTime) == true )
                    {   // 送信済み時刻よりも後の情報ならば　送信しなければならない

                        csReadDataD2 = m_csInFileInfo.m_csNextSndRcrd.GetData();
                        for (long lP = 0; lP < lOutputDataNum; lP++)
                        {   // 送信接続数繰り返し

                            csOutputCellData[lP].SetCurrentTime(m_csInFileInfo.m_csNextSndRcrd.GetTime());
                            csSndCellData = csOutputCellData[lP].PrepareSendCellD3();  // 送信情報の準備
                            for (long lLp3 = 0; lLp3 < m_csInFileInfo.m_lDim3; lLp3++)
                            {   // 配列３
                                csReadData = csReadDataD2[lLp3].GetData();
                                for (long lLp2 = 0; lLp2 < m_csInFileInfo.m_lDim2; lLp2++)
                                {   // 配列２
                                    dReadData = csReadData[lLp2].GetData();
                                    for (long lLp1 = 0; lLp1 < m_csInFileInfo.m_lDim1; lLp1++)
                                    {   // 配列１
                                        csSndCellData[lLp1, lLp2, lLp3].m_dData[0] = dReadData[lLp1];
                                    }
                                }
                            }

                            csOutputCellData[lP].SendData();
                        }   // end of for(送信接続数）
                        m_csInFileInfo.m_csLastDataSendTime.SetTime(m_csInFileInfo.m_csNextSndRcrd.GetTime()); // 送信時刻の設定
                        m_csInFileInfo.m_lSndRcrdNum += 1;
                    }
                }
                else
                {
                    // 今回は送信しない
                    break;
                }
            }

            return lRtn;
        }

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

        // Ver1.5 追加（ファイルの有無チェック）引数追加
        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetProperty(csCellMdlPropertyInfo, ref csErrorInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <param name="csErrorInfo">エラー情報</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo, ref McStructErrorInfo csErrorInfo)
        {
            bool bRtn = true;   // Ver1.5 追加（ファイルの有無チェック）

            // 使用しやすいようにキャストしておく
            m_csInFileInfo = (McTestReadD3CSVFileInfo)m_csCalInfo;

            McModelPropertyInfo csPropInf = csCellMdlPropertyInfo as McModelPropertyInfo;
            if (csPropInf != null)
            {
                // CommonMPVer1.0 で作成したプロジェクトファイルの互換性を保つため
                string sVerInf = "";
                csPropInf.GetInfo("sVer", ref sVerInf);
                if (sVerInf != "")
                {   // Ver1.1以後の設定ならば
                    string sInFileName = "";
                    // 入力ファイルの設定
                    csPropInf.GetInfo("m_csInFileNameWithPath", ref sInFileName);

                    // 相対パス設定値を絶対パス化
                    //m_csInFileNameWithFullPath = this.GetProjectGroupDirectory() + new HySString("\\" + sInFileName);
                    m_csInFileInfo.m_sInPutFile = this.GetProjectGroupDirectory().ToString() + "\\" + sInFileName;
                }
                else
                {   // Ver1.0 での設定ならば
                    csPropInf.GetInfo("m_csInFileNameWithPath", ref m_csInFileInfo.m_sInPutFile);
                }

                // Ver1.5 追加（ファイルの有無チェック）
                HySFile csFile = new HySFile(m_csInFileInfo.m_sInPutFile);
                if (csFile.Exist() != true)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInfo.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                          Properties.Resources.STATEMENT_FILE_NO_OR_INVALID + m_csInFileInfo.m_sInPutFile);
                   // csErrorInfo.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_D3CSV_FILE_IN_KIND,
                   //      "入力ファイルが未設定です。または不正なファイルです。" + m_csInFileInfo.m_sInPutFile);
                    bRtn = false;
                }

                csPropInf.GetInfo("m_lDim1", ref this.m_csInFileInfo.m_lDim1);
                csPropInf.GetInfo("m_lDim2", ref this.m_csInFileInfo.m_lDim2);
                csPropInf.GetInfo("m_lDim3", ref this.m_csInFileInfo.m_lDim3);
            }

            return bRtn;
        }

        // Ver1.5 追加（プロジェクトプロパティ画面）
        /// <summary><para>method outline:</para>
        /// <para>モデルが読み込むデータファイル名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>List csRtnList = GetReadFiles()</para>
        /// </example>
        /// <param name="">なし</param>
        /// <returns> データファイル名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override List<string> GetReadFiles()
        {
            List<string> csRtnList = new List<string>();
            csRtnList.Add(System.IO.Path.GetFileName(m_csInFileInfo.m_sInPutFile));
            return csRtnList;
        }
    }
}
