// <summary>シミュレータ制御クラス</summary>
// <author>CommonMP</author>

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

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

namespace CommonMP.HYMCO.CUI.HymcoCUI
{
    /// <summary><para>class outline:</para>
    /// <para>シミュレータ制御クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class McCUISimulationController: HySSimulationController
    {
        /// <summary> HYMCO CUI シングルスレッド制御 </summary>
        McCUISimThreadController m_csHymcoThreadCtl = null;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimulationController csController = new McCUISimulationController( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McCUISimulationController()
        {
        }

        /// <summary><para>method outline:</para>
        /// <para>システム構成要素を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.SetSysUnit( csUnit ) </para>
        /// </example>
        /// <param name="csUnit">システム構成要素</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void SetSysUnit(HySSysUnit csUnit)
        {
            // Do nothing
        }


        /// <summary><para>method outline:</para>
        /// <para>イベントを受け取った時に動作するメソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.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)
        {
            Boolean bRtn = false;
            //HySKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetSimKind();
            //HySID csID = ((HySEventObject)csEvent).GetSuppID();
            long lEventNo = ((HySEventObject)csEvent).GetEventNo();

            if (lEventNo == HySEventObject.CMND_NEW_SIMULATOR_CREATE)
            {   // シミュレーター生成ならば
                bRtn = this.CmndCreateNewSimulator(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_SIMULATOR_RESTORE)
            {
                // 演算中断復元処理ならば
                bRtn = this.CmdStructureSimulation(csEvent);
            }
            else if (lEventNo == HySEventObject.CMND_SIMULATOR_SAVE)
            {
                // 演算中断保存処理ならば
                bRtn = this.CmdSaveSimulation(csEvent);
            }
            else
            {   // シミュレーター生成以外のイベントならば
                if (m_csHymcoThreadCtl != null)
                {
                    bRtn = m_csHymcoThreadCtl.EventCallback(csEvent);
                }
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントをイベント管理クラスにポストする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.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)
        {
            csEvent.SetFrom(HySSysEvent.OBJID_SIMULATOR);
            return m_csEventMng.PutEvent(csEvent);
        }

        /*
        /// <summary><para>method outline:</para>
        /// <para>初期化処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void Initialize()
        {
            HySSimulatorFactory csSimulatorFactory = null;
            HySObjectKind csSimKind = null;
            HySString csSimKey = null;
            // 複数の　業務生成ファクトリに対してそれぞれ業務を作成させる
            long lFctNo = m_csFactoryManager.GetFactoryNum();
            for (long lLp = 0; lLp < lFctNo; lLp++)
            {
                csSimulatorFactory = m_csFactoryManager.GetFactory(lLp) as HySSimulatorFactory;
                if (csSimulatorFactory != null)
                {
                    csSimKind = (HySObjectKind)csSimulatorFactory.GetSimKind();
                    csSimKey = (HySString)csSimKind.ToString();
                    m_csSimulatorFactoryTbl.Add(csSimKey.GetString(), csSimulatorFactory);  // シミュレーション管理テーブルへ積み込み
                }
            }
        }
        */

        /// <summary><para>method outline:</para>
        /// <para>立ち上がり処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool WakeUp()
        {
            // Do nothing
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>終了処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool ShutDown()
        {
            HySEventObject csEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
            if (m_csHymcoThreadCtl != null)
            {
                m_csHymcoThreadCtl.EventCallback(csEvent);
            }

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>システム終了準備完了判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.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 Boolean ExitOK()
        {
            // Do nothing
            return true;
        }


        /// <summary><para>method outline:</para>
        /// <para>シミュレーターを新規に作成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySControllerRoot.CmndCreateNewSimulator(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override Boolean CmndCreateNewSimulator(HySSysEvent csEvent)
        {
            Boolean bRtn = false;

            // イベント内の　シミュレーター識別子から　関連ファクトリを探す
            HySObjectKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
            HySString csKey = (HySString)csSimKind.GetString();
            HySSimulatorFactory csSimulatorFactory = (HySSimulatorFactory)m_csSimulatorFactoryTbl[csKey.ToString()];

            if (csSimulatorFactory != null)
            {   // 対象ファクトリ有り

                HySID csID = ((HySEventObject)csEvent).GetSuppID();  // シミュレーター固有ID

                // シミュレーター本体を作成させる
                HySSimulatorRoot csSimulator = csSimulatorFactory.CreateSimulator(csSimKind, csID); // シミュレーター設定
                if (csSimulator != null)
                {   // シミュレーター作成成功ならば
                    bRtn = true;

                    // にコンテナ等を設定
                    HySSimulationDataContainer csContainer = (HySSimulationDataContainer)((HySEventObject)csEvent).GetData(); // コンテナ取得
                    if (csContainer == null)
                    {
                        csContainer = (HySSimulationDataContainer)csSimulatorFactory.CreateDataContainer(csSimKind, csID); // コンテナ生成
                    }
                    else
                    {
                        csContainer.SetID(csID);
                    }
                    csSimulator.SetContainer(csContainer); // データコンテナ設定

                    // シミュレーター動作用のスレッド制御を生成する
                    m_csHymcoThreadCtl = new McCUISimThreadController(csSimulator);
                    m_csHymcoThreadCtl.SetController(this);

                    // シミュレーターに対して、自らに関連するファクトリクラスを設定する
                    csSimulator.SetSimulatorFactory(csSimulatorFactory);

                    // シミュレーターの立ち上がり初期化
                    csSimulator.Initialize();
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController","CmndCreateNewSimulator", 
                        Properties.HymcoCUIResources.STATEMENT_NOT_CREATE_SIM + "(" + csKey.ToString() +")" );
                   // HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController", "CmndCreateNewSimulator", "Cannot Create Simulator(" + csKey.ToString() + ")");
                }
            }
            else
            {
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController","CmndCreateNewSimulator", 
                    Properties.HymcoCUIResources.STATEMENT_NOT_SIM_FACT +"(" + csKey.ToString() + ")");
               // HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController", "CmndCreateNewSimulator", "Cannot be find SimulatorFactory(" + csKey.ToString() + ")");
            }   // end of if(csSimulatorFactory)
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーター取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimulator csSim = HySSimThreadController.GetSimulator(csKind,csID) </para>
        /// </example>
        /// <param name="csKind">シミュレーター種別</param>
        /// <param name="csID">シミュレーター識別子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override HySSimulatorRoot GetSimulator(HySObjectKind csKind, HySID csID)
        {
            HySSimulatorRoot csRtn = null;
            if (m_csHymcoThreadCtl != null)
            {
                csRtn = m_csHymcoThreadCtl.GetSimulator();
            }
            return csRtn;
        }
        

        /// <summary><para>method outline:</para>
        /// <para>演算中断保存処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = CmdSaveSimulation(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override Boolean CmdSaveSimulation(HySSysEvent csEvent)
        {
            Boolean bRtn = false;
            HySSimulatorRoot csSimulator;
            HySEventObject csHySEvent = (HySEventObject)csEvent;
            HySString csFilePath = (HySString)csHySEvent.GetData();
            HySFile csFile = new HySFile(csFilePath);
            try
            {
                if (m_csHymcoThreadCtl != null)
                {
                    // シミュレータの取得
                    csSimulator = m_csHymcoThreadCtl.GetSimulator();
                    // ファイル出力用データクラスの作成
                    HySFileOutData csFileOutData = new HySFileOutData();
                    // シミュレータに対して、データクラスを提供するのみ。データの出力はシミュレータ自身が行う。
                    bRtn = csSimulator.SerializeAllInfo(csFileOutData);
                    if (bRtn == true)
                    {
                        // 演算情報出力処理が正常終了した場合
                        if (csFile.Open(HySFile.OPEN_MODE.CREATE_NEW, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR) == 0)
                        {
                            // ファイルへ書き込み
                            csFile.DataWrite(csFileOutData);
                            csFile.Close();
                        }
                        else
                        {
                            // ファイルオープン処理が失敗した場合(他プロセスにより開かれている等)
                            bRtn = false;
                        }
                    }
                    // 演算情報出力処理が異常終了した場合
                    csFile = null;
                }
            }
            catch (Exception ex)
            {
                bRtn = false;
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算中断復元処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = CmdStructureSimulation(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override Boolean CmdStructureSimulation(HySSysEvent csEvent)
        {
            Boolean bRtn = false;

            HySKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
            HySID csID = ((HySEventObject)csEvent).GetSuppID();
            HySEventObject csHySEvent = (HySEventObject)csEvent;
            HySString csFilePath = (HySString)csHySEvent.GetData();
            HySFile csFile = new HySFile(csFilePath);
            HySFileOutData csFileOutData = null;

            try
            {
                if (csFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) == 0)
                {
                    // ファイルからデータクラスを読み込み
                    csFileOutData = (HySFileOutData)csFile.DataRead();
                    csFile.Close();
                }
                else
                {
                    // ファイルオープン処理が失敗した場合(他プロセスにより開かれている等)

                    // 失敗イベント送信
                    HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE_NG);
                    csEventObj.SetToSimKind(csSimKind);
                    PutEvent(csEventObj);
                    csFile = null;
                    return false;
                }
                // コンテナ取得
                HySSimulationDataContainer csContainer = (HySSimulationDataContainer)csFileOutData.GetContainer();
 
                // 開く対象のシミュレータがすでに存在するか確認
                if (m_csHymcoThreadCtl == null)
                {
                    // シミュレータの新規作成と復元開始
                    csHySEvent.SetData(csContainer);
                    bRtn = this.CmndCreateNewSimulator(csHySEvent);
                }
                HySSimulatorRoot csSimulator = m_csHymcoThreadCtl.GetSimulator();
                bRtn = csSimulator.StructureAllInfo(csFileOutData);

                csFile = null;
            }
            catch (Exception ex)
            {
                bRtn = false;
            }
            return bRtn;
        }
    }
}
