// <summary>ソースコード：モデル用プロパティスクリーンファクトリクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;


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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Viewer;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Controller;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreOptions.McViewer.DotNetViewer;

// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
namespace CommonMP.HYMCO.OptionImpl.TestModel
{
    /// <summary><para>class outline:</para>
    /// <para>モデル用プロパティス画面用 .net のフォーム</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/06/25][新規作成]</para>
    /// <para>remarks:</para>
    /// <para>必ず　McDotNetModelCellPropertyDetailBaseForm, McModelCellPropertyDetailFormIFから派生の事</para>
    /// </remarks>
    public partial class MyForecastModelDetailForm : McDotNetModelCellPropertyDetailBaseForm, McModelCellPropertyDetailFormIF
    {
        /// <summary>
        /// <para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>McMyModelDetailForm csPropertyDetailForm = new McMyModelDetailForm();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public MyForecastModelDetailForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// <para>method outline:</para>
        /// <para>プロパティ表示編集</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>EditParameter( );</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void EditParameter()
        {
            // まず、プロパティ情報から設定を行います。
            if (m_csPropertyInfo != null)
            {

                // ローカル変数を定義します。
                McModelPropertyInfo csModelPrptyInf = null;
                long lPropertyTypeNum = 0;
                HySString csKey = new HySString();
                HySString csPropertyName = new HySString();
                McDefine.ValKind lObjKind = new McDefine.ValKind();
                double dVal = new double();

                // 1) 登録プロパティ情報があれば処理を行います。
                csModelPrptyInf = m_csPropertyInfo as McModelPropertyInfo;
                if (csModelPrptyInf != null)
                {
                    // 2) 登録プロパティ情報数を取得して、情報数分処理を実行します。
                    lPropertyTypeNum = csModelPrptyInf.GetInfoTypeNum();
                    for (long lP = 1; lP <= lPropertyTypeNum; lP++)
                    {
                        // 3) プロパティ情報型式の取得例です。
                        if (csModelPrptyInf.GetInfoType(lP, ref csKey, ref csPropertyName, ref lObjKind) == true)
                        {
                            if (lObjKind == McDefine.ValKind.DOUBLE)
                            {   // 4) 実数型の場合は画面に値を初期表示させます。
                                if (csModelPrptyInf.GetInfo(csKey, ref dVal) == true)
                                {
                                    if (csKey.ToString() == "TIME_STEP")
                                    {
                                        // 5) タイムステップの場合は、所定のテキストボックスに表示する例です。
                                        TimeStepTextBox.Text = dVal.ToString();
                                        // ↑　配置した部品の名前です。
                                    }
                                    else if (csKey.ToString() == "m_dForeModelConst")
                                    {
                                        // 6) 未来計算型モデル定数の場合は、所定のテキストボックスに表示する例です。
                                        ModelConstTextBox.Text = dVal.ToString();
                                        // ↑　配置した部品の名前です。
                                    }
                                }
                            }
                            else
                            {
                                // その他の情報型の場合は何もしない例です。
                                continue;
                            }
                        }
                    }
                }
            }
            // 次に、初期化情報の設定を行います。
            if (m_csInitialInfo != null)
            {

                // ローカル変数を定義します。
                McInitialInfo csModelInitInf = null;
                long lInitialTypeNum = 0;
                HySString csKey = new HySString();
                HySString csInitialName = new HySString();
                McDefine.ValKind lObjKind = new McDefine.ValKind();
                double dVal = new double();

                // 7) 登録初期化情報があれば処理を行います。
                csModelInitInf = m_csInitialInfo as McInitialInfo;
                if (csModelInitInf != null)
                {
                    // 8) 登録初期化情報数を取得して、情報数分処理を実行します。
                    lInitialTypeNum = csModelInitInf.GetInfoTypeNum();
                    for (long lP = 1; lP <= lInitialTypeNum; lP++)
                    {
                        // 9) 初期化情報型式の取得例です。
                        if (csModelInitInf.GetInfoType(lP, ref csKey, ref csInitialName, ref lObjKind) == true)
                        {
                            if (lObjKind == McDefine.ValKind.DOUBLE)
                            {   // 10) 実数型の場合は画面に値を初期表示させます。
                                if (csModelInitInf.GetInfo(csKey, ref dVal) == true)
                                {
                                    if (csKey.ToString() == "Q_Initial")
                                    {
                                        // 11) 初期流量(出力情報)の場合は、所定のテキストボックスに表示する例です。
                                        QInitTextBox.Text = dVal.ToString();
                                        // ↑　配置した部品の名前です。
                                    }
                                    else if (csKey.ToString() == "Q_internal_Initial")
                                    {
                                        // 12) 初期流量(内部状態)の場合は、所定のテキストボックスに表示する例です。
                                        QInterInitTextBox.Text = dVal.ToString();
                                        // ↑　配置した部品の名前です。
                                    }
                                }
                            }
                            else
                            {
                                // その他の情報型の場合は何もしない例です。
                                continue;
                            }
                        }
                    }
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>ファイル入力処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>FileOpen_Click(sender,e);</para>
        /// </example>
        /// <param name="sender">Object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>「ファイル入力」ボタンを押下された時の処理を記述</para>
        /// </remarks>
        private void FileOpen_Click(object sender, EventArgs e)
        {
            if (m_csPropertyInfo != null || m_csInitialInfo != null)
            {  // プロパティ情報・初期設定情報があった場合は処理を行います。
                OpenFileDialog.FileName = "";
                OpenFileDialog.Filter = "ＣＳＶ ファイル (*.csv)|*.csv|すべてのファイル (*.*)|*.*";
                // 1) ファイルを開くためのダイアログボックスを表示します。
                if (OpenFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    FileName.Text = OpenFileDialog.FileName;        // プロパティ画面のファイル名称にテキスト表示を行います。
                    // ↓　ファイル入力処理の例です。
                    string csFileName = OpenFileDialog.FileName;    // ←　入力ファイルフルパス名です。
                    HySFile csFile = new HySFile((new HySString(csFileName)));
                    HySString sOut = new HySString();
                    string[] sInWk;

                    if (csFile.Exist() == true)
                    {  // 2) 既存ファイルが有れば処理を続行します。
                        if (csFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) == 0)
                        {   // 3) 既存CSVファイルを正常に開ければ処理を続行します。
                            while (csFile.ReadText(ref sOut) != 0)
                            {   // ↑１行取得する例です。本サンプルモデルでの1行取得例　⇒　([P],タイムステップ（秒）,30,TIME_STEP)
                                sInWk = sOut.ToString().Split(',');
                                // ↑　取得した行を','で4つに区切ります。
                                if (sInWk.LongLength == 4)
                                {   // 4) パラメータ情報項目数と一致した場合は処理を続行します。
                                    if (sInWk[0] != "#")
                                    {   // 5) コメント行以外の場合は処理を続行します。
                                        if (sInWk[0] == "[P]")
                                        {   // 6) プロパティ情報を入力します。
                                            if (sInWk[3] == "TIME_STEP")
                                            {
                                                // タイムステップの場合です。
                                                TimeStepTextBox.Text = sInWk[2];
                                            }
                                            else if (sInWk[3] == "m_dForeModelConst")
                                            {
                                                // 未来計算型モデル定数の場合です。
                                                ModelConstTextBox.Text = sInWk[2];
                                            }
                                        }
                                        else if (sInWk[0] == "[I]")
                                        {   // 7) 初期設定情報を入力します。
                                            if (sInWk[3] == "Q_Initial")
                                            {
                                                // 初期流量（出力情報）の場合です。
                                                QInitTextBox.Text = sInWk[2];
                                            }
                                            else if (sInWk[3] == "Q_internal_Initial")
                                            {
                                                // 初期流量（内部状態）の場合です。
                                                QInterInitTextBox.Text = sInWk[2];
                                            }
                                        }
                                    }
                                }
                            }
                            // 8) 開いていたファイルを閉じます。
                            csFile.Close();
                        }
                    }
                }
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>ファイル出力処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>FileSave_Click(sender,e);</para>
        /// </example>
        /// <param name="sender">Object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>「ファイル出力」ボタンを押下された時の処理を記述</para>
        /// </remarks>
        private void FileSave_Click(object sender, EventArgs e)
        {
            McModelPropertyInfo csModelPrptyInf = null;
            McInitialInfo csModelInitInf = null;
            // 1) 出力する前に、入力された項目をチェックします。
            if (ParaSet_Check() == true)
            {
                return;
            }

            if (m_csPropertyInfo != null || m_csInitialInfo != null)
            {  // プロパティ情報・初期設定情報があった場合は処理を行います。
                SaveFileDialog.FileName = FileName.Text;
                SaveFileDialog.Filter = "ＣＳＶ ファイル (*.csv)|*.csv|すべてのファイル (*.*)|*.*";
                // 2) ファイルを保存するためのダイアログボックスを表示します。
                if (SaveFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    FileName.Text = SaveFileDialog.FileName;            // プロパティ画面のファイル名称にテキスト表示を行います。

                    string csFileName = SaveFileDialog.FileName;    // ←　出力ファイルフルパス名です。
                    // ↓　ファイル出力処理の例です。
                    HySFile csFile = new HySFile((new HySString(csFileName)));
                    HySString sOut = new HySString();

                    if (csFile.Open(HySFile.OPEN_MODE.CREATE_NEW, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.MK_DIR) == 0)
                    {   // 4) CSVファイルが生成できたら処理を続行します。
                        HySString csKey = new HySString();
                        HySString csPropertyName = new HySString();
                        HySString csInitialName = new HySString();
                        McDefine.ValKind lObjKind = new McDefine.ValKind();
                        long lInitialTypeNum = 0;
                        long lPropertyTypeNum = 0;
                        double dVal = new double();

                        csModelPrptyInf = m_csPropertyInfo as McModelPropertyInfo;

                        // 5) プロパティ情報を出力します。
                        if (csModelPrptyInf != null)
                        {
                            lPropertyTypeNum = csModelPrptyInf.GetInfoTypeNum();
                            for (long lP = 1; lP <= lPropertyTypeNum; lP++)
                            {
                                // プロパティ情報型式の取得を行う例です。
                                if (csModelPrptyInf.GetInfoType(lP, ref csKey, ref csPropertyName, ref lObjKind) == true)
                                {
                                    if (lObjKind == McDefine.ValKind.DOUBLE)
                                    {   // 実数型の場合は処理を行います。
                                        if (csKey.ToString() == "TIME_STEP")
                                        {
                                            // タイムステップの場合です。
                                            dVal = double.Parse(TimeStepTextBox.Text);
                                            sOut = new HySString("[P]" + "," + csPropertyName.ToString() + "," + dVal.ToString() + "," + csKey.ToString());
                                        }
                                        else if (csKey.ToString() == "m_dForeModelConst")
                                        {
                                            // 未来計算型モデル定数の場合です。
                                            dVal = double.Parse(ModelConstTextBox.Text);
                                            sOut = new HySString("[P]" + "," + csPropertyName.ToString() + "," + dVal.ToString() + "," + csKey.ToString());
                                        }
                                    }
                                    if (sOut.GetLength() > 0)
                                    {
                                        csFile.WriteText(sOut);                 // ←　プロパティ情報出力を行います。
                                    }
                                }
                            }
                        }
                        // 6) 初期化情報を出力します。
                        if (m_csInitialInfo != null)
                        {
                            csModelInitInf = m_csInitialInfo as McInitialInfo;

                            if (csModelInitInf != null)
                            {
                                lInitialTypeNum = csModelInitInf.GetInfoTypeNum();
                                for (long lP = 1; lP <= lInitialTypeNum; lP++)
                                {
                                    // プロパティ情報型式の取得
                                    if (csModelInitInf.GetInfoType(lP, ref csKey, ref csPropertyName, ref lObjKind) == true)
                                    {
                                        if (lObjKind == McDefine.ValKind.DOUBLE)
                                        {   // 実数型の場合
                                            if (csKey.ToString() == "Q_Initial")
                                            {
                                                // 初期流量（出力情報）の場合です。
                                                dVal = double.Parse(QInitTextBox.Text);
                                                sOut = new HySString("[I]" + "," + csPropertyName.ToString() + "," + dVal.ToString() + "," + csKey.ToString());
                                            }
                                            else if (csKey.ToString() == "Q_internal_Initial")
                                            {
                                                // 初期流量（内部状態）の場合です。
                                                dVal = double.Parse(QInterInitTextBox.Text);
                                                sOut = new HySString("[I]" + "," + csPropertyName.ToString() + "," + dVal.ToString() + "," + csKey.ToString());
                                            }
                                        }
                                        if (sOut.GetLength() > 0)
                                        {
                                            csFile.WriteText(sOut);                 // ←　プロパティ情報出力を行います。
                                        }
                                    }
                                }
                            }
                        }
                        csFile.Close();
                    }
                }
            }
        }
        /// <summary>
        /// <para>method outline:</para>
        /// <para>設定内容チェック処理</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>ParaSet_Check();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>false : 正常、true : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool ParaSet_Check()
        {
            double dVal;
            bool bBreakfg = false;

            // 1) まず、プロパティ情報からチェックを行います。
            if (m_csPropertyInfo != null)
            {
                try
                {
                  dVal = double.Parse(TimeStepTextBox.Text);
                  // テキストボックスの背景色を戻す例です。
                  TimeStepTextBox.BackColor = Color.Empty;
                }
                catch
                {
                    // 入力異常を検知すると、ここに処理が移ります。
                    // テキストボックスの背景色を赤色にする例です。
                    TimeStepTextBox.BackColor = Color.Red;
                    bBreakfg = true;// ←　設定内容に異常があることを示します。
                }
                try
                {
                    dVal = double.Parse(ModelConstTextBox.Text);
                    // テキストボックスの背景色を戻す例です。
                    ModelConstTextBox.BackColor = Color.Empty;
                }
                catch
                {
                    // 入力異常を検知すると、ここに処理が移ります。
                    // テキストボックスの背景色を赤色にする例です。
                    ModelConstTextBox.BackColor = Color.Red;
                    bBreakfg = true;// ←　設定内容に異常があることを示します。
                }
            }
            // 2) 次に、初期化情報のチェックを行います。
            if (m_csInitialInfo != null)
            {
                try
                {
                    dVal = double.Parse(QInitTextBox.Text);
                    // テキストボックスの背景色を戻す例です。
                    QInitTextBox.BackColor = Color.Empty;
                }
                catch
                {
                    // 入力異常を検知すると、ここに処理が移ります。
                    // テキストボックスの背景色を赤色にする例です。
                    QInitTextBox.BackColor = Color.Red;
                    bBreakfg = true;// ←　設定内容に異常があることを示します。
                }
                try
                {
                    dVal = double.Parse(QInterInitTextBox.Text);
                    // テキストボックスの背景色を戻す例です。
                    QInterInitTextBox.BackColor = Color.Empty;
                }
                catch
                {
                    // 入力異常を検知すると、ここに処理が移ります。
                    // テキストボックスの背景色を赤色にする例です。
                    QInterInitTextBox.BackColor = Color.Red;
                    bBreakfg = true;// ←　設定内容に異常があることを示します。
                }
            }
            return bBreakfg;
        }

        /// <summary>
        /// <para>method outline:</para>
        /// <para>設定内容登録処理</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>ParaRegist();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>false : 変更無し、true : 変更有り</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool ParaRegist()
        {
            double dOrgVal = new double();
            double dNewVal;
            bool bModifyFlg = false;

            // 1) まず、プロパティ情報から登録を行います。
            if (m_csPropertyInfo != null)
            {
                // 実数型に変換を行う例です。
                dNewVal = double.Parse(TimeStepTextBox.Text);
                ((McModelPropertyInfo)m_csPropertyInfo).GetInfo("TIME_STEP", ref dOrgVal);
                if (dNewVal != dOrgVal)
                {
                    // 2) すでに設定されている値と異なる場合は、変更します。
                    ((McModelPropertyInfo)m_csPropertyInfo).SetInfo("TIME_STEP", dNewVal);
                    bModifyFlg = true; // ←変更ありとします。
                }
                // 実数型に変換を行う例です。
                dNewVal = double.Parse(ModelConstTextBox.Text);
                ((McModelPropertyInfo)m_csPropertyInfo).GetInfo("m_dForeModelConst", ref dOrgVal);
                if (dNewVal != dOrgVal)
                {
                    // 3) すでに設定されている値と異なる場合は、変更します。
                    ((McModelPropertyInfo)m_csPropertyInfo).SetInfo("m_dForeModelConst", dNewVal);
                    bModifyFlg = true; // ←変更ありとします。
                }
            }
            // 4) 次に、初期化情報の登録を行います。
            if (m_csInitialInfo != null)
            {
                // 実数型に変換を行う例です。
                dNewVal = double.Parse(QInitTextBox.Text);
                ((McInitialInfo)m_csInitialInfo).GetInfo("Q_Initial", ref dOrgVal);
                if (dNewVal != dOrgVal)
                {
                    // 5) すでに設定されている値と異なる場合は、変更します。
                    ((McInitialInfo)m_csInitialInfo).SetInfo("Q_Initial", dNewVal);
                    bModifyFlg = true; // ←変更ありとします。
                }
                // 実数型に変換を行う例です。
                dNewVal = double.Parse(QInterInitTextBox.Text);
                ((McInitialInfo)m_csInitialInfo).GetInfo("Q_internal_Initial", ref dOrgVal);
                if (dNewVal != dOrgVal)
                {
                    // 6) すでに設定されている値と異なる場合は、変更します。
                    ((McInitialInfo)m_csInitialInfo).SetInfo("Q_internal_Initial", dNewVal);
                    bModifyFlg = true; // ←変更ありとします。
                }
            }
            return bModifyFlg;
        }

        /// <summary><para>method outline:</para>
        /// <para>設定処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ParaSet_Click(sender,e);</para>
        /// </example>
        /// <param name="sender">object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>「設定」ボタンを押下された時の処理を記述</para>
        /// </remarks>
        private void ParaSet_Click(object sender, EventArgs e)
        {
            if (ParaSet_Check() == true)
            {
                // 1) 入力された項目に異常がある場合は何もしません。
                return;
            }

            if (ParaRegist() == true)
            {
                // 2) 設定内容登録処理にて、値が変更された場合は、OK状態にします。
                DialogResult = DialogResult.OK;
            }
            else
            {
                // 3) 設定内容登録処理にて、値が変更されていない場合は、キャンセル状態に設定します。
                DialogResult = DialogResult.Cancel;
            }
            // 4) 画面を閉じます。
            Close();
        }
        /// <summary><para>method outline:</para>
        /// <para>キャンセル処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Cancel_Click(sender,e);</para>
        /// </example>
        /// <param name="sender">Object</param>
        /// <param name="e">Event</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>「キャンセル」ボタンを押下された時の処理を記述</para>
        /// </remarks>
        private void Cancel_Click(object sender, EventArgs e)
        {
            // 1) キャンセル状態に設定します。
            DialogResult = DialogResult.Cancel;
            // 2) 画面を閉じます。
            Close();
        }
    }
}