// <summary>ソースコード：ＨＹＭＣＯ描画要素</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Drawing;

using CommonMP.HYSSOP.Interface;
using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data.StructInfo;

namespace CommonMP.HYMCO.CoreOptions.McViewer.DotNetViewer
{
    /// <summary><para>class outline:</para>
    /// <para>描画要素クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/11/28][新規作成]</para>
    /// </remarks>
    /// <remarks><para>remarks:</para>
    /// <para>本クラスはバージョンアップ互換性の対象外</para>
    /// </remarks>
    [Serializable]
    public class McGraphicsGroupElement : McGraphicsElement
    {

        /// <summary>グループ内要素リスト </summary>
        protected List<McGraphicsElement> m_csElmList;

        /// <summary>グループ内接続線リスト</summary>
        protected List<McGraphicsElement> m_csLineList;

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsGroupElement csElement = new McGraphicsGroupElement(eKind)</para>
        /// </example>
        /// <param name="eKind">シンボル描画種別</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsGroupElement(McDefine.SymbolDrawKind eKind)
            : base(eKind, new HySObjectKind())
        {
            m_csElmList = new List<McGraphicsElement>();
            m_csLineList = new List<McGraphicsElement>();
        }

        //======================================
        // 内部エレメント関連メソッド
        //======================================
        /// <summary><para>method outline:</para>
        /// <para>グループ要素追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = AddElement( csElm )</para>
        /// </example>
        /// <param name="csElm">グループ構成要素</param>
        /// <returns>long 0:成功，-1:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long AddElement(McGraphicsElement csElm)
        {
            if (csElm == null)
            {// パラメータ異常
                return -1L;
            }

            csElm.SetParentElm(this);

            m_csElmList.Add(csElm);

            return 0L;
        }
        /// <summary><para>method outline:</para>
        /// <para>グループ要素数取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lCount = GetElmCount()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long  グループ要素数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long GetElmCount()
        {
            return m_csElmList.Count;
        }

        /// <summary><para>method outline:</para>
        /// <para>グループ要素取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsElement csElement = GetElement(lPos)</para>
        /// </example>
        /// <param name="lPos">位置(0相対)</param>
        /// <returns>McGraphicsElement  グループ要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsElement GetElement(long lPos)
        {
            McGraphicsElement csElm = null;  // グループ要素

            if (lPos >= 0 && lPos < GetElmCount())
            {// 範囲内
                csElm = m_csElmList[(int)lPos];
            }

            return csElm;
        }

        /// <summary><para>method outline:</para>
        /// <para>グループ要素削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsElement csElement = DelElement(lPos)</para>
        /// </example>
        /// <param name="lPos">位置(0相対)</param>
        /// <returns>McGraphicsElement  削除グループ要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsElement DelElement(long lPos)
        {
            McGraphicsElement csElm = null;  // グループ要素

            if (lPos >= 0 && lPos < GetElmCount())
            {// 範囲内
                csElm = m_csElmList[(int)lPos];
                m_csElmList.RemoveAt((int)lPos);
            }

            return csElm;
        }

        /// <summary><para>method outline:</para>
        /// <para>グループ要素リスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>List＜McGraphicsElement＞ csElementList = GetGroupElementList()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>List＜McGraphicsElement＞  グループ要素リスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public List<McGraphicsElement> GetGroupElementList()
        {
            return m_csElmList;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続線要素追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = AddLineElement( csLineElm )</para>
        /// </example>
        /// <param name="csLineElm">接続線要素</param>
        /// <returns>long 0:成功，-1:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long AddLineElement(McGraphicsElement csLineElm)
        {
            if (csLineElm == null)
            {// パラメータ異常
                return -1L;
            }

            csLineElm.SetParentElm(this);

            m_csLineList.Add(csLineElm);

            return 0L;
        }
        /// <summary><para>method outline:</para>
        /// <para>接続線要素数取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lCount = GetLineElmCount()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long  接続線要素数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long GetLineElmCount()
        {
            return m_csLineList.Count;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続線要素取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsElement csLineElm = GetLineElement(lPos)</para>
        /// </example>
        /// <param name="lPos">位置(0相対)</param>
        /// <returns>McGraphicsElement  接続線要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsElement GetLineElement(long lPos)
        {
            McGraphicsElement csElm = null;  // 接続線要素

            if (lPos >= 0 && lPos < GetLineElmCount())
            {// 範囲内
                csElm = m_csLineList[(int)lPos];
            }

            return csElm;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続線要素削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsElement csLineElm = DelLineElement(lPos)</para>
        /// </example>
        /// <param name="lPos">位置(0相対)</param>
        /// <returns>McGraphicsElement  接続線要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsElement DelLineElement(long lPos)
        {
            McGraphicsElement csElm = null;  // 接続線要素

            if (lPos >= 0 && lPos < GetLineElmCount())
            {// 範囲内
                csElm = m_csLineList[(int)lPos];
                m_csLineList.RemoveAt((int)lPos);
            }

            return csElm;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続線要素リスト取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>List＜McGraphicsElement＞ csLineElmList = GetGroupLineElementList()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>List＜McGraphicsElement＞  接続線要素リスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public List<McGraphicsElement> GetGroupLineElementList()
        {
            return m_csLineList;
        }

        /// <summary><para>method outline:</para>
        /// <para>要素表示範囲取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = GetDispRect(pPointLeftTop,pPointRightBottom)</para>
        /// </example>
        /// <param name="pPointLeftTop">表示座標左上</param>
        /// <param name="pPointRightBottom">表示座標右下</param>
        /// <returns>long  0:正常、-1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long GetDispRect(ref Point pPointLeftTop, ref Point pPointRightBottom)
        {
            long lRtn = -1;                     // リターンコード
            long lTempWidth = 0;                // 要素幅
            long lTempHeight = 0;               // 要素高さ
            long lTempX = 0;                    // 要素座標X
            long lTempY = 0;                    // 要素座標Y

            long lMemberLeftX = 0;              // 左端座標X
            long lMemberTopY = 0;               // 上端座標Y
            long lMemberRightX = 0;             // 右端座標X
            long lMemberBottomY = 0;            // 下端座標Y

            McGraphicsElement csTmpElement=null;// 描画要素クラス

            if (m_csElmList.Count > 0)
            {   // 要素有り
                csTmpElement = m_csElmList[0];
                csTmpElement.GetPosition(ref lTempX, ref lTempY);
                if ((csTmpElement.GetRotate() == McDefine.HYM_DRAW_ANGLE_0) ||
                    (csTmpElement.GetRotate() == McDefine.HYM_DRAW_ANGLE_180))
                {// 向きが上下の場合
                    csTmpElement.GetElementSize(ref lTempWidth, ref lTempHeight);
                }
                else
                {// 向きが左右の場合
                    csTmpElement.GetElementSize(ref lTempHeight, ref lTempWidth);
                }
                lMemberLeftX = lTempX - lTempWidth / 2;
                lMemberTopY = lTempY - lTempHeight / 2;
                lMemberRightX = lTempX + lTempWidth / 2;
                lMemberBottomY = lTempY + lTempHeight / 2;

                for (int iLoop = 1; iLoop < m_csElmList.Count; iLoop++)
                {// プロジェクト要素メンバー数ループ
                    csTmpElement = m_csElmList[iLoop];
                    csTmpElement.GetPosition(ref lTempX, ref lTempY);
                    if ((csTmpElement.GetRotate() == McDefine.HYM_DRAW_ANGLE_0) ||
                        (csTmpElement.GetRotate() == McDefine.HYM_DRAW_ANGLE_180))
                    {// 向きが上下の場合
                        csTmpElement.GetElementSize(ref lTempWidth, ref lTempHeight);
                    }
                    else
                    {// 向きが左右の場合
                        csTmpElement.GetElementSize(ref lTempHeight, ref lTempWidth);
                    }

                    if (lMemberLeftX > lTempX - lTempWidth / 2)
                    {// 最も左に位置する場合
                        lMemberLeftX = lTempX - lTempWidth / 2;
                    }
                    if (lMemberTopY > lTempY - lTempHeight / 2)
                    {// 最も上に位置する場合
                        lMemberTopY = lTempY - lTempHeight / 2;
                    }
                    if (lMemberRightX < lTempX + lTempWidth / 2)
                    {// 最も右に位置する場合
                        lMemberRightX = lTempX + lTempWidth / 2;
                    }
                    if (lMemberBottomY < lTempY + lTempHeight / 2)
                    {// 最も下に位置する場合
                        lMemberBottomY = lTempY + lTempHeight / 2;
                    }
                }
                pPointLeftTop.X = (int)lMemberLeftX;
                pPointLeftTop.Y = (int)lMemberTopY;
                pPointRightBottom.X = (int)lMemberRightX;
                pPointRightBottom.Y = (int)lMemberBottomY;
                lRtn = 0;
            }
            return lRtn;
        }

        //======================================
        // 表示関連メソッド
        //======================================

        /// <summary>
        /// <para>method outline:</para>
        /// <para>グループ要素検索</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>McGraphicsElement csGraphicsElement = SearchGroupElement(csID)</para>
        /// </example>
        /// <param name="csID">検索グループID</param>
        /// <returns>McGraphicsElement　グループ要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McGraphicsElement SearchGroupElement(HySIdentifier csID)
        {
            McGraphicsElement csSearchGroup = null;

            for (int iLp = 0; iLp < m_csElmList.Count; iLp++)
            {// グループ内要素数ループ
                if ((m_csElmList[iLp].GetSymbolDrawKind() == McDefine.SymbolDrawKind.HYM_GROUP) ||
                    (m_csElmList[iLp].GetSymbolDrawKind() == McDefine.SymbolDrawKind.HYM_CALC_GROUP))
                {// グループ要素の場合
                    if (m_csElmList[iLp].Equal(csID) == true)
                    {// 検索要素の場合
                        csSearchGroup = m_csElmList[iLp];
                        break;
                    }
                    csSearchGroup = ((McGraphicsGroupElement)m_csElmList[iLp]).SearchGroupElement(csID);
                    if (csSearchGroup != null)
                    {// 検索グループ要素があった場合
                        break;
                    }
                }
            }

            return csSearchGroup;
        }

        /// <summary>
        /// <para>method outline:</para>
        /// <para>要素情報検索</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>McGraphicsElement csElement = SearchElement(csElementID)</para>
        /// </example>
        /// <param name="csElementID">検索要素ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override McGraphicsElement SearchElement(HySIdentifier csElementID)
        {
            McGraphicsElement csElement = null;

            if (GetID().Equals(csElementID) == true)
            {// 自身が検索要素の場合
                csElement = this;
            }

            if (csElement == null)
            {// 自身が検索要素ではない場合
                for (int iLp = 0; iLp < m_csElmList.Count; iLp++)
                {// グループ内要素数ループ
                    csElement = m_csElmList[iLp].SearchElement(csElementID);
                    if (csElement != null)
                    {// 検索要素があった場合
                        break;
                    }
                }
            }

            if (csElement == null)
            {// 検索要素がない場合
                for (int iLp = 0; iLp < m_csLineList.Count; iLp++)
                {// グループ内接続線数ループ
                    if (m_csLineList[iLp].GetID().Equals(csElementID) == true)
                    {// 検索要素の場合
                        csElement = m_csLineList[iLp];
                        break;
                    }
                }
            }

            if (csElement == null)
            {// 検索要素がない場合
                for (int iLp = 0; iLp < m_csPortList.Count; iLp++)
                {// 端子数ループ
                    if (m_csPortList[iLp].GetID().Equals(csElementID) == true)
                    {// 検索要素の場合
                        csElement = m_csPortList[iLp];
                        break;
                    }
                }
            }

            return csElement;
        }


        // ================================================
        //   Undo/Redo用処理
        // ================================================
        /// <summary><para>method outline:</para>
        /// <para>ID設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetIDUsedByUndoRedoOnly(csID)</para>
        /// </example>
        /// <param name="csID">ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>GUIでのUndo/Redoのみ使用、その他は使用禁止</para>
        /// </remarks>
        public void SetIDUsedByUndoRedoOnly(HySIdentifier csID)
        {
            if (m_csViewerElm != null)
            {// 要素の場合
                ((McStructGroupElement)m_csViewerElm).SetIDUsedByUndoRedoOnly(csID);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>中継端子ID設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetPortIDUsedByUndoRedoOnly(csBeforeID, csAfterID)</para>
        /// </example>
        /// <param name="csBeforeID">現在のID</param>
        /// <param name="csAfterID">設定ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>GUIでのUndo/Redoのみ使用、その他は使用禁止</para>
        /// </remarks>
        public void SetPortIDUsedByUndoRedoOnly(HySIdentifier csBeforeID, HySIdentifier csAfterID)
        {
            if (m_csViewerElm != null)
            {// 要素の場合
                ((McStructGroupElement)m_csViewerElm).SetPortIDUsedByUndoRedoOnly(csBeforeID, csAfterID);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>情報のコピー</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McGraphicsElement csElement = CopyInfUsedByUndoRedoOnly(csCopyElement)</para>
        /// </example>
        /// <param name="csCopyElement">複製要素</param>
        /// <returns>McGraphicsElement 複製要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override McGraphicsElement CopyInfUsedByUndoRedoOnly(McGraphicsElement csCopyElement)
        {
            if (csCopyElement == null)
            {// 複製要素がない場合
                csCopyElement = new McGraphicsGroupElement(GetSymbolDrawKind());
            }

            base.CopyInfUsedByUndoRedoOnly(csCopyElement);

            for (int iLp = 0; iLp < m_csElmList.Count; iLp++)
            {// グループ内要素数ループ
                ((McGraphicsGroupElement)csCopyElement).m_csElmList.Add(m_csElmList[iLp].CopyInfUsedByUndoRedoOnly(null));
            }
            for (int iLp = 0; iLp < m_csLineList.Count; iLp++)
            {// グループ内接続線数ループ
                ((McGraphicsGroupElement)csCopyElement).m_csLineList.Add(m_csLineList[iLp].CopyInfUsedByUndoRedoOnly(null));
            }

            return csCopyElement;
        }
    }
}
