// <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から引き継いだ属性としては 個別図形識別子以外に 有効な属性はない</para>
    /// </remarks>
    [Serializable]
    public class HySGeoDim3MeshData : HySGeoMesh //, HySTimeRecordIF
    {
        ///// <summary>配列データ本体  m_lMeshKind = DOUBLE_DATA_HOLD or BOTH_DATA_HOLD の場合に有効</summary>
        //protected HySD3CellArrayData m_csCellDataDim = null;

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

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

        /// <summary><para>method outline:</para>
        /// <para>メッシュ情報インスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySCellData[,,] csData = GetMeshData();</para>
        /// <para>csData[経度No,緯度No,高度No] = x;</para>
        /// <para>y = csData[経度No,緯度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 ((HySD3CellArrayData)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,k] = x;</para>
        /// <para> y = lPtnNo[a,b,c];</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> 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)
        {
            HySGeoDim3MeshData csOrgMeshData = csOrgData as HySGeoDim3MeshData;
            if (csOrgMeshData != null)
            {
                base.CopyData(csOrgMeshData);

                if (csOrgMeshData.m_csCellArray != null)
                {
                    m_csCellArray = new HySD3CellArrayData((HySD3CellArrayData)csOrgMeshData.m_csCellArray);
                }

                if (csOrgMeshData.m_lPatternNo != null)
                {
                    m_lPatternNo = new long[m_lLonDim, m_lLatDim, m_lAltDim];
                    for (long lLp = 0; lLp < m_lAltDim; lLp++)
                    {
                        for (long lLp2 = 0; lLp2 < m_lLatDim; lLp2++)
                        {
                            for (long lLp3 = 0; lLp3 < m_lLonDim; lLp3++)
                            {
                                m_lPatternNo[lLp3, lLp2, lLp] = csOrgMeshData.m_lPatternNo[lLp3, 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> HySGeoDim3MeshData 単独データメッシュ情報　</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>指定されたインデックスのセル内部データのみを持つメッシュ情報データを生成する</para>
        /// </remarks>
        public override HySGeoMesh CreateSingleDataMesh(long lDataIndex)
        {
            HySGeoDim3MeshData csRtnData = null;

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

            return csRtnData;
        }

        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <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();
            }
        }
    }
}
