// <summary>ソースコード：各種実行体の起動制御</summary>
// <author>CommonMP</author>

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

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

namespace CommonMP.HYSSOP.CoreImpl.HSTools.HSExecutor
{
    /// <summary><para>class outline:</para>
    /// <para>CommonMP関係各種プロセス起動制御</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.2.0][2011/12/08][新規作成]</para>
    /// </remarks>
    public class HySExcecutor
    {
        /// <summary>起動スートクラスの管理リスト </summary>
        protected HySDataLinkedList m_csSuiteList = new HySDataLinkedList();

        /// <summary><para>method outline:</para>
        /// <para>起動スートの生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>MakeSuiteList( sArgs )</para>
        /// </example>
        /// <param name="sArgs">HySExcecutor起動時のパラメーター</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void MakeSuiteList(string[] sArgs)
        {
            try
            {
                if (sArgs.Length > 0)
                {
                    if (sArgs[0] == "-p")
                    {   // 単独起動ならば
                        if (sArgs.Length > 1)
                        {
                            string sAfterExeName = "";
                            string sExeName = sArgs[1];
                            string sParam = "";
                            for (int i = 2; i <= sArgs.Length; i++)
                            {
                                sParam += sArgs[i - 1];
                            }
                            HySExecSuite csSuiteData = new HySExecSuite(true, sAfterExeName, sExeName, sParam);
                            m_csSuiteList.AddLast(csSuiteData);
                        }
                    }
                    else if (sArgs[0] == "-c")
                    {   // シーケンシャル起動ならば
                        // sArgs[1]で指定されたファイルを読み出して、起動シーケンスを作成する
                        if (sArgs.Length > 1)
                        {
                            HySString csXmlFile = new HySString(sArgs[1]);
                            HySFile csFile = new HySFile(csXmlFile);
                            if (csFile.Exist() == true)
                            {
                                this.ReadXML(csXmlFile);// 設定ファイルを読み込む

                                csFile.Delete();// 後始末
                            }
                        }
                        else
                        {
                            // Do Nothing
                        }
                    }
                }
                else
                {
                    sArgs = new string[2];
                    sArgs[0] = "-c";
                    sArgs[1] = "..\\temp\\exit.xml";  // デフォルトファイル名を入れる

                    this.MakeSuiteList(sArgs);
                }
            }
            catch
            {
                // DoNothig
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>起動スートに従って、順にプログラムを起動する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Work(  )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void Work()
        {
            HySExecSuite csSuiteData=null;
            bool bLclRtn = false;
            long lSuiteNo = m_csSuiteList.GetCount();   // 起動スート数
            m_csSuiteList.SetCursorFirst();
            for (long lLp = 0; lLp < lSuiteNo; lLp++)
            {
                csSuiteData = m_csSuiteList.GetCursorData() as HySExecSuite;    // 起動スートを順に読み出す
                if (csSuiteData != null)
                {   // スートがあれば
                    bLclRtn=this.ExecuteProc(csSuiteData);  // プログラム起動
                }
                m_csSuiteList.MoveCursorNext();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>プログラム起動</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ExecuteProc( sArgs )</para>
        /// </example>
        /// <param name="csSuiteData">起動スート（１レコード分）</param>
        /// <returns>Boolean:起動戻り値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean ExecuteProc(HySExecSuite csSuiteData)
        {
            // 初期起動遅延時間分待つ
            int lDelayTime = (int)csSuiteData.GetDelayTime();
            System.Threading.Thread.Sleep(lDelayTime);


            bool bWaitFlg=csSuiteData.GetWaitFlg();
            string sAfterExeName=csSuiteData.GetAfterPrcName();
            string sExeName=csSuiteData.GetProcName();
            string sParam=csSuiteData.GetProcParam();
                        
            // 起動終了を待つ処理があれば　前処理の終了を待つ
            if (bWaitFlg == true)
            {
                System.Diagnostics.Process[] p;
                int iCnt = 0;
                for (iCnt = 0; iCnt < 100; iCnt++)
                {
                    // プロセス取得
                    p = System.Diagnostics.Process.GetProcessesByName(sAfterExeName);
                    int iPNo = p.Length;
                    if (iPNo < 1)
                    {   // 取得したプロセスは居ない
                        break;
                    }
                    System.Threading.Thread.Sleep(250);
                }
                if (iCnt > 98)
                {   // タイムアウト
                    return false;
                }
            }
            
            // プロセス起動
            Process process = new Process();
            process.StartInfo.RedirectStandardOutput = true;  // コンソールを開かなくする
            process.StartInfo.CreateNoWindow = true; // コンソール・ウィンドウを開かない
            process.StartInfo.UseShellExecute = false; // シェル機能を使用しない （必須）

            process.StartInfo.FileName = sExeName;
            process.StartInfo.Arguments = sParam;

            return process.Start();
        }
        /// <summary><para>method outline:</para>
        /// <para>起動スート１レコード追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AddExecSuite( csSuiteData )</para>
        /// </example>
        /// <param name="csSuiteData">起動スート（１レコード分）</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void AddExecSuite(HySExecSuite csSuiteData)
        {
            m_csSuiteList.AddLast(csSuiteData);
        }

        /// <summary><para>method outline:</para>
        /// <para>XMLファイル出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = WriteXML( csXmlFileNameWithPath )</para>
        /// </example>
        /// <param name="csXmlFileNameWithPath">書き出しXMLファイル</param>
        /// <returns>true:正常 false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool WriteXML(HySString csXmlFileNameWithPath)
        {
            try
            {
                // ファイル本体　.XML
                HySXmlWriter csXmlWriter = new HySXmlWriter(csXmlFileNameWithPath);

                HySXmlNode csRootNode = csXmlWriter.CreateRoot("HySExcecuteList");

                HySExecSuite csSuiteData = null;
                HySXmlNode csNode = null;

                // XmlWriterによる処理 -->
                long lSuiteNo = m_csSuiteList.GetCount();
                m_csSuiteList.SetCursorFirst();
                for (long lLp = 0; lLp < lSuiteNo; lLp++)
                {
                    csSuiteData = m_csSuiteList.GetCursorData() as HySExecSuite;
                    if (csSuiteData != null)
                    {
                        csNode = csSuiteData.WriteXML(ref csXmlWriter, lLp);
                        if (csNode != null)
                        {
                            csRootNode.AppendChild(csNode);
                        }
                    }
                    m_csSuiteList.MoveCursorNext();
                }

                csXmlWriter.Save();
                return true;
            }
            catch
            {
                return false;
            }
        }
       
        /// <summary><para>method outline:</para>
        /// <para>XMLファイル入力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lCnt = ReadXML( csXmlFileNameWithPath )</para>
        /// </example>
        /// <param name="csXmlFileNameWithPath">読み込みXMLファイル</param>
        /// <returns>スート数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long ReadXML(HySString csXmlFileNameWithPath)
        {
            try
            {
                m_csSuiteList.Clear(); // ｸﾘｱ

                HySXmlReader csXmlReader = new HySXmlReader(csXmlFileNameWithPath);

                HySXmlNode csRootNode = csXmlReader.GetRootNode();

                HySXmlNode csXmlCompNode;
                HySXmlNodeList csXmlComponentList = csRootNode.GetChildNodeListByTagName("HySExecSuite");
                long lCompNum = csXmlComponentList.GetCount();

                // スート数分の格納エリア確保
                HySExecSuite[] csSuiteElm = new HySExecSuite[lCompNum];


                HySExecSuite csSuite;
                long lOrderNo = -1;
                // XMLの起動スートを復元
                for (long lLp = 0; lLp < lCompNum; lLp++)
                {
                    csXmlCompNode = csXmlComponentList.GetNode(lLp);
                    csSuite = new HySExecSuite();
                    lOrderNo = csSuite.ReadXML(csXmlCompNode);
                    if (lOrderNo != -1)
                    {
                        csSuiteElm[lOrderNo] = csSuite;
                    }
                }
                // 起動番号順に従って、追加
                for (long lLp = 0; lLp < lCompNum; lLp++)
                {
                    if (csSuiteElm[lLp] != null)
                    {
                        m_csSuiteList.AddLast(csSuiteElm[lLp]);
                    }
                }
                return m_csSuiteList.GetCount();
            }
            catch
            {
                return -1;
            }
        }
    }
}
