// <summary>ソースコード：ＨＹＭＣＯ　CUI-CommonMP制御ＡＰＩ</summary>
// <author>CommonMP</author>

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

using System.Threading;
using System.IO;
using System.Diagnostics;

using CommonMP.HYMCO.CUI.HymcoCUI;

namespace CommonMP.HYMCO.hymcoAPIh28
{
    /// <summary><para>class outline:</para>
    /// <para>常駐化CUI-CommonMP制御API（H28年版)クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.6.1][2016/12/01][新規作成]</para>
    /// </remarks>
    public class hymcoAPIh28
    {
        /// <summary>繰り返しモード</summary>
        public enum CUI_ZMode
        {
            /// <summary> -zr 繰り返し中にリセット有 </summary>
            Z_mode_R = 2,
            /// <summary> -zc 繰り返し中にリセット無：状態継続 </summary>
            Z_mode_C = 3
        }

        /// <summary>起動 hymco 登録情報リスト </summary>
        static List<HymcoMngData> g_RegHymcoList = new List<HymcoMngData>();


        /// <summary><para>method outline:</para>
        /// <para>常駐CUI-CommonMP登録</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>hymcoAPIh28.Z_ResisterHymco(eMode,lProcNo,sConfigFileName,sProjectFileName)</para>
        /// </example>
        /// <param name="eMode">繰り返しモード（初期化有り、継続）</param>
        /// <param name="lProcNo">プロセス識別番号</param>
        /// <param name="sConfigFileName">動作環境設定（confg）ファイル名</param>
        /// <param name="sProjectFileName">プロジェクトファイル名</param>
        /// <returns>=0:正常、=-1:起動不良、=-2:登録済み識別番号が存在している</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>登録後、hymco.exeが直ちに起動される</para>
        /// </remarks>
        static public long Z_ResisterHymco(
            CUI_ZMode  eMode,
            long       lProcNo,
            string     sConfigFileName,
            string     sProjectFileName )
        {
            long iCanAddFlg = 0;

            // ２重起動チェック
            for (int iLp = 0; iLp < g_RegHymcoList.Count; iLp++)
            {   // 既に起動したプロセス数分繰り返し
                if (g_RegHymcoList[iLp].m_lProcNo == lProcNo)
                {   // 同じプロセス識別番号が存在していれば
                    iCanAddFlg = -2;    // 重複
                    break;
                }
            }

            try
            {   // start of try
                // 起動開始
                if (iCanAddFlg == 0)
                {   // 追加OKならば
                    // １）情報を追加する
                    HymcoMngData csAddData = new HymcoMngData();
                    csAddData.m_eZMode = eMode;
                    csAddData.m_lProcNo = lProcNo;
                    csAddData.m_sConfigFileName = sConfigFileName;
                    csAddData.m_sProjectFileName = sProjectFileName;
                    g_RegHymcoList.Add(csAddData);

                    // ２）ロックファイルを作成する
                    DirectoryInfo csDi = Directory.GetParent(Directory.GetCurrentDirectory());
                    HymcoCUIProgram.m_sHomeDirectory = csDi.ToString(); // 現在のディレクトリ
                    HymcoCUIProgram.m_sLockFileName = HymcoCUIProgram.m_sHomeDirectory + @"\.\temp\" + HymcoDefine.LOCKFILE_NAME;
                    HymcoCUIProgram.CreateLockFile(lProcNo);

                    // ３）hymco を起動する。
                    if (HymcoCUIProgram.LockFileExist(lProcNo) == true)
                    {   // ロックファイルが生成されたならば

                        Process newProcess = new Process();    // プロセス生成
                        //newProcess.StartInfo.RedirectStandardOutput = true;  // コンソールを開かなくする(CommonMPが動作中のコンソール画面を開きたくないときには本行のコメントを外して下さい)
                        //newProcess.StartInfo.CreateNoWindow = true; // コンソール・ウィンドウを開かない(CommonMPが動作中のコンソール画面を開きたくないときには本行のコメントを外して下さい)

                        newProcess.StartInfo.UseShellExecute = false; // シェル機能を使用しない （必須）
                        newProcess.StartInfo.FileName = "hymco.exe";   // 起動ﾌﾟﾛｸﾞﾗﾑ
                        if (csAddData.m_eZMode == CUI_ZMode.Z_mode_C)
                        {   // 継続モード
                            newProcess.StartInfo.Arguments = "-zc " + lProcNo.ToString() + " " + sConfigFileName + " " + sProjectFileName;  // 起動引数
                        }
                        else
                        {   // 初期化有りモード
                            newProcess.StartInfo.Arguments = "-zr " + lProcNo.ToString() + " " + sConfigFileName + " " + sProjectFileName;  // 起動引数
                        }

                        if (newProcess.Start() == false)
                        {   // 起動できなければ
                            iCanAddFlg = -1;    // リターン値：異常
                        }
                    }
                    else
                    {    // ロックファイルが生成不可ならば
                        iCanAddFlg = -1;    // リターン値：異常
                    }
                }
            }   // end of try
            catch (Exception)
            {
                iCanAddFlg = -1; // リターン値：異常
            }
            return iCanAddFlg;
        }

        /// <summary><para>method outline:</para>
        /// <para>全CUI-CommonMPプロセスのkill</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>hymcoAPIh28.Z_KillAllHymco()</para>
        /// </example>
        /// <param name=""></param>
        /// <returns>常にゼロ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public long Z_KillAllHymco()
        {
            System.Diagnostics.Process[] p;
            //hymcoというプ名称を持つプロセスを取得
            p = System.Diagnostics.Process.GetProcessesByName("hymco");
            int iPNo = p.Length;
            if (iPNo > 0)
            {
                // 複数のCUI版CommonMPが動作している時、全てのプロセスを中断させるならば
                // p[i] 全てに対して　kill 命令を発行する必要がある。
                try
                {
                    for (int iLp = 0; iLp < iPNo; iLp++)
                    {
                        if (p[iLp].HasExited != true)
                        {   // プロセスが動作中ならば
                            //プロセスを強制終了
                            p[iLp].Kill();
                        }
                    }
                }
                catch
                {
                    // Do Nothing
                }
            }
            // 不要ロックファイルを破棄する
            for (int iLp = 0; iLp < g_RegHymcoList.Count; iLp++)
            {
                HymcoCUIProgram.DeleteLockFile(g_RegHymcoList[iLp].m_lProcNo);
            }
            // リストを全クリアする
            g_RegHymcoList.Clear(); 
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>全CUI-CommonMPプロセスの計算開始</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>hymcoAPIh28.Z_StartCalculation()</para>
        /// </example>
        /// <param name=""></param>
        /// <returns>常にゼロ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public long Z_StartCalculation()
        {
            // 不要メモリ破棄
            GC.Collect();
            
            // 全プロセスの計算開始
            for (int iLp = 0; iLp < g_RegHymcoList.Count; iLp++)
            {
                // 登録済みロックファイルをすべて削除
                HymcoCUIProgram.DeleteLockFile(g_RegHymcoList[iLp].m_lProcNo);    // 指定ロックファイル破棄
            }
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>全CUI-CommonMPプロセスの計算終了問い合わせ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>hymcoAPIh28.Z_IsCalculationCompleted()</para>
        /// </example>
        /// <param name=""></param>
        /// <returns>=true：計算完了、=false:計算未完了のプロセスがある</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public Boolean Z_IsCalculationCompleted()
        {
            Boolean bRtn = true;  // 戻り値

            for (int iLp = 0; iLp < g_RegHymcoList.Count; iLp++)
            {
                // 登録済みプロセスのロックファイルが一つでも存在しなければ false で返る
                if (HymcoCUIProgram.LockFileExist(g_RegHymcoList[iLp].m_lProcNo) == false)
                {   // ロックファイルが存在しない
                    bRtn = false;   // リターン値：false
                    break;
                }
            }

            if (bRtn == false)
            {   // 未だ、計算終了していないプロセスがある。
                Thread.Sleep(333);  // ループ内で休みなしに超高速で呼ばれないための保障
            }
            return bRtn;
        }


    }
}
