// <summary>ソースコード：ＧＩＳ－表示用　凡例情報<</summary>
// <author>CommonMP</author>

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

using CommonMP.HYSSOP.Interface;
using CommonMP.HYSSOP.Interface.HSData;

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


namespace CommonMP.HYSSOP.CoreImpl.HSTools
{
    /// <summary><para>class outline:</para>
    /// <para>CommonMP GIS データから　KML 作成用ツールクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.1.0][2010/12/22][新規作成]</para>
    /// <para>remarks:</para>
    /// <para>無し</para>
    /// </remarks>
    public class HySGeoKMLWirteTool : HySRoot
    {
        /// <summary><para>method outline:</para>
        /// <para>KMLヘッダ書き込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlHeader(csFile, sName)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="sName">string オブジェクトのラベル</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlHeader(HySFile csFile, string sName)
        {
            // ＫＭＬヘッダ部分
            csFile.WriteText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            csFile.WriteText("<kml xmlns=\"http://earth.google.com/kml/2.2\">");
            csFile.WriteText("<Document>");
            csFile.WriteText("    <name>" + sName + "</name>");
        }

        /// <summary><para>method outline:</para>
        /// <para>KMLフッター書き込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlFooter(csFile)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlFooter(HySFile csFile)
        {
            // ＫＭＬフッター部分
            csFile.WriteText("</Document>");
            csFile.WriteText("</kml>");
            //csFile.WriteText("\r\n");
        }

        /// <summary><para>method outline:</para>
        /// <para>LookAtタグ設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlLookAt(csFile, dLat, dLon, dRange)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="dLat">double ビューの中心緯度</param>
        /// <param name="dLon">double ビューの中心経度</param>
        /// <param name="dRange">double  LookAt 地点からの距離(メートル)</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlLookAt(HySFile csFile, double dLat, double dLon, double dRange)
        {
            csFile.WriteText("  <LookAt>");                                            //カメラの位置の設定
            csFile.WriteText("      <longitude>" + dLon.ToString() + "</longitude>");  //カメラの中心経度
            csFile.WriteText("      <latitude>" + dLat.ToString() + "</latitude>");    //カメラの中心緯度
            csFile.WriteText("      <altitude>0</altitude>");                          //地表からの距離（メートル）ただし<altitudeMode> の設定に従って解釈されます
            csFile.WriteText("      <range>" + dRange.ToString() + "</range>");        // LookAt 地点からの距離
            //csFile.WriteText("      <heading>-34.82469740081282</heading>");
            csFile.WriteText("      <tilt>50.0</tilt>");                               //地表の法線と LookAt への視点の方向との間の角度
            csFile.WriteText("  </LookAt>");                                           //カメラの位置の設定終了
        }

        /// <summary><para>method outline:</para>
        /// <para>TimeSpanタグ設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.TagKmlTimeSpan(csBeginTm, csEndTm, ref sTimeSpn)</para>
        /// </example>
        /// <param name="csBeginTm">HySTime アニメーション開始時刻</param>
        /// <param name="csEndTm">HySTime アニメーション終了時刻</param>
        /// <param name="sTimeSpn">string 開始時刻と終了時刻のkml</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void TagKmlTimeSpan(HySTime csBeginTm, HySTime csEndTm, ref string sTimeSpn)
        {
            sTimeSpn = "      <TimeSpan>\n";  //開始と終了で区切られた時間の範囲の設定（<begin>と<end>が必要）
            DateTime csDT = DateTime.Parse("1/1/1970 0:0:0");
            TimeSpan csTS = TimeSpan.FromMilliseconds(csBeginTm.GetTime() * 1000);
            csDT = csDT.Add(csTS);

            sTimeSpn += "          <begin>" +
                csDT.Year.ToString() + "-" + csDT.Month.ToString("00") + "-" + csDT.Day.ToString("00") + "T" + csDT.Hour.ToString("00") + ":" + csDT.Minute.ToString("00") + ":" + csDT.Second.ToString("00") + "Z"
                + "</begin>\n";  //開始時刻の設定
            csDT = DateTime.Parse("1/1/1970 0:0:0");
            csTS = TimeSpan.FromMilliseconds(csEndTm.GetTime() * 1000);
            csDT = csDT.Add(csTS);

            sTimeSpn += "          <end>" +
                csDT.Year.ToString() + "-" + csDT.Month.ToString("00") + "-" + csDT.Day.ToString("00") + "T" + csDT.Hour.ToString("00") + ":" + csDT.Minute.ToString("00") + ":" + csDT.Second.ToString("00") + "Z"
                + "</end>\n";  //終了時刻の設定

            sTimeSpn += "      </TimeSpan>";  //時間の範囲の設定終了
        }

        /// <summary><para>method outline:</para>
        /// <para>メッシュデータ書き込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlMeshData(csFile, csDim2Mesh, lCellItemNo, csLegendInf)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="csDim2Mesh">HySGeoDim2MeshData　2次元メッシュ情報</param>
        /// <param name="lCellItemNo">long　セル番号</param>
        /// <param name="csLegendInf">HySGeoLegendInf　凡例情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlMeshData(HySFile csFile, HySGeoDim2MeshData csDim2Mesh, long lCellItemNo, HySGeoLegendInf csLegendInf)
        {
            // ヘッダー情報書き込み
            HySTime stTm = csDim2Mesh.GetLastTime();
            HySGeoKMLWirteTool.WriteKmlHeader(csFile, stTm.GetTime().ToString());

            // 位置情報を取得
            long lNumLat = csDim2Mesh.GetLatDimension();
            long lNumLon = csDim2Mesh.GetLonDimension();

            double dSWLat = 0.0; double dSWLon = 0.0;
            double dNELat = 0.0; double dNELon = 0.0;
            csDim2Mesh.GetLocation(ref dSWLat, ref dSWLon, ref dNELat, ref dNELon);
            double dDltLat = (dNELat - dSWLat) / (double)lNumLat;
            double dDltLon = (dNELon - dSWLon) / (double)lNumLon;

            // 視点位置等を　KMLﾌｧｲﾙに書き込む
            HySGeoKMLWirteTool.WriteKmlLookAt(csFile, (dSWLat + dNELat) / 2.0, (dSWLon + dNELon) / 2.0, 15000.0);

            // KMLﾌｧｲﾙ 本体部作成し KMLﾌｧｲﾙに書き込み
            HySCellData[,] csCells = csDim2Mesh.GetMeshData();
            // 各セルの値を書き出す
            for (long lLpLat = 0; lLpLat < lNumLat; lLpLat++)
            {
                for (long lLpLon = 0; lLpLon < lNumLon; lLpLon++)
                {
                    HySGeoKMLWirteTool.WriteKmlMeshTag(
                        lLpLat * lNumLon + lLpLon,
                        csFile, csCells[lLpLon, lLpLat].m_dData[lCellItemNo], csLegendInf,
                        dSWLat + (double)lLpLat * dDltLat, dSWLon + (double)lLpLon * dDltLon,
                        dSWLat + (double)(lLpLat + 1) * dDltLat, dSWLon + (double)(lLpLon + 1) * dDltLon);
                }
            }

            // フッター情報書き込み
            HySGeoKMLWirteTool.WriteKmlFooter(csFile);
        }

        /// <summary><para>method outline:</para>
        /// <para>メッシュデータ書き込み処理（時系列情報）</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlMeshTag(csFile, csD2MeshSerialData, lCellItemNo, csLegendInf)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="csD2MeshSerialData">HySGeoDim2MeshSerialData　2次元メッシュ時系列情報</param>
        /// <param name="lCellItemNo">long　セル番号</param>
        /// <param name="csLegendInf">HySGeoLegendInf　凡例情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlMeshData(HySFile csFile, HySGeoDim2MeshSerialData csD2MeshSerialData,long lCellItemNo, HySGeoLegendInf csLegendInf)
        {
            lCellItemNo = 0;
            // KML ヘッダー情報をKMLﾌｧｲﾙに書き込み
            string sDataName = csD2MeshSerialData.GetCellDataCharacteristic().m_csLabel[lCellItemNo];
            sDataName = csD2MeshSerialData.GetCellDataCharacteristic().GetDataKind(lCellItemNo).ToString();
            HySGeoKMLWirteTool.WriteKmlHeader(csFile, sDataName);

            // 視点位置等を　KMLﾌｧｲﾙに書き込む
            double dSWLat = 0.0; double dSWLon = 0.0;
            double dNELat = 0.0; double dNELon = 0.0;
            csD2MeshSerialData.GetLocation(ref dSWLat, ref dSWLon, ref dNELat, ref dNELon);
            HySGeoKMLWirteTool.WriteKmlLookAt(csFile, (dSWLat + dNELat) / 2.0, (dSWLon + dNELon) / 2.0, 15000.0);

            // KMLﾌｧｲﾙ 本体部作成し KMLﾌｧｲﾙに書き込み
            //     時系列情報を　レコードに分割取得し、各レコード毎に　KMLﾌｧｲﾙに書き込む
            long lNum = csD2MeshSerialData.GetCount();// レコード数
            HySTime csDltTm = new HySTime(3600 * 24);
            csD2MeshSerialData.SetCursorFirst();
            HySGeoDim2MeshData csMeshDt = csD2MeshSerialData.GetCursorData() as HySGeoDim2MeshData;

            for (long lLP = 0; lLP < lNum; lLP++)
            {   // レコード数繰り返し（時系列ﾃﾞｰﾀ内のレコード）
                if (csMeshDt == null) { break; } // 異常により中止

                csD2MeshSerialData.MoveCursorNext();
                HySGeoDim2MeshData csNextMeshDt = csD2MeshSerialData.GetCursorData() as HySGeoDim2MeshData;
                if (csNextMeshDt != csMeshDt)
                { csDltTm = csNextMeshDt.GetLastTime() - csMeshDt.GetLastTime(); }
                //if (csMeshDt != null)
                {
                    csMeshDt.SetLocation(dSWLat, dSWLon, dNELat, dNELon);
                    HySGeoKMLWirteTool.WriteKmlMeshTag(csFile, csMeshDt, lCellItemNo, csLegendInf, csDltTm);
                }
                csMeshDt = csNextMeshDt;
            }

            // KML フッター情報をKMLﾌｧｲﾙに書き込み
            HySGeoKMLWirteTool.WriteKmlFooter(csFile);
        }

        /// <summary><para>method outline:</para>
        /// <para>メッシュタグ書き込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlMeshData(csFile, csDim2Mesh, lCellItemNo, csLegendInf, csDltTm)</para>
        /// </example>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="csDim2Mesh">HySGeoDim2MeshData　2次元メッシュ情報</param>
        /// <param name="lCellItemNo">long　セル番号</param>
        /// <param name="csLegendInf">HySGeoLegendInf　凡例情報</param>
        /// <param name="csDltTm">HySTime　タイムスパン</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlMeshTag(HySFile csFile, HySGeoDim2MeshData csDim2Mesh, long lCellItemNo, HySGeoLegendInf csLegendInf, HySTime csDltTm)
        {
            // フォルダータグを時間単位で作成し、そのタイムスパンは csDltTm 分
            csFile.WriteText("  <Folder>");
            HySTime csTime = csDim2Mesh.GetLastTime();


            csFile.WriteText("      <name>" + HySCalendar.ToString(csTime, HySCalendar.FORMAT.lSW_YEAR) + "</name>");
            csFile.WriteText("      <visibility>0</visibility>");


            string sTimeSpn = "";
            HySGeoKMLWirteTool.TagKmlTimeSpan(csTime, csTime + csDltTm, ref  sTimeSpn);
            csFile.WriteText(sTimeSpn);

            // 位置情報を取得
            long lNumLat = csDim2Mesh.GetLatDimension();
            long lNumLon = csDim2Mesh.GetLonDimension();

            double dSWLat = 0.0; double dSWLon = 0.0;
            double dNELat = 0.0; double dNELon = 0.0;
            csDim2Mesh.GetLocation(ref dSWLat, ref dSWLon, ref dNELat, ref dNELon);
            double dDltLat = (dNELat - dSWLat) / (double)lNumLat;
            double dDltLon = (dNELon - dSWLon) / (double)lNumLon;

            HySCellData[,] csCells = csDim2Mesh.GetMeshData();

            // 各セルの値を書き出す
            for (long lLpLat = 0; lLpLat < lNumLat; lLpLat++)
            {
                for (long lLpLon = 0; lLpLon < lNumLon; lLpLon++)
                {
                    HySGeoKMLWirteTool.WriteKmlMeshTag(
                        lLpLat * lNumLon + lLpLon,
                        csFile, csCells[lLpLon, lLpLat].m_dData[lCellItemNo], csLegendInf,
                        dSWLat + (double)lLpLat * dDltLat, dSWLon + (double)lLpLon * dDltLon,
                        dSWLat + (double)(lLpLat + 1) * dDltLat, dSWLon + (double)(lLpLon + 1) * dDltLon);
                }
            }
            // フォルダータグを閉じる
            csFile.WriteText("  </Folder>");
        }

        /// <summary><para>method outline:</para>
        /// <para>メッシュタグ書き込み処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySGeoKMLWirteTool.WriteKmlMeshTag(lIDNo, csFile, dVal, csLegendInf, dSWLat, dSWLon, dNELat, dNELon)</para>
        /// </example>
        /// <param name="lIDNo">long　ID</param>
        /// <param name="csFile">HySFile ファイル情報</param>
        /// <param name="dVal">double　表示する値</param>
        /// <param name="csLegendInf">HySGeoLegendInf　凡例情報</param>
        /// <param name="dSWLat">double 南西緯度</param>
        /// <param name="dSWLon">double 南西経度</param>
        /// <param name="dNELat">double 北東緯度</param>
        /// <param name="dNELon">double 北東経度</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public void WriteKmlMeshTag(long lIDNo, HySFile csFile, double dVal, HySGeoLegendInf csLegendInf, double dSWLat, double dSWLon, double dNELat, double dNELon)
        {
            short uiR = 50;
            short uiG = 125;
            short uiB = 254;
            csLegendInf.GetDispInf(dVal, ref  uiR, ref  uiG, ref  uiB);
            short uiAlpl = csLegendInf.GetAlpha();
            HySGeoLegendInf.G2DMeshDispMode lMod = csLegendInf.GetG2DMeshDispMode();
            if (lMod == HySGeoLegendInf.G2DMeshDispMode.clampToGround)
            {   // 地面張り付きモードならば
                csFile.WriteText("      <Placemark id = \"" + lIDNo.ToString() + "\">");  //Placemark
                csFile.WriteText("          <name>Nm_RECT</name>");                       //オブジェクトのラベル
                csFile.WriteText("          <Style>");
                csFile.WriteText("              <PolyStyle>");                            //ポリゴンの描画スタイル設定
                csFile.WriteText("                  <color>" +                            //色と不透明度（アルファ）の値(16 進表記)
                                            uiAlpl.ToString("X2") +
                                            uiB.ToString("X2") +
                                            uiG.ToString("X2") +
                                            uiR.ToString("X2") +
                                            "</color>");                                  //色設定終了
                csFile.WriteText("                  <fill>1</fill>");                     //ポリゴンの塗りつぶし（ブール値）
                csFile.WriteText("                  <outline>1</outline>");               //ポリゴンの輪郭の描画 （ブール値）
                csFile.WriteText("              </PolyStyle>");                           //ポリゴンの描画スタイル設定の終了
                csFile.WriteText("          </Style>");
                csFile.WriteText("          <Polygon>");
                csFile.WriteText("              <extrude>1</extrude>");                   //Polygon を地面に接続するかどうかを指定（ブール値）
                csFile.WriteText("              <tessellate>1</tessellate>");             //Polygon を地形に合わせて表示（ブール値）
                csFile.WriteText("              <altitudeMode>clampToGround</altitudeMode>");//要素内の標高コンポーネントの解釈方法を指定（clampToGround,elativeToGround,absoluteから選択）
                csFile.WriteText("              <outerBoundaryIs>");                      //<outerBoundaryIs>は必須
                csFile.WriteText("                  <LinearRing>");                       //Polygon の輪郭のような、閉じた折れ線を定義
                csFile.WriteText("                      <coordinates>");                  //経度、緯度、標高を表す浮動小数点数値を指定
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + ",1");
                csFile.WriteText("                          " + dNELon.ToString() + "," + dSWLat.ToString() + ",1");
                csFile.WriteText("                          " + dNELon.ToString() + "," + dNELat.ToString() + ",1");
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dNELat.ToString() + ",1");
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + ",1");
                csFile.WriteText("                      </coordinates>");
                csFile.WriteText("                  </LinearRing>");
                csFile.WriteText("              </outerBoundaryIs>");
                csFile.WriteText("          </Polygon>");
                csFile.WriteText("      </Placemark>");
            }
            else if (lMod == HySGeoLegendInf.G2DMeshDispMode.relativeToGround)
            {   // 地面からの相対高さで表すモードならば
                double dMng = csLegendInf.GetAltMagnitude();
                csFile.WriteText("      <Placemark id = \"" + lIDNo.ToString() + "\">");
                csFile.WriteText("          <name>Nm_RECT</name>");
                csFile.WriteText("          <Style>");
                csFile.WriteText("              <PolyStyle>");
                csFile.WriteText("                  <color>" +
                                            uiAlpl.ToString("X2") +
                                            uiB.ToString("X2") +
                                            uiG.ToString("X2") +
                                            uiR.ToString("X2") +
                                            "</color>");
                csFile.WriteText("                  <fill>1</fill>");
                csFile.WriteText("                  <outline>1</outline>");
                csFile.WriteText("              </PolyStyle>");
                csFile.WriteText("          </Style>");
                csFile.WriteText("          <Polygon>");
                csFile.WriteText("              <extrude>1</extrude>");
                csFile.WriteText("              <tessellate>1</tessellate>");
                csFile.WriteText("              <altitudeMode>relativeToGround </altitudeMode>");
                csFile.WriteText("              <outerBoundaryIs>");
                csFile.WriteText("                  <LinearRing>");
                csFile.WriteText("                      <coordinates>");
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dNELon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dNELon.ToString() + "," + dNELat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dNELat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                      </coordinates>");
                csFile.WriteText("                  </LinearRing>");
                csFile.WriteText("              </outerBoundaryIs>");
                csFile.WriteText("          </Polygon>");
                csFile.WriteText("      </Placemark>");
            }
            else
            {   // 海抜からの高さで表すモードならば
                double dMng = csLegendInf.GetAltMagnitude();
                HySObjectKind csObjData = csLegendInf.GetDataKind();

                csFile.WriteText("      <Placemark id = \"" + lIDNo.ToString() + "\">");
                csFile.WriteText("          <name>Nm_RECT</name>");
                csFile.WriteText("          <Style>");
                csFile.WriteText("              <PolyStyle>");
                csFile.WriteText("                  <color>" +
                                            uiAlpl.ToString("X2") +
                                            uiB.ToString("X2") +
                                            uiG.ToString("X2") +
                                            uiR.ToString("X2") +
                                            "</color>");
                csFile.WriteText("                  <fill>1</fill>");
                csFile.WriteText("                  <outline>1</outline>");
                csFile.WriteText("              </PolyStyle>");
                csFile.WriteText("          </Style>");
                csFile.WriteText("          <Polygon>");
                csFile.WriteText("              <extrude>1</extrude>");
                csFile.WriteText("              <tessellate>1</tessellate>");
                csFile.WriteText("              <altitudeMode>absolute</altitudeMode>");
                csFile.WriteText("              <outerBoundaryIs>");
                csFile.WriteText("                  <LinearRing>");
                csFile.WriteText("                      <coordinates>");
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dNELon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dNELon.ToString() + "," + dNELat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dNELat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                          " + dSWLon.ToString() + "," + dSWLat.ToString() + "," + (dMng * dVal).ToString());
                csFile.WriteText("                      </coordinates>");
                csFile.WriteText("                  </LinearRing>");
                csFile.WriteText("              </outerBoundaryIs>");
                csFile.WriteText("          </Polygon>");
                csFile.WriteText("      </Placemark>");
            }
        }

        // 
    }
}
