// <summary>ソースコード：ＨＹＳＳＯＰ２次元地理メッシュ情報 データクラス<</summary>
// <author>CommonMP</author>

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

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
//using CommonMP.HYSSOP.CoreImpl.HSData.CommonData;

namespace CommonMP.HYSSOP.CoreImpl.HSData
{
    /// <summary><para>class outline:</para>
    /// <para>２次元地理メッシュ情報 データクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// <para>remarks:</para>
    /// <para>２次元メッシュ状の地理空間上に　１次元配列情報を保持できる（但し直交座標）</para>
    /// <para>Remarks</para>
    /// <para>HySGeometryから引き継いだ属性としては m_csID,m_eAltMode,m_bExtrudeMode,m_bTessellateModeが有効</para>
    /// </remarks>
    [Serializable]
    public class HySGeoDim2MeshData : HySGeoMesh //, HySTimeRecordIF
    {
        ///// <summary>配列データ本体  m_lMeshKind = DOUBLE_DATA_HOLD or BOTH_DATA_HOLD の場合に有効</summary>
        //protected HySD2CellArrayData m_csCellDataDim = null;

        /// <summary>パターン番号保持データ（m_csPatternInf[]の０相対配列番号を保持）m_lMeshKind = PATTARN_DATA_HOLD or BOTH_DATA_HOLD の場合に有効</summary>
        protected long[,] m_lPatternNo = null;
        /// <summary>標高（m単位）m_lMeshKind = PATTARN_DATA_HOLD の場合に有効</summary>
        public double m_dDispAltitude = 0.0;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>  使用禁止 </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>使用禁止</para>
        /// </remarks>
        private HySGeoDim2MeshData()
        {
            //バージョン情報設定
            SetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoMesh csData = new HySGeoDim2MeshData(lKind,lLonDim,lLatDim,lCellDataDim); </para>
        /// </example>
        /// <param name="lKind">保持するデータの形</param>
        /// <param name="lLonDim">経度方向のメッシュ分割数</param>
        /// <param name="lLatDim">緯度方向のメッシュ分割数</param>
        /// <param name="lCellDataDim">１メッシュ内のデータ配列数</param>
        /// <returns> HySGeoDim2MeshData 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySGeoDim2MeshData(HySGeoMesh.MESH_DATA_KIND lKind, long lLonDim, long lLatDim, long lCellDataDim) 
            :base(lKind, lLonDim, lLatDim, 1)
        {
            /*
            if (lKind != MESH_DATA_KIND.PATTARN_DATA_HOLD)
            {
                m_csCellArray = new HySD2CellArrayData(lLonDim, lLatDim, lCellDataDim);
            }
            if (lKind != MESH_DATA_KIND.DOUBLE_DATA_HOLD)
            {
                m_lPatternNo = new long[lLonDim,lLatDim ];
            }
            */
            this.Init(lKind, lLonDim, lLatDim, lCellDataDim, true);
            //バージョン情報設定
            SetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>内部処理用コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoDim2MeshData csData = new HySGeoDim2MeshData(lKind,lLonDim,lLatDim,false); </para>
        /// </example>
        /// <param name="lKind">保持するデータの形</param>
        /// <param name="lLonDim">経度方向のメッシュ分割数</param>
        /// <param name="lLatDim">緯度方向のメッシュ分割数</param>
        /// <param name="lCellDataDim">１メッシュ内のデータ配列数</param>
        /// <param name="bSW">常にfalse</param>
        /// <returns> HySGeoDim2MeshData 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>内部処理用：
        ///   時系列情報として情報を設定するとき　各レコード間に共通な情報を
        /// 　内部に冗長な情報として持たないように、共通情報の生成を止めて生成する
        /// </para>
        /// </remarks>
        internal HySGeoDim2MeshData(HySGeoMesh.MESH_DATA_KIND lKind, long lLonDim, long lLatDim, long lCellDataDim,bool bSW)
            : base(lKind, lLonDim, lLatDim, 1)
        {
            /*
            if (lKind != MESH_DATA_KIND.PATTARN_DATA_HOLD)
            {
                m_csCellArray = new HySD2CellArrayData(lLonDim, lLatDim, lCellDataDim,false);
            }
            if (lKind != MESH_DATA_KIND.DOUBLE_DATA_HOLD)
            {
                m_lPatternNo = new long[lLonDim, lLatDim];
            }
            */
            this.Init(lKind, lLonDim, lLatDim, lCellDataDim, false);
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ（Ｋｍｌ用）</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoDim2MeshData csData = new HySGeoDim2MeshData(csKmlFile); </para>
        /// </example>
        /// <param name="csKmlFile">ファイル名（フルパス）</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySGeoDim2MeshData(HySString csKmlFile)
        {
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>初期化処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Init(lKind, lLatDim, lLonDim) </para>
        /// </example>
        /// <param name="lKind">保持するデータの形</param>
        /// <param name="lLonDim">経度方向のメッシュ分割数</param>
        /// <param name="lLatDim">緯度方向のメッシュ分割数</param>
        /// <param name="lCellDataDim">１メッシュ内のデータ配列数</param>
        /// <param name="bSW">レコードフラグ：</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>コンストラクターから呼ばれる</para>
        /// </remarks>
        protected virtual void Init(MESH_DATA_KIND lKind, long lLonDim, long lLatDim, long lCellDataDim, bool bSW)
        {
            if (lKind != MESH_DATA_KIND.PATTARN_DATA_HOLD)
            {
                if (bSW == true)
                {
                    m_csCellArray = new HySD2CellArrayData(lLonDim, lLatDim, lCellDataDim);
                }
                else
                {
                    m_csCellArray = new HySD2CellArrayData(lLonDim, lLatDim, lCellDataDim, false);
                }
            }
            if (lKind != MESH_DATA_KIND.DOUBLE_DATA_HOLD)
            {
                m_lPatternNo = new long[lLonDim, lLatDim];
            }
            base.Init(lKind, lLonDim, lLatDim, 1);
        }
        /// <summary><para>method outline:</para>
        /// <para>コピーコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoMesh csData = new HySGeoDim2MeshData(lKind,lLatDim,lLonDim); </para>
        /// </example>
        /// <param name="csOrgData">コピー元データ</param>
        /// <returns> HySGeoDim2MeshData 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySGeoDim2MeshData(HySGeoDim2MeshData csOrgData)
            : base(csOrgData.m_lMeshKind, csOrgData.m_lLonDim, csOrgData.m_lLatDim, csOrgData.m_lAltDim)
        {
            this.CopyData(csOrgData);
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>メッシュ情報インスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySCellData[,] csData = GetMeshData();</para>
        /// <para>csData[経度No,経度No] = x;</para>
        /// <para>y = csData[緯度No,経度No];</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>２次元セルデータ配列インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>配列のインデックスは０相対</para>
        /// </remarks>
        public HySCellData[,] GetMeshData()
        {
            if (m_csCellArray != null)
            {
                return ((HySD2CellArrayData)m_csCellArray).GetCellData();
            }
            else
            {
                return null;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>パターンメッシュ情報インスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long[,] lPtnNo = GetPatternMeshData()</para> 
        /// <para>lPtnNo[i,j] = x;</para>
        /// <para>y = lPtnNo[a,b];</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long[緯度配列,経度配列] ２次元パターンメッシュインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long[,] GetPatternMeshData()
        {
            return m_lPatternNo;
        }

        /// <summary><para>method outline:</para>
        /// <para>パターン表示時の高度設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetPatternDispAlt(dAlt); </para>
        /// </example>
        /// <param name="dAlt">パターン表示高度</param>
        /// <returns> 無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>３次元地図に　メッシュをパターン表示する際　その表示高度を設定する</para>
        /// <para>２次元地図の場合には　無効</para>
        /// </remarks>
        public void SetPatternDispAlt(double dAlt)
        {
            m_dDispAltitude = dAlt;
        }
        /// <summary><para>method outline:</para>
        /// <para>パターン表示時の高度取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetPatternDispAlt(); </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>パターン表示高度</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>３次元地図に　メッシュをパターン表示する際　その表示高度を取得する</para>
        /// <para>２次元地図の場合には不要</para>
        /// </remarks>
        public double GetPatternDispAlt()
        { return m_dDispAltitude; }

        /// <summary><para>method outline:</para>
        /// <para>引数で与えられたデータを自分にコピーする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> CopyData(csOrgData) </para>
        /// </example>
        /// <param name="csOrgData">コピー元情報</param>
        /// <returns> 無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void CopyData(HySGeoMesh csOrgData)
        {
            HySGeoDim2MeshData csOrgMeshData = csOrgData as HySGeoDim2MeshData;
            if (csOrgMeshData != null)
            {
                base.CopyData(csOrgMeshData);

                m_dDispAltitude = csOrgMeshData.m_dDispAltitude;
                if (csOrgMeshData.m_csCellArray != null)
                {
                    m_csCellArray = new HySD2CellArrayData((HySD2CellArrayData)csOrgMeshData.m_csCellArray);
                }
                if (csOrgMeshData.m_lPatternNo != null)
                {
                    m_lPatternNo = new long[m_lLonDim, m_lLatDim];
                    for (long lLp = 0; lLp < m_lLatDim; lLp++)
                    {
                        for (long lLp2 = 0; lLp2 < m_lLonDim; lLp2++)
                        {
                            m_lPatternNo[lLp2, lLp] = csOrgMeshData.m_lPatternNo[lLp2, lLp];
                        }
                    }
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>単独データメッシュ情報生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoMesh csMeshData = CreateSingleDataMesh(lDataIndex) </para>
        /// </example>
        /// <param name="lDataIndex">セル内データIndex(0相対)</param>
        /// <returns> HySGeoMesh 単独データメッシュ情報　</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>指定されたインデックスのセル内部データのみを持つメッシュ情報データを生成する</para>
        /// </remarks>
        public override HySGeoMesh CreateSingleDataMesh(long lDataIndex)
        {
            HySGeoDim2MeshData csRtnData = null;

            // データがパターン所持の場合は作成不可能
            // Indexが正しい場合のみ生成
            if ((m_lMeshKind != MESH_DATA_KIND.PATTARN_DATA_HOLD) && 
                (lDataIndex >= 0) && (lDataIndex < m_csCellArray.GetDataDimentionInCell()))
            {
                // コピーを生成後、内部のセルデータを単独セルデータに差し替える
                csRtnData = new HySGeoDim2MeshData(this);
                csRtnData.m_csCellArray = m_csCellArray.CreateSingleDataCellArray(lDataIndex);
            }

            return csRtnData;
        }

// ver1.1 start of 追加

        /// <summary><para>method outline:</para>
        /// <para>１行分のデータ書き出し</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lRtn = CSVDataAppendWrite(csFile,csCellChara) </para>
        /// </example>
        /// <param name="csFile">CSVファイル</param>
        /// <param name="csCellChara">セル内の変数情報</param>
        /// <returns> =0:正常、-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long CSVDataAppendWrite(HySFile csFile, HySDataCharacteristicInCell csCellChara)
        {
            long lRtn = 0;
            String sStr = HySCalendar.GetString(this.m_csCellArray.GetLastTime(), HySCalendar.FORMAT.lSW_YEAR).ToString();
            csFile.WriteText(sStr);

            HySCellData[,] csCells = ((HySD2CellArrayData)this.m_csCellArray).GetCellData();
            for(int iIdx=0;iIdx<csCellChara.m_lDim;iIdx++)
            {
                for (int iDtP2 = 0; iDtP2 < this.m_lLatDim; iDtP2++)
                {
                    sStr = ",";
                    if( iDtP2 == 0 )
                    {
                        sStr += csCellChara.m_csLabel[iIdx];
                    }
                    
                    for (int iDtLp = 0; iDtLp < this.m_lLonDim; iDtLp++)
                    {
                        sStr += "," + csCells[iDtLp, iDtP2].m_dData[iIdx].ToString();
                    }
                    
                    csFile.WriteText(sStr);
                }
            }
            return lRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>１行分のデータ読み込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lRtn = CSVRecordDataRead(csFile,csCellChara) </para>
        /// </example>
        /// <param name="csFile">CSVファイル</param>
        /// <param name="csCellChara">Cell内変数情報</param>
        /// <returns> long =1:データ有り、 =0:データ無し、=-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long CSVRecordDataRead(HySFile csFile, HySDataCharacteristicInCell csCellChara)
        {
            long lRtn = 0;
            HySString sOut = new HySString();

            string[] sInWk;
            if (csFile.ReadText(ref sOut) > 0)
            {   // データ有り
                HySCellData[,] csCells = ((HySD2CellArrayData)this.m_csCellArray).GetCellData();
                lRtn = 1;
                try
                {
                    HySTime csTim = null;
                    // ','区切りで展開する
                    sInWk = sOut.ToString().Split(',');
                    csTim = HySCalendar.CreateTime(sInWk[0]);
                    if (csTim == null) { lRtn = -1; return lRtn; }

                    this.SetTime(csTim);

                    for (int iIdx = 0; iIdx < csCellChara.m_lDim; iIdx++)
                    {
                        for (int iDtP2 = 0; iDtP2 < this.m_lLatDim; iDtP2++)
                        {
                            if (csFile.ReadText(ref sOut) > 0)
                            {   // データ有り
                                sInWk = sOut.ToString().Split(',');
                                for (int iDtLp = 0; iDtLp < this.m_lLonDim; iDtLp++)
                                {
                                    csCells[iDtLp, iDtP2].m_dData[iIdx] = double.Parse(sInWk[iDtLp + 2]);
                                }
                            }
                            else
                            {
                                lRtn = -1;
                                return lRtn;
                            }
                        }
                    }
                }
                catch
                {
                    lRtn = -1;
                }
            }
            return lRtn;
        }

// ver1.1 start of 追加
      
        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <summary>保存バージョン情報</summary>
        private string m_sDecodedVersion;
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sDecodedVersion = GetDecodedVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 保存バージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メンバー変数に設定されているバージョン情報を返す</para>
        /// </remarks>
        public new string GetDecodedVersion()
        {
            return m_sDecodedVersion;
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sVersion = GetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 現在のバージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public new string GetNowVersion()
        {
            return "1.00";
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在のバージョン情報をメンバー変数に設定する</para>
        /// </remarks>
        public new void SetNowVersion()
        {
            m_sDecodedVersion = GetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>復元後の整合性確保処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> PostDeserialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
        /// バージョンによって変数等追加がない場合には、実装の必要がない
        /// </para>
        /// </remarks>
        public override void PostDeserialize()
        {
            base.PostDeserialize();

            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }
    }
}
