// <summary>ソースコード：ＨＹＭＣＯ演算モデルクラス型紙</summary>
// <author>CommonMP</author>

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

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
namespace CommonMP.HYMCO.OptionImpl.McSampleModelForDeveloper  
{
    /// <summary><para>class outline:</para>
    /// <para>演算モデル型紙</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.1.0][2010/12/22][新規作成]</para>
    /// </remarks>
    public class McGISTest2DMeshDataGenerateModel : McForecastModelBase
    {
        /// <summary> 演算データ（キャスト用） </summary>
        McGISTest2DMeshDataGenerateInfo m_csTestGISInf = null;   // 便利の為、キャスト用に定義しておく

        //=========================
        // 演算実行前処理関連メソッド
        //=========================


        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            if (lInputDataNum > 0)
            {
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckWarningData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND,
                     Properties.Resources.STATEMENT_INPUT_NO_MEAN);
               // csErrorInf.AddCheckWarningData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND, "入力は意味を持ちません。");
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。

                // To Do
                // 出力する伝送データの型式や設定値等をチェックし、一つでも期待情報でなければ、bRtn=false; を設定します。
                HySObjectKind csCellType = csOutputCellData[lLp].GetTranInfoKind();
                if (McTranInfoDefine.D2_GIS_MESH_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    long lDimNum = 0;// データの次元数
                    long m_lDimLat = 0;// 配列数：緯度
                    long m_lDimLon = 0;// 配列数：経度
                    long m_lDimAlt = 0;// 配列数：高度
                    HySGeoMesh.MESH_DATA_KIND m_lKind = HySGeoMesh.MESH_DATA_KIND.DOUBLE_DATA_HOLD;// GISデータ種別
                    long m_lDataDimInCell=0;// セル内の変数の数
                    // メッシュの配列数取得
                    lDimNum = csOutputCellData[lLp].GetGISMeshDimension(ref m_lKind, ref m_lDimLon, ref m_lDimLat, ref m_lDimAlt, ref m_lDataDimInCell);
                    if( m_csTestGISInf.m_lLatDim != m_lDimLat)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND, 
                            Properties.Resources.STATEMENT_DIFF_DIM_LAT );
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND, "接続データの配列（緯度方向）が異なっています");
                        bRtn = false;
                    }
                    if (m_csTestGISInf.m_lLonDim != m_lDimLon)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND,
                            Properties.Resources.STATEMENT_DIFF_DIM_LON );
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelSampleDefine.TEST_GIS_OUT_TESTMODEL_KIND, "接続データの配列（経度方向）が異なっています");
                        bRtn = false;
                    }
                    // メッシュの４隅の緯度、経度を設定する
                    csOutputCellData[lLp].SetLocation(m_csTestGISInf.dRcvSWLat, m_csTestGISInf.dRcvSWLon, m_csTestGISInf.dRcvNELat, m_csTestGISInf.dRcvNELon);

                }
                else
                {
                    bRtn = false;
                }

            }
            return bRtn;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = false;
            // 引数で与えられたデータを　キャストしています。
            McInitialInfo csInDt = csInitialData as McInitialInfo;

            if (csInDt != null)
            {
                bRtn = true;
                // To Do
                // 演算データ等で初期化が必要な情報に対して、引数で与えられた初期化情報の内容を読み取って、設定します。

                Random rnd = new Random();
                
                long lPCnt = (long)DateTime.Now.Second;
                for (long lLp = 0; lLp<lPCnt; lLp++)
                {
                    rnd.Next(1, 100);
                }
                McGISTest2DMeshDataGenerateInfo.dSlp = 0.5 + 0.5 * (double)rnd.Next(1, 100) / 100.0;
            }
            return bRtn;
        }

        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "McGISTest2DMeshDataGenerateModel", "Calculate", "in");
            
            // To Do
            // 演算処理を行います。

            //McLog.DebugOut(GetSimulationTime(), GetID(), "McGISTest2DMeshDataGenerateModel", "Calculate", "out");
            return 0;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "McGISTest2DMeshDataGenerateModel", "DataFusion", "in");
         
            
            m_csTestGISInf.dTtlCnt += 1.0;
            McGISTest2DMeshDataGenerateInfo.lCnt += 1;
            //HySCellData[] csSndCellData = null;
            HySCellData[,] csSndCellData2 = null;
            //long[,]  lGISPttnD2 = null;

            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。

                // To Do
                // 出力する伝送データの型式や設定値等をチェックし、それに合わせて、伝送データに出力値を設定します。
                //m_csOutputData[lLp]
                HySObjectKind csCellType = csOutputCellData[lLp].GetTranInfoKind(); // 伝送データ種別の取得例
                McTranInfo csTrnInf = csOutputCellData[lLp].GetTranInfo();  // 伝送データ本体の取得例

                if (McTranInfoDefine.D2_GIS_MESH_SERIAL.Equals(csOutputCellData[lLp].GetTranInfoKind()) == true)
                {
                    csSndCellData2 = csOutputCellData[lLp].PrepareSendCellD2();

                    //csOutputCellData[lLp].SetLocation(35.5 - 0.01, 138.0 - 0.01, 35.5 + 0.11, 138.0 + 0.12);

                    Random rnd = new Random();
                    double[] v = { rnd.Next(0, 20), rnd.Next(10, 90), rnd.Next(10, 90) };
                    for (long lLon = 0; lLon < m_csTestGISInf.m_lLonDim; lLon++)
                    {
                        for (long lLat = 0; lLat < m_csTestGISInf.m_lLatDim; lLat++)
                        {
                            // 流量
                            csSndCellData2[lLon, lLat].m_dData[0] = v[1] + rnd.Next(1, 20);
                            // 水位
                            csSndCellData2[lLon, lLat].m_dData[1] = 1.0 * (1.0 + Math.Cos(3.14 * (double)(McGISTest2DMeshDataGenerateInfo.lCnt * 30) / 180.0 + 3.14 * McGISTest2DMeshDataGenerateInfo.dSlp * (double)(lLat * 2 + lLon * 4) / 180.0) );
                            // 雨量
                            csSndCellData2[lLon, lLat].m_dData[2] = 40.0 * (1.0 + Math.Cos(3.14 * (double)(McGISTest2DMeshDataGenerateInfo.lCnt * 30) / 180.0 + 3.14 * McGISTest2DMeshDataGenerateInfo.dSlp * (double)(lLon * 2 + lLat * 4) / 180.0));
                        }
                    }

                    //lGISPttnD2 = csOutputCellData[lLp].PrepareSendGISPatternD2();
                }

            }

            //McLog.DebugOut(GetSimulationTime(), GetID(), "McGISTest2DMeshDataGenerateModel", "DataFusion", "out");
            return 0;
        }


        //====================
        // その他必要なメソッド
        //====================

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            // 使用しやすいようにキャストしておく
            m_csTestGISInf = (McGISTest2DMeshDataGenerateInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());

                bRtn = true;

                csPrptyInfo.GetInfo("m_lLatDim", ref m_csTestGISInf.m_lLatDim);
                csPrptyInfo.GetInfo("m_lLonDim", ref m_csTestGISInf.m_lLonDim);
                double dLatCenter = 0.0; csPrptyInfo.GetInfo("dLatCenter", ref dLatCenter);
                double dLonCenter = 0.0; csPrptyInfo.GetInfo("dLonCenter", ref dLonCenter);
                double dLatWidth = 0.0; csPrptyInfo.GetInfo("dLatWidth", ref dLatWidth);
                double dLonWidth = 0.0; csPrptyInfo.GetInfo("dLonWidth", ref dLonWidth);

                m_csTestGISInf.dRcvSWLat = dLatCenter - dLatWidth;
                m_csTestGISInf.dRcvSWLon = dLonCenter - dLonWidth;
                m_csTestGISInf.dRcvNELat = dLatCenter + dLatWidth;
                m_csTestGISInf.dRcvNELon = dLonCenter + dLonWidth;
                // To Do
                // モデルの係数等、必要な情報に対して、引数で与えられたプロパティ情報の内容を読み取って、設定します。
            }
            return bRtn;
        }
    }
    //
}
