// <summary>ソースコード：幾何学図形基底抽象化クラス<</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

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


namespace CommonMP.HYSSOP.CoreImpl.HSData
{
    /// <summary><para>class outline:</para>
    /// <para>地図上のエリアを示すクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/12/01][新規作成]
    /// Ver1.0 では矩形エリアのみリリース
    /// </para>
    /// <para>remarks:</para>
    /// <para>地理空間上のエリアを示す情報</para>
    /// </remarks>
    [Serializable]
    public class HySGeoAreaInfo : HySDataRoot, HySVersionManagement
    {
        /// <summary>エリア形状定義 </summary>
        public enum AreaType
        {
            /// <summary>矩形</summary>
            RECT = 1,
            /// <summary>円</summary>
            CIRCLE,
            /// <summary>任意多角形</summary>
            POLYGON,
            /// <summary>折れ線</summary>
            LINE
        }

        /// <summary>エリア形状</summary>
        protected AreaType m_eAreaType = AreaType.RECT;

        //============　m_eAreaType=AreaType.RECT の時有効　================
        /// <summary>南西頂点緯度（度単位）</summary>
        protected double m_dSWLatitude=0.0;
        /// <summary>南西頂点経度度（度単位）</summary>
        protected double m_dSWLongitude=0.0;
        /// <summary>北東頂点緯度（度単位）</summary>
        protected double m_dNELatitude=0.0;
        /// <summary>北東頂点経度度（度単位）</summary>
        protected double m_dNELongitude=0.0;


        //============　m_eAreaType=AreaType.CIRCLE の時有効　================
        /// <summary>中心位置：経度（度単位）</summary>
        protected double m_dCenterLon = 0.0;
        /// <summary>中心位置：緯度（度単位）</summary>
        protected double m_dCenterLat = 0.0;
        /// <summary>半径：経度方向（度単位）</summary>
        protected double m_dLonRadius = 0.0;
        /// <summary>半径：緯度方向（度単位）</summary>
        protected double m_dLatRadius = 0.0;

        //============　m_eAreaType=AreaType.POLYGON の時有効　================
        /// <summary>経度頂点列（度単位）　最初と最後の頂点を結んで　閉曲線となる </summary>
        protected HySLinkedListDouble m_dLonList = null;
        /// <summary>緯度頂点列（度単位）　最初と最後の頂点を結んで　閉曲線となる </summary>
        protected HySLinkedListDouble m_dLatList = null;

        //============　柱状の形状を定義する時有効　================
        /// <summary>標高上限（m単位）</summary>
        protected double m_dUpperAltitude = 0.0;
        /// <summary>標高下限（m単位）</summary>
        protected double m_dLowerAltitude = 0.0;


        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoAreaInfo csArea = new HySGeoAreaInfo()  </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySGeoAreaInfo 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySGeoAreaInfo()
        {
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>エリア形状取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetAreaType( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>AreaType エリア形状</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual AreaType GetAreaType( )
        {
            return m_eAreaType;
        }

        /// <summary><para>method outline:</para>
        /// <para>エリア情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetArea(dSWLat, dSWLon, dNELat, dNELon) </para>
        /// </example>
        /// <param name="dSWLat">南西頂点緯度（度単位）</param>
        /// <param name="dSWLon">南西頂点経度（度単位）</param>
        /// <param name="dNELat">北東頂点緯度（度単位）</param>
        /// <param name="dNELon">北東頂点経度（度単位）</param> 
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetArea(double dSWLat, double dSWLon, double dNELat, double dNELon)
        {
            m_eAreaType = AreaType.RECT;
            m_dSWLatitude = dSWLat;
            m_dSWLongitude = dSWLon;
            m_dNELatitude = dNELat;
            m_dNELongitude = dNELon;
        }
        /// <summary><para>method outline:</para>
        /// <para>エリア情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetArea(ref dSWLat,ref dSWLon,ref dNELat,ref dNELon) </para>
        /// </example>
        /// <param name="dSWLat">南西頂点緯度（度単位）</param>
        /// <param name="dSWLon">南西頂点経度（度単位）</param>
        /// <param name="dNELat">北東頂点緯度（度単位）</param>
        /// <param name="dNELon">北東頂点経度（度単位）</param> 
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual AreaType GetArea(ref double dSWLat, ref double dSWLon, ref double dNELat, ref double dNELon)
        {
            dSWLat = m_dSWLatitude;
            dSWLon = m_dSWLongitude;
            dNELat = m_dNELatitude;
            dNELon = m_dNELongitude;
            return m_eAreaType;
        }


        /// <summary><para>method outline:</para>
        /// <para>高度位置設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetAltitude(dUpAlt, dLwAlt) </para>
        /// </example>
        /// <param name="dUpAlt">上限高度（ｍ単位）</param>
        /// <param name="dLwAlt">下限高度（ｍ単位）</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetAltitude(double dUpAlt, double dLwAlt)
        {
            m_dUpperAltitude = dUpAlt;
            m_dLowerAltitude = dLwAlt;
        }
        /// <summary><para>method outline:</para>
        /// <para>高度位置取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HGetAltitude(ref dUpAlt, ref dLwAlt) </para>
        /// </example>
        /// <param name="dUpAlt">上限高度（ｍ単位）</param>
        /// <param name="dLwAlt">下限高度（ｍ単位）</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void GetAltitude(ref double dUpAlt, ref double dLwAlt)
        {
            dUpAlt = m_dUpperAltitude;
            dLwAlt = m_dLowerAltitude;
        }




        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <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 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 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 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 virtual void PostDeserialize()
        {
            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>逆シリアル化時追加処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
        /// </example>
        /// <param name="csObj">ダミー</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>予約処理</para>
        /// </remarks>
        void IDeserializationCallback.OnDeserialization(Object csObj)
        {
            PostDeserialize();
        }
    }
}
