// <summary>ソースコード：HYMCO_CUI制御専用クラス</summary>
// <author>CommonMP</author>

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

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Data.StructInfo;
using CommonMP.HYMCO.CoreImpl.FigureUnity;

namespace CommonMP.HYMCO.CUI.HymcoCUI
{
    /// <summary><para>class outline:</para>
    /// <para>HYNCO CUI 時の演算中制御を行う(シングルスレッド動作)</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class McCUISimThreadController : HySSimThreadController
    {
        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimThreadController csController = new HySSimThreadController(csSimulator) </para>
        /// </example>
        /// <param name="csSimulator">シミュレーター</param>
        /// <returns>生成インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McCUISimThreadController(HySSimulatorRoot csSimulator)
            : base(csSimulator)
        {
        }

        // ====================================
        // 演算実行
        // ====================================


        /// <summary><para>method outline:</para>
        /// <para>イベントを受け取った時に動作するメソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = EventCallback( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>各実装クラスは受け取ったイベント毎に処理を行う</para>
        /// </remarks>
        public override bool EventCallback(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "McCUISimThreadController","EventCallback", "start");
            bool bRtn = false;
            long lEventNo = ((HySEventObject)csEvent).GetEventNo();

            
            if (lEventNo == HySEventObject.CMND_MODEL_CONSTRUCTION)
            {   // シミュレーションモデル作成開始指示
                bRtn = this.ModelConstruction(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_INITIALIZE_SIMULATION)
            {   // シミュレーション初期化指示
                bRtn = this.InitializeSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_START_SIMULATION)
            {   // シミュレーション開始指示
                bRtn = this.StartSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_PAUSE_SIMULATION)
            {   // シミュレーション中断指示
                bRtn = this.PauseSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_RESTART_SIMULATION)
            {   // シミュレーション再開指示
                bRtn = this.RestartSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_STOP_SIMULATION)
            {   // シミュレーション強制終了指示
                bRtn = this.StopSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_REPORT_SIMU_PROGRESS)
            {   // シミュレーション計算進捗状況報告指示
                bRtn = this.ReportSimuProgress(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_RENEW_INPUTDATA)
            {   // シミュレーション入力情報取り込み指示(入力情報が更新された場合等)指示
                //bRtn = this.ReportSimuProgress(csEvent);
                bRtn = this.OnlineSetPrpty(csEvent);
            }
            else
            {   // その他のイベント
                bRtn = m_csSimulator.CmdArbitraryEvent(csEvent);
            }
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "McCUISimThreadController","EventCallback", "end");

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントを送る</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = PutEvent( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送るイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>自分からイベントを送信する時に使用する</para>
        /// </remarks>
        /// 
        public override bool PutEvent(HySSysEvent csEvent)
        {
            // Do nothing
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>システム終了準備完了判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = ExitOK( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : システムExit準備OK　、false : システムExit準備NG</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool ExitOK()
        {
            // Do nothing
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算完了したという報告</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> NoticeCompleteCalculation(　) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void NoticeCompleteCalculation()
        {
            // Do Nothing
        }

        /// <summary><para>method outline:</para>
        /// <para>内部演算モデル作成処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = ModelConstruction(csEvent) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool ModelConstruction(HySSysEvent csEvent)
        {
            bool bRtn = false;
            if (m_csSimulator != null)
            {
                bRtn = m_csSimulator.ModelConstruction(csEvent);
            }
            // Do Nothing
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーションの初期化</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = InitializeSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// シミュレーション演算中のスレッドからコールしてはならない
        /// 　（EventCallback()以外からのコール禁止）
        /// </para>
        /// </remarks>
        protected override bool InitializeSimulation(HySSysEvent csEvent)
        {
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "McCUISimThreadController","InitializeSimulation", "start");
            bool bRtn=true;

            HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;
            // 時刻設定
            m_csSimulator.SetSimuStartTime(csContainer.GetStartTime());
            m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime());
            m_csSimulator.SetSimuTime(csContainer.GetSimuTime());
            m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime());
            // 初期化開始
            bRtn = m_csSimulator.CmdInitializeSimulation(csEvent);

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の開始</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = StartSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// シミュレーション演算中のスレッドからコールしてはならない
        /// 　（EventCallback()以外からのコール禁止）
        /// </para>
        /// </remarks>
        protected override bool StartSimulation(HySSysEvent csEvent)
        {      
            bool bRtn = false;
            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "McCUISimThreadController","StartSimulation", "start");

            m_bThreadStatus = THREAD_AT_WORK;
            bRtn = m_csSimulator.CmdStartSimulation(csEvent);
            //if (m_csSimulator.CmdStartSimulation(csEvent) == true)
            //{
            //    bRtn = m_csSimulator.CmdRestartSimulation(csEvent);
            //}
            //else
            //{
            //    HySLog.LogOut(HySLog.SYSTEM_DEBUG, "McCUISimThreadController", "StartSimulation", "start");
            //}

            m_bThreadStatus = THREAD_NOT_WORK;
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の中断</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = PauseSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool PauseSimulation(HySSysEvent csEvent)
        {
            return m_csSimulator.CmdPauseSimulation(csEvent);
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の再開</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = RestartSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool RestartSimulation(HySSysEvent csEvent)
        {
            bool bRtn = true;

            HySSimulationDataContainer csContainer = m_csSimulator.GetContainer() as HySSimulationDataContainer;

            // 時刻設定
            //m_csSimulator.SetSimuStartTime(csContainer.GetStartTime());  <-- これを行ってはならない（復元したスタートタイムを消してしまう）
            m_csSimulator.SetSimuGoalTime(csContainer.GetGoalTime()); // <-- これは必要（最終ゴールが　復元後変化する）
            //m_csSimulator.SetSimuTime(csContainer.GetSimuTime());  <-- これを行ってはならない（復元した経過タイムを消してしまう）
            m_csSimulator.SetSimuDeltaTime(csContainer.GetDeltaTime()); // <-- これは必要（復元後δTが変化することもある）

            bRtn = m_csSimulator.CmdRestartSimulation(csEvent);
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算の終了</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = StopSimulation( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool StopSimulation(HySSysEvent csEvent)
        {
            // Do nothing
            return true;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション計算進捗状況報告</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = ReportSimuProgress( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント（必要ならば使用する）</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool ReportSimuProgress(HySSysEvent csEvent)
        {
            // Do nothing
            return true;
        }


        /// <summary><para>method outline:</para>
        /// <para>シミュレーション中のプロパティ情報等変更</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = OnlineSetPrpty( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual bool OnlineSetPrpty(HySSysEvent csEvent)
        {
            McFigureUnity csFigUnty = m_csSimulator as McFigureUnity;

            HySSimulationDataContainer csContainer = ((HySEventObject)csEvent).GetData() as HySSimulationDataContainer;
            McStructInfo csStructInfo = (McStructInfo)csContainer.GetData(McDefine.HYM_DATA_STRUCT_INFO);
            McStructErrorInfo csCheckInf = csContainer.GetData(McDefine.HYM_DATA_CHECK_INFO) as McStructErrorInfo;

            this.OnlineSetPrpty(ref csFigUnty, csStructInfo, ref csCheckInf);
            HySID csID = csFigUnty.GetID() as HySID;
            McModelInfo csMdlInfo = csStructInfo.GetModelInfo();
            csFigUnty.CmndSetOnlineProperty(csID, csMdlInfo, ref csCheckInf);

            // start of ver1.6.1
            HySTime csSimTime = csContainer.GetSimuTime() as HySTime;
            csFigUnty.SetSimulationTime(csSimTime);
            csFigUnty.SetSimuStartTime(csSimTime);
            // end of ver1.6.1
            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>シミュレーション中のプロパティ情報等変更</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = OnlineSetPrpty( ref csFigUnty,csGrpElmPrnt,ref csCheckInf ) </para>
        /// </example>
        /// <param name="csFigUnty">HIMCO シミュレーター</param>
        /// <param name="csGrpElmPrnt">Gr化エレメント</param>
        /// <param name="csCheckInf">エラー等情報格納クラス</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual bool OnlineSetPrpty(ref McFigureUnity csFigUnty, McStructGroupElement csGrpElmPrnt,ref McStructErrorInfo csCheckInf)
        {
            long lElmNum = csGrpElmPrnt.GetElmCount();
            for (long llp = 0; llp < lElmNum; llp++)
            {
                McStructElement csStrElm = csGrpElmPrnt.GetElement(llp);
                McStructGroupElement csGrpElm = csStrElm as McStructGroupElement;
                if (csGrpElm == null)
                {   // Gr化要素ではない
                    // Do Nothing
                }
                else
                {   // Gr化要素である
                    this.OnlineSetPrpty(ref csFigUnty, csGrpElm,ref csCheckInf);
                }
                HySID csElmID = csStrElm.GetID() as HySID;
                McModelInfo csMdlInfo = csStrElm.GetModelInfo();
                csFigUnty.CmndSetOnlineProperty(csElmID, csMdlInfo, ref csCheckInf);
            }
            return true;
        }
        // ====================================
        // スレッド制御
        // ====================================

        /// <summary><para>method outline:</para>
        /// <para>スレッド起動（別スレッドで this.ThreadRun()が動作を開始する）</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStart() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override void ThreadStart()
        {
            // Do nothing
        }
        /// <summary><para>method outline:</para>
        /// <para>スレッド処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> スレッド起動時に呼ばれる </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override void ThreadRun()
        {
            // Do nothing
        }
        /// <summary><para>method outline:</para>
        /// <para>スレッドを終了させる</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStop() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override void ThreadStop()
        {
            // Do Nothing
        }

        /// <summary><para>method outline:</para>
        /// <para>スレッドを終了の見張り</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ThreadStopWatchDog()
        /// </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override void ThreadStopWatchDog()
        {
            //Do Nothing
        }
        
    } // end of class
} // end of namespace
