// <summary>ソースコード：システム内イベント制御クラス</summary>
// <author>CommonMP</author>

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

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

namespace CommonMP.HYSSOP.CoreImpl.HSController
{
    /// <summary><para>class outline:</para>
    /// <para>システム内イベント制御クラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>無し</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class HySEventManager : HySEventMngRoot
    {
        /// <summary>イベントQueue</summary>
        protected HySQueue m_csEventQueue = new HySQueue(1024);
        /// <summary>処理終了フラグ</summary>
        protected Boolean m_bSystemStopFlg = false;
        /// <summary>スレッド動作中フラグ</summary>
        protected bool m_bThreadWorkFlg = false;

        /// <summary>システムコントローラー</summary>
        protected HySSystemController m_csSystemCtl = null;

        /// <summary>業務制御</summary>
        protected HySBusiController m_csBusiCtl = null;

        /// <summary>ビューアコントローラー</summary>
        protected HySViewerController m_csViewerCtl = null;

        /// <summary>シミュレーションコントローラー</summary>
        protected HySSimulationController m_csSimCtl = null;

        /// <summary>ライブラリ管理</summary>
        protected HySLibraryController m_csLibraryCtl = null;

        /// <summary>ＧＩＳ管理</summary>
        protected HySGISController m_csGISCtl = null;


        /// <summary><para>method outline:</para>
        /// <para>システム制御クラスを設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> AddSysController( csController ) </para>
        /// </example>
        /// <param name="csController">システム制御クラス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void AddSysController(HySControllerRoot csController)
        {
            csController.SetEventManager(this); // イベントマネージャーを設定

            long lToNo = csController.AdressIDNo();
            if (lToNo == HySSysEvent.OBJID_SYSCONTROLLER)
            {   // 宛先がシステムコントローラーならば
                m_csSystemCtl = (HySSystemController)csController;
            }
            else if (lToNo == HySSysEvent.OBJID_BUSIPROCEDURE)
            {   // 宛先が業務コントローラーならば
                m_csBusiCtl = (HySBusiController)csController;
            }
            else if (lToNo == HySSysEvent.OBJID_VIEWER)
            {   // 宛先がビューアコントローラーならば
                m_csViewerCtl = (HySViewerController)csController;
            }
            else if (lToNo == HySSysEvent.OBJID_SIMULATOR)
            {   // 宛先がシミュレーションコントローラーならば
                m_csSimCtl = (HySSimulationController)csController;
            }
            else if (lToNo == HySSysEvent.OBJID_LIBMANAGER)
            {   // 宛先がライブラリコントローラーならば
                m_csLibraryCtl = (HySLibraryController)csController;
            }
            else if (lToNo == HySSysEvent.OBJID_GISCONTROLLER)
            {   // 宛先がＧＩＳコントローラーならば
                m_csGISCtl = (HySGISController)csController;
            }
        }

        
        /// <summary><para>method outline:</para>
        /// <para>立ち上がり処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean WakeUp()
        {
            m_bSystemStopFlg = false;

            ThreadStart ThSt = new ThreadStart(this.ThreadRun);
            Thread t = new Thread(ThSt);
            t.Start();

            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>終了処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ShutDown( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void ShutDown()
        {
            m_bSystemStopFlg = true; // 終了を設定
            HySEventObject csEvent = new HySEventObject(HySSysEvent.OBJID_EVENTMANAGER, HySEventObject.CMND_SHUTDOWN_SYSTEM);
            this.PutEvent(csEvent);
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントを宛先に従ってシステム制御クラスにポストする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = PutEvent( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送るイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean PutEvent(HySSysEvent csEvent)
        {
            return m_csEventQueue.PushObject(csEvent);
        }

        /// <summary><para>method outline:</para>
        /// <para>システム終了準備完了判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean 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 virtual Boolean ExitOK()
        {
            if (m_bThreadWorkFlg == true)
            { return false; }
            else
            { return true; }
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントを宛先に従ってシステム制御クラスにポストする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = BranchEvent( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送るイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean BranchEvent(HySSysEvent csEvent)
        {
            bool bRtn = false;
            long lToNo = csEvent.To();
            if (lToNo == HySSysEvent.OBJID_SYSCONTROLLER)
            {   // 宛先がシステムコントローラーならば
                if (m_csSystemCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csSystemCtl.EventCallback()");
                    bRtn = m_csSystemCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo == HySSysEvent.OBJID_BUSIPROCEDURE)
            {   // 宛先が業務コントローラーならば
                if (m_csBusiCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csBusiCtl.EventCallback()");
                    bRtn = m_csBusiCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo == HySSysEvent.OBJID_VIEWER)
            {   // 宛先がビューアコントローラーならば
                if (m_csViewerCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csViewerCtl.EventCallback()");
                    bRtn = m_csViewerCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo == HySSysEvent.OBJID_SIMULATOR)
            {   // 宛先がシミュレーションコントローラーならば
                if (m_csSimCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csSimCtl.EventCallback()");
                    bRtn = m_csSimCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo == HySSysEvent.OBJID_LIBMANAGER)
            {   // 宛先がライブラリコントローラーならば
                if (m_csLibraryCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csLibraryCtl.EventCallback()");
                    bRtn = m_csLibraryCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo == HySSysEvent.OBJID_GISCONTROLLER)
            {   // 宛先がＧＩＳコントローラーならば
                if (m_csGISCtl != null)
                {
                    //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::PutEvent", "m_csGISCtl.EventCallback()");
                    bRtn = m_csGISCtl.EventCallback(csEvent);
                }
            }
            else if (lToNo ==  HySSysEvent.OBJID_EVENTMANAGER)
            {   // イベントマネージャーならば
                if (((HySEventObject)csEvent).GetEventNo() == HySEventObject.CMND_SHUTDOWN_SYSTEM)
                {
                    m_bSystemStopFlg = true;
                }
            }
            return bRtn;
        }
        
        /// <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 virtual void ThreadRun()
        {
            // PT-003 言語切り替え不具合修正　地域情報をTheadにセット
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentCulture;

            HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::ThreadRun", "ThreadRun start");
            HySEventObject csEvent; // イベント
            m_bThreadWorkFlg = true; 
            for (;;)
            {// ∞ループ

                csEvent = (HySEventObject)(m_csEventQueue.PullObject());
                this.BranchEvent(csEvent);
                if (m_bSystemStopFlg == true)
                {
                    break;
                }
                System.Threading.Thread.Sleep(0); // スレッドの隙間を空ける <-- 重要
            }
            m_bThreadWorkFlg = false;
            //HySLog.LogOut(HySLog.SYSTEM_DEBUG, "HySEventManager::ThreadRun", "ThreadRun end"); <-- Log が機能していない可能性あり
        }
    }
}
