// <summary>ソースコード：>河道横断面データファイルクラス</summary>
// <author>CommonMP</author>

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

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

namespace CommonMP.HYSSOP.CoreImpl.HSTools
{
    /// <summary><para>class outline:</para>
    /// <para>河道横断面データ一覧ファイルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/09/14][新規作成]</para>
    /// </remarks>
    public class HySRiverCrossSectionListFile
    {

        /// <summary>XMLライタ</summary>
        private HySXmlWriter m_csXMLWriter = null;

        ///// <summary>m⇒km変換用</summary>
        //static private readonly double CONV_UNIT_M_TO_KM = 1000.0;

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySRiverCrossSectionListFile csFile = new HySRiverCrossSectionListFile(csFilePath) </para>
        /// </example>
        /// <param name="csFilePath">ファイルパス</param>
        /// <returns>HySRiverCrossSectionListFile  生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySRiverCrossSectionListFile(string csFilePath)
        {
            m_csXMLWriter = new HySXmlWriter(csFilePath);
        }

        /// <summary><para>method outline:</para>
        /// <para>河道横断面データ一覧ファイル出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = Write(csDataList) </para>
        /// </example>
        /// <param name="csDataList">ストックデータリスト</param>
        /// <returns>bool  =true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public bool Write(HySStockDataList csDataList)
        {
            // 河川横断面データを距離順にソート
            List<HySGeoRiverCrossSectionData> csSortedList = SortList(csDataList);

            // 横断面データ一覧の要素作成
            CreateCrossSectionListNode(csSortedList);

            // ファイル保存
            bool bSave = m_csXMLWriter.Save();
            if (!bSave)
            {   // ファイル出力失敗
                // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, "HySRiverCrossSectionListFile::Write()",
                                           Properties.HysMsgResources.STATEMENT_RCSLF_OUT_NG);

               // HySLog.LogOut(HySLog.ONLINE, "HySRiverCrossSectionListFile::Write()",
               //                              "河道横断面データ一覧ファイルの出力に失敗しました。");
            }

            return bSave;
        }

        /// <summary><para>method outline:</para>
        /// <para>「横断面リスト」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> CreateCrossSectionListNode(csDataList) </para>
        /// </example>
        /// <param name="csDataList">ストックデータリスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void CreateCrossSectionListNode(List<HySGeoRiverCrossSectionData> csDataList)
        {
            // 横断面リストの要素作成
            HySXmlNode csRootNode = m_csXMLWriter.CreateRoot(HySGISDefine.xml_CROSS_SEC_SECTIONS);

            // ストックデータリストの要素分、横断面要素を作成
            for (int i = 0; i < csDataList.Count; i++)
            {
                // 横断面データを順に取り出す
                HySGeoRiverCrossSectionData csCrossSectionData = csDataList[i];

                // １横断面の要素作成
                HySXmlNode csCrossSectionNode = CreateCrossSectionNode(csCrossSectionData);
                csRootNode.AppendChild(csCrossSectionNode);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>「横断面」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySXmlNode csNode = CreateCrossSectionNode(csData) </para>
        /// </example>
        /// <param name="csData">河道横断面図形状データ</param>
        /// <returns>HySXmlNode　1横断面の要素を表すxmlノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySXmlNode CreateCrossSectionNode(HySGeoRiverCrossSectionData csData)
        {
            // 1横断面の要素作成
            HySXmlNode csRtnNode = HySXmlNode.CreateElement(HySGISDefine.xml_CROSS_SEC_SECTION, m_csXMLWriter);
            // 断面ID
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_ID, csData.GetID().ToString());
            // 河川コード
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_RIVERCODE, csData.GetRiverCode().ToString());
            // 補助河川コード
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_AUX_RIVER_FLAG, csData.GetAuxRiverCode().ToString());
            // 距離標
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_DISTANCE_POST_ATT, csData.GetDistancePost().ToString());
            // 横断面x座標の最小値
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_MIN, csData.GetMinXCoordinate().ToString());
            // 横断面x座標の最大値
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_MAX, csData.GetMaxXCoordinate().ToString());

            // 距離標の要素作成
            HySXmlNode csDistancePostNode = CreateDistancePost(csData.GetGeoRiverDistancePost());

            // 子要素を追加
            csRtnNode.AppendChild(csDistancePostNode);

            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>「距離標」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySXmlNode csNode = CreateDistancePost(csData) </para>
        /// </example>
        /// <param name="csData">河道横断面図形状データ</param>
        /// <returns>HySXmlNode　「距離標」要素を表すxmlノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySXmlNode CreateDistancePost(HySGeoRiverDistancePost csData)
        {

            // 距離標要素作成
            HySXmlNode csRtnNode = HySXmlNode.CreateElement(HySGISDefine.xml_CROSS_SEC_DISTANCE_POST_ELE, m_csXMLWriter);
            // 距離
            //double dMeterDistance = csData.GetDistance() * CONV_UNIT_M_TO_KM;
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_DISTANCE, csData.GetDistance().ToString());

            // 左岸距離標の要素作成
            if (csData.GetLeftGeoPoint() != null)
            {
                HySXmlNode csLeftNode = CreateLeftDistancePostNode(csData.GetLeftGeoPoint());
                csRtnNode.AppendChild(csLeftNode);
            }

            // 右岸距離標の要素作成
            if (csData.GetRightGeoPoint() != null)
            {
                HySXmlNode csRightNode = CreateRightDistancePostNode(csData.GetRightGeoPoint());
                csRtnNode.AppendChild(csRightNode);
            }

            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>「左岸距離標」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySXmlNode csNode = CreateLeftDistancePostNode(csPoint) </para>
        /// </example>
        /// <param name="csPoint">経緯度情報</param>
        /// <returns>HySXmlNode　「左岸距離標」要素を表すxmlノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySXmlNode CreateLeftDistancePostNode(HySGeoPoint csPoint)
        {
            // 左岸点距離標要素を作成
            HySXmlNode csRtnNode = HySXmlNode.CreateElement(HySGISDefine.xml_CROSS_SEC_LEFT_DISTANCE_POST, m_csXMLWriter);
            // 地理座標要素を作成
            HySXmlNode csCoordNode = CreateGeoCoodinatesNode(csPoint);

            // 子要素を追加
            csRtnNode.AppendChild(csCoordNode);

            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>「右岸距離標」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySXmlNode csNode = CreateRightDistancePostNode(csPoint) </para>
        /// </example>
        /// <param name="csPoint">経緯度情報</param>
        /// <returns>HySXmlNode　「右岸距離標」要素を表すxmlノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySXmlNode CreateRightDistancePostNode(HySGeoPoint csPoint)
        {
            // 右岸点要素を作成
            HySXmlNode csRtnNode = HySXmlNode.CreateElement(HySGISDefine.xml_CROSS_SEC_RIGHT_DISTANCE_POST, m_csXMLWriter);
            // 地理座標要素を作成
            HySXmlNode csCoordNode = CreateGeoCoodinatesNode(csPoint);

            // 右岸点要素に子要素を追加
            csRtnNode.AppendChild(csCoordNode);

            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>「地理座標」要素作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySXmlNode csNode = CreateGeoCoodinatesNode(csPoint) </para>
        /// </example>
        /// <param name="csPoint">経緯度情報</param>
        /// <returns>HySXmlNode　「地理座標」要素を表すxmlノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySXmlNode CreateGeoCoodinatesNode(HySGeoPoint csPoint)
        {
            // 地理座標要素を作成
            // 子要素が無いため属性だけ設定し返却
            HySXmlNode csRtnNode = HySXmlNode.CreateElement(HySGISDefine.xml_CROSS_SEC_COORDINATES, m_csXMLWriter);

            // 属性を設定
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_LATITUDE, csPoint.m_dLatitude.ToString());
            csRtnNode.SetAttribute(HySGISDefine.xml_CROSS_SEC_LONGITUDE, csPoint.m_dLongitude.ToString());

            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>横断面データを距離順(昇順)にソートする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List csList = SortList(csDataList) </para>
        /// </example>
        /// <param name="csDataList">ストックデータリスト</param>
        /// <returns>List　ソート後の横断面データリスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private List<HySGeoRiverCrossSectionData> SortList(HySStockDataList csDataList)
        {
            // StockDataList型をList<HySGeoRiverCrossSectionData>型に変換
            List<HySGeoRiverCrossSectionData> csSortedList = ConvToList(csDataList);

            // 昇順にソートする
            IComparer<HySGeoRiverCrossSectionData> csDistanceComparer = new HySRiverCrossSectionDistanceComparer();
            csSortedList.Sort(csDistanceComparer);

            return csSortedList;
        }

        /// <summary><para>method outline:</para>
        /// <para>HySStockDataList型をList型に変換する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List csList = ConvToList(csDataList) </para>
        /// </example>
        /// <param name="csDataList">ストックデータリスト</param>
        /// <returns>List型のデータリスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private List<HySGeoRiverCrossSectionData> ConvToList(HySStockDataList csDataList)
        {
            // HySStockDataList型をList<>型に変換
            List<HySGeoRiverCrossSectionData> csRtnList = new List<HySGeoRiverCrossSectionData>();
            csDataList.SetCursorFirst();
            for (int i = 0; i < csDataList.GetCount(); i++)
            {
                HySStockData csStockData = (HySStockData)csDataList.GetCursorData();
                HySGeoRiverCrossSectionData csData = (HySGeoRiverCrossSectionData)csStockData.GetData();
                csRtnList.Add(csData);
                csDataList.MoveCursorNext();
            }
            return csRtnList;
        }
    }

    /// <summary><para>class outline:</para>
    /// <para>河道横断面データ一覧ファイルクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/09/14][新規作成]</para>
    /// </remarks>
    public class HySRiverCrossSectionDistanceComparer : IComparer<HySGeoRiverCrossSectionData>
    {
        /// <summary><para>method outline:</para>
        /// <para>2つのオブジェクトの距離を比較する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> List csList = ConvToList(csDataList) </para>
        /// </example>
        /// <param name="x">第一比較用オブジェクト</param>
        /// <param name="y">第二比較用オブジェクト</param>
        /// <returns>0より小さい値:xがyより小さい, 0:x=y, 0より大きい値:xがyより大きい</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public int Compare(HySGeoRiverCrossSectionData x, HySGeoRiverCrossSectionData y)
        {
            // 2つのオブジェクトの距離を比較し、xがyより小さい場合-1、
            // 等しい場合0、大きい場合1を返す
            if (x.GetGeoRiverDistancePost().GetDistance() - y.GetGeoRiverDistancePost().GetDistance() < 0)
            {
                return -1;
            }
            else if (x.GetGeoRiverDistancePost().GetDistance() - y.GetGeoRiverDistancePost().GetDistance() == 0)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
    }
}