// <summary>ソースコード：ビューアジョブクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

using System.Diagnostics;


using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.Interface.HSViewer;
using CommonMP.HYSSOP.CoreImpl;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYSSOP.CoreImpl.HSGIS;
using CommonMP.HYSSOP.CoreImpl.HSSimulator;
using CommonMP.HYSSOP.CoreImpl.HSController;
using CommonMP.HYSSOP.OptionImpl.HSViewer.DotNetViewer;


namespace CommonMP.HYSSOP.OptionImpl.HSAddin.Lsor
{
    /// <summary><para>class outline:</para>
    /// <para>ビューアジョブクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/02/15][新規作成]</para>
    /// </remarks>
    public class HsAddinLsorViewerJob : HySDotNetViewerJob
    {
        
        /// <summary>Exe プロセス</summary>
        private Process m_process;

        /// <summary>Exe 実行ディレクトリパス</summary>
        private string m_sPath;


        [DllImport("USER32.DLL", CharSet = CharSet.Auto)]
        private static extern int ShowWindow(
            System.IntPtr hWnd,
            int nCmdShow
        );

        [DllImport("USER32.DLL", CharSet = CharSet.Auto)]
        private static extern bool SetForegroundWindow(
            System.IntPtr hWnd
        );


        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HsAddinLsorViewerJob csViewerJob = new HsAddinLsorViewerJob( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HsAddinLsorViewerJob 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HsAddinLsorViewerJob()
        {
            m_sPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        }

        /// <summary><para>method outline:</para>
        /// <para>メニューコールバック処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lRtn = MenuCallBack( lCallBackNo,bCheckOnOff ) </para>
        /// </example>
        /// <param name="lCallBackNo">メニューコールバック番号</param>
        /// <param name="bCheckOnOff">チェックオンオフフラグ</param>
        /// <returns>＝０：正常、≠０：異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long MenuCallBack(long lCallBackNo, Boolean bCheckOnOff)
        {
            long lRtn = -1;

            if (lCallBackNo == HysAddinLsorDefine.DISP_SCREEN)
            {   // 画面表示開始
                if (Run())
                {
                    lRtn = 0;
                }
            }
            else
            {
            }

            return lRtn;
        }

        /// <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 override Boolean Initialize()
        {
            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>終了処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = Terminate( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override Boolean Terminate()
        {
            //Exe終了
            if (!StopExe())
            {
                return false;
            }

            return true;
        }
        /// <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 override Boolean ExitOK()
        {
            // 処理中でなければ、本業務処理はＥｘｉｔしてもＯＫとしてtrue を返す
            if (IsRunning)
            {
                return false;
            }

            return true;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>イベントを受け取った時に動作するメソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean 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 Boolean EventCallback(HySSysEvent csEvent)
        {
            //Do Nothing;
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>スクリーン生成ファクトリ取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetScreen(csPrjID)</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySScreenFactory スクリーンファクトリ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual HySScreenFactory GetScreenFactory()
        { 
            return this.m_csScreenFactory;
        }

        // ★★
        // ToDo　コールバックに対応する処理が必要な場合に処理を追加する
        // ★★

        /// <summary><para>method outline:</para>
        /// <para>動作中判定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = IsRunning( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : Exe動作中　、false : Exe未動作</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>Exeが起動しているかを取得する。</para>
        /// </remarks>
        internal bool IsRunning
        {
            get
            {
                try
                {
                    return m_process != null && !m_process.HasExited;
                }
                catch (InvalidOperationException)
                {
                    return false;
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>Exeを起動する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = Run( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true: 起動成功または既に起動済み、false: 起動失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual bool Run()
        {
            if (IsRunning)
            {   //すでに起動中の場合、アクティブにします
                Activate();
                return true;
            }

            ProcessStartInfo proInfo = new ProcessStartInfo();
            proInfo.WorkingDirectory = m_sPath;
            //proInfo.FileName = "lsor.exe";
            proInfo.FileName = "HysAddinLsorGraphView.exe";

            // EXEを起動する
            m_process = new Process();
            try
            {
                m_process = Process.Start(proInfo);
            }
            catch (Exception e)
            {
                OutputLog("HsAddinLsorViewerJob", e.TargetSite.Name, e.Message + " (" + proInfo.WorkingDirectory + "\\" + proInfo.FileName + ")");
                return false;
            }


            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>Exeアクティブ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = Activate( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true: アクティブ成功、false: アクティブ失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>Exeをアクティブにする。</para>
        /// </remarks>
        private bool Activate()
        {
            try
            {
                //アクティブにする
                ShowWindow(m_process.MainWindowHandle, 1);
                SetForegroundWindow(m_process.MainWindowHandle);

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>Exe停止</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = StopExe( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>正常に終了した場合true、Exeが起動していない場合、終了処理でエラーが発生した場合false。</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>Exeが起動中であれば、Exeを終了させる。</para>
        /// </remarks>
        private bool StopExe()
        {
            if (!IsRunning)
            {   //起動していない
                return false;
            }

            //ユーザーの操作待ちの場合もあるので、アクティブにして操作の終了を促します。
            Activate();

            try
            {
                //クローズメッセージを送信してプロセス終了
                m_process.CloseMainWindow();

                //Exeが実際に終了するまで待機する（無制限）
                m_process.WaitForExit();

                ////Exeが実際に終了するまで待機する（5秒）
                //if (!m_process.WaitForExit(5 * 1000))
                //{
                //    //ユーザーの操作が終了しているかもしれないので、もう一度クローズメッセージを送信してみる
                //    m_process.CloseMainWindow();

                //    //Exeが実際に終了するまで待機する（5秒）
                //    if (!m_process.WaitForExit(5 * 1000))
                //    {
                //        OutputLog("HsAddinLsorViewerJob", "StopExe", "EXEの終了待ちでタイムアウトした為、EXEを強制終了します。");

                //        //強制終了
                //        m_process.Kill();

                //        return false;
                //    }
                //}
                return true;
            }
            catch (Exception e)
            {
                OutputLog("HsAddinLsorViewerJob", e.TargetSite.Name, e.Message);
                return false;
            }
        }


        /// <summary><para>method outline:</para>
        /// <para>ログ出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> OutputLog( className, methodName, message ) </para>
        /// </example>
        /// <param name="className">クラス名</param>
        /// <param name="methodName">メソッド名</param>
        /// <param name="message">メッセージ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal static void OutputLog(string className, string methodName, string message)
        {
            HySLog.LogOut(HySLog.ONLINE, className, methodName, message);
            Debug.Print("{0}.{1}: {2}", className, methodName, message);
        }


    }
}
